Arduino sketches

SWINGRRRR

Premium Member
I am starting this thread due to the fact that some of us have the hardware side of the LEDs and dimmers down. Now we really need to focus on the software. So please, hopefully some people with more experience will join in. Here are a couple of my sketches.

Random clouds: This one worked really well and is my favorite so far. The jumps happen so fast that its not huge "edges."
Code:
int led1Pin = 3;    // LED connected to digital pin 9
int led2Pin = 5;
int led3Pin = 6;
int led4Pin = 9;    // LED connected to digital pin 9
int led5Pin = 10;
int led6Pin = 11;
void setup(){}
void loop(){ 
int randNumber = random(100, 255);
int randTime = random (750, 1500);
analogWrite(led1Pin, randNumber); 
delay (randTime); 
analogWrite(led2Pin, randNumber); 
delay (randTime);  
analogWrite(led3Pin, randNumber); 
delay (randTime);  
analogWrite(led4Pin, randNumber); 
delay (randTime); 
analogWrite(led5Pin, randNumber); 
delay (randTime);  
}

All on: Pretty self explanatory
Code:
int led1Pin = 3;
int led2Pin = 5;
int led3Pin = 6;
int led4Pin = 9;    
int led5Pin = 10;
int led6Pin = 11;

void setup(){}
void loop(){ 
  analogWrite(led1Pin, 255);  
  analogWrite(led2Pin, 255); 
  analogWrite(led3Pin, 255); 
  analogWrite(led4Pin, 255); 
  analogWrite(led5Pin, 255);
  analogWrite(led6Pin, 255);
}

Clouds with dimming: This one worked ok. There was some blinking, which is obviously a timing issue. I am not using it really. Just something to share.
Code:
int led1Pin = 3;    
int led2Pin = 5;
int led3Pin = 6;
int led4Pin = 9;    
int led5Pin = 10;
int led6Pin = 11;
void setup()  {}
void loop() {
          // Pin 1
  for(int fade1Value = 35 ; fade1Value <= 255; fade1Value +=7) 
  { 
   analogWrite(led1Pin, fade1Value);            
   delay(10);                            
  } 
  for(int fade1Value = 255 ; fade1Value >= 55; fade1Value -=8) 
  { 
   analogWrite(led1Pin, fade1Value);         
   delay(15);                            
  }                      //Pin2
  for(int fade2Value = 35 ; fade2Value <= 255; fade2Value +=5) 
  { 
   analogWrite(led2Pin, fade2Value);         
   delay(15);                            
  } 
  for(int fade2Value = 255 ; fade2Value >= 40; fade2Value -=8) 
  { 
   analogWrite(led2Pin, fade2Value);         
   delay(15);                            
  }                      //Pin3
  for(int fade3Value = 45 ; fade3Value <= 255; fade3Value +=6) 
  { 
   analogWrite(led3Pin, fade3Value);         
   delay(13);                            
  } 
  for(int fade3Value = 255 ; fade3Value >= 50; fade3Value -=9) 
  { 
   analogWrite(led3Pin, fade3Value);         
   delay(15);       
  }                      //Pin4
  for(int fade4Value = 40 ; fade4Value <= 255; fade4Value +=8) 
  { 
   analogWrite(led4Pin, fade4Value);         
   delay(10);                            
  } 
  for(int fade4Value = 255 ; fade4Value >= 45; fade4Value -=5) 
  { 
   analogWrite(led4Pin, fade4Value);         
   delay(15);    
  }                      //Pin5
  for(int fade5Value = 70 ; fade5Value <= 255; fade5Value +=6) 
  { 
   analogWrite(led5Pin, fade5Value);         
   delay(10);                            
  } 
  for(int fade5Value = 255 ; fade5Value >= 40; fade5Value -=7) 
  { 
   analogWrite(led5Pin, fade5Value);         
   delay(15);    
  }                   //Pin 6
  for(int fade6Value = 20 ; fade6Value <= 255; fade6Value +=9) 
  { 
   analogWrite(led6Pin, fade6Value);         
   delay(10);                            
  } 
  for(int fade6Value = 255 ; fade6Value >= 40; fade6Value -=5) 
  { 
   analogWrite(led6Pin, fade6Value);         
   delay(15); 
}
}
 
This is a good idea for a thread. :thumbsup:

That random clouds one is neat. You could wrap all of that code into a function and then call it only when you want random clouds and do the same thing with your 'on' sketch. Then you could program it to switch between them using a button or automatically do it based on an RTC.

I think if you want to get the last one to work properly you are going to need to use one set of for loops and put all the analogWrite calls inside that only instead of just using vanilla fadeValue, you'll need to use some kind of algorythm in each one to change it up to how you want it.

something like:

Code:
for(int fadeValue = 1, fadeValue <= 255, fadeValue ++) {

analogWrite(led1Pin, fadeValue - 20);  //these can be manipulated in any way
analogWrite(led2Pin, fadeValue * .9);  //you want to achieve desired effect

}

for(int fadeValue = 255, fadeValue >= 1, fadeValue --){

//here you put the same code from the above for loop
}
 
Last edited:
You could wrap all of that code into a function and then call it only when you want random clouds and do the same thing with your 'on' sketch. Then you could program it to switch between them using a button or automatically do it based on an RTC.
Thats the plan, but that sketch is on my work laptop and I don't feel like going out and starting my car and all. Ill post it when I get a chance. Its pretty basic, just changes the state based on how many times the button is pushed.


I'm a real novice at the RTC, but I am reading all I can.

Edit: I forgot I have put it on arduino.cc so I just copy and paste it here. I know some of the pins are different than above, you just change them to whatever you are using. There will be 1 more state added for the "Day" program.
Code:
nt switchPin = 2;              // switch is connected to pin 2
const int led1Pin = 13;         // White 1 LED, etc, etc
const int led2Pin = 12;
const int led3Pin = 11;      
const int led4Pin = 10;      
const int led5Pin = 09;      
const int led6Pin = 08;              

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int lightMode = 0;              // What mode is the light in?

void setup() {
 pinMode(switchPin, INPUT);    // Set the switch pin as input
 pinMode(led1Pin, OUTPUT);     // LEDs to output
 pinMode(led2Pin, OUTPUT);
 pinMode(led3Pin, OUTPUT);
 pinMode(led4Pin, OUTPUT);
 pinMode(led5Pin, OUTPUT);
 pinMode(led6Pin, OUTPUT);
 
 Serial.begin(9600);           // Set up serial communication at 9600bps
 buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){
 val = digitalRead(switchPin);      // read input value and store it in val
 delay(10);                         // 10 milliseconds is a good amount of time
 val2 = digitalRead(switchPin);     // read the input again to check for bounces
 if (val == val2) {                 // make sure we got 2 consistent readings!
   if (val != buttonState) {          // the button state has changed!
     if (val == LOW) {                // check if the button is pressed
       if (lightMode == 0) {          // if its off
         lightMode = 1;               // turn whites on
       } else {
         if (lightMode == 1) {        // if whites are on
           lightMode = 2;             // then tuen blues on
         } else {
           if (lightMode == 2) {      // if blues are on
             lightMode = 3;           // make then turn all on
           } else {
        if (lightMode == 3) {     //  if all are on
               lightMode = 0;         // turn light off!
             }
                 }
         }
       }
     }
   }
   buttonState = val;                 // save the new state in our variable
 }

 // Now do whatever the lightMode indicates
 if (lightMode == 3) { // All off
   digitalWrite(led1Pin, LOW);
   digitalWrite(led2Pin, LOW);
   digitalWrite(led3Pin, LOW);
   digitalWrite(led4Pin, LOW);
   digitalWrite(led5Pin, LOW);
   digitalWrite(led6Pin, LOW);    
 }

 if (lightMode == 1) { // Whites on
   digitalWrite(led1Pin, HIGH);
   digitalWrite(led2Pin, HIGH);
   digitalWrite(led3Pin, HIGH);
   digitalWrite(led4Pin, LOW);
   digitalWrite(led5Pin, LOW);
   digitalWrite(led6Pin, LOW);
 }

 if (lightMode == 2) { // Blues on
   digitalWrite(led1Pin, LOW);
   digitalWrite(led2Pin, LOW);
   digitalWrite(led3Pin, LOW);    
   digitalWrite(led3Pin, HIGH);
   digitalWrite(led4Pin, HIGH);
   digitalWrite(led5Pin, HIGH);
   
 }
 if (lightMode == 0)  { // All On
   digitalWrite(led1Pin, HIGH);
   digitalWrite(led2Pin, HIGH);
   digitalWrite(led3Pin, HIGH);
   digitalWrite(led4Pin, HIGH);
   digitalWrite(led5Pin, HIGH);
   digitalWrite(led6Pin, HIGH);

 }
 
My scratchwork code is poorly organized and even more poorly written and documented, but I'll play.

A DS1307 example, if you don't want to use the new Time library:

Code:
/*
9-1-2009
DS1307 Example Sketch

//
This code implements a simple interface to a DS1307 RTC via I2C.

Two functions are included for translation of BCD:
  decToBcd() converts decimal numbers to binary coded decimal
  bcdToDec() converts binary coded decimal numbers to decimal

Two functions are included to communicate with the RTC:
  setDateDs1307() sets the date, time, etc. and starts the clock
  getDateDs1307() gets the date and time from the clock

*/

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// Convert decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Sets date and time, starts the clock
void setDate(byte second,        // 0-59
             byte minute,        // 0-59
             byte hour,          // 1-23
             byte dayOfWeek,     // 1-7
             byte dayOfMonth,    // 1-31
             byte month,         // 1-12
             byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time
void getDate(byte *second,
             byte *minute,
             byte *hour,
             byte *dayOfWeek,
             byte *dayOfMonth,
             byte *month,
             byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  // uncomment the next line if you need to set the clock.
  //   format is second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  //   once you have set the clock, comment this back out so you don't reset
  //   each time you upload
  // setDate(1, 1, 10, 1, 1, 9, 9);
}

void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  Serial.print(hour, DEC);
  Serial.print(":");
  Serial.print(minute, DEC);
  Serial.print(":");
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print("  Day_of_week:");
  Serial.println(dayOfWeek, DEC);

  delay(995);
}


If you just want two pots to control two channels of dimming. Put a pot on analog 0 for blues, and one on analog 1 for whites. Put blues on digital pin 5, and whites on 6:

Code:
int blueIn = 0;
int whiteIn = 1;
int blueOut = 5;
int whiteOut = 6;

void setup()
{
}

void loop()
{
  analogWrite(blueOut, map(analogRead(blueIn), 0, 1023, 0, 255));
  analogWrite(whiteOut, map(analogRead(whiteIn), 0, 1023, 0, 255));
}

This is close to my "most complete" LED sketch but the storm part isn't quite right. It fades three banks of LEDs on and off at set points, with definable "slopes" (i.e. how long it takes to fade on and off). Then, it's supposed to create random "storms" where the LEDs dim to simulate cloud cover, for a random length of time. The variables in that part of the sketch don't look right but it's been a few months since I played with this and I don't really remember:

Code:
/*
 Arduino controller for reef aquariums

//** Current Functionality
// paramterized LED lighting control for reef aquariums
// use a DS1307 RTC to kick off lighting schedules
// trigger a master pin "on" when the preset start time is reached
//   then, fade up on a given slope
//         delay a set amount
//         fade back down
//   such that the photoperiod lasts the correct amount of time

//** Functionality under development
//
// trigger "random" storms:
//   lights fade down from side to side to imitate cloud cover
//   during cloud cover, randomly strobe a bank of LEDs to imitate lightening
//   run wavemaker powerheads at higher-than-normal levels to simulate increased
//      wave action
//


//**  Circuit
// 
//  PWM pins described below connected to dimming circuits on drivers
// ledMaster pin below connected to a 120V AC relay to turn the LED drivers on and off
// grounds from drivers connected to arduino ground
// DS1307 RTC connected via I2C
//
//
//

 */

// Pins to control LEDs
int eastLed = 9;     // LED PWM channel for east end
int centerLed = 10;  // LED PWM channel for center
int westLed = 11;    // LED PWM channel for west end
int ledMaster = 8;   // Master channel to control LED powersupply

// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;

// Set up One Wire for single DS18S20 temp sensor
/*static const int ONE_WIRE_PIN = 8;
#include <DallasTemperature.h>
NewOneWire oneWire(ONE_WIRE_PIN);
DallasTemperature tempSensor(oneWire);
float temperature = 0;
*/
// Other variables. These control the behavior of lighting.
int minCounter = 0;         // counter that resets at midnight
int ledStartMins = 480;    // minute to start lights
int photoPeriod = 510;     // photoperiod in minutes
int photoStagger = 60;      // minutes to stagger photoperiods for each bank
long stormChance = 0;       // random number to generate storms
long storm = 0;             // minutes remaining in a storm
int noStorm = 0;            // minutes since the last storm happened
int stormFreq = 0;          // how frequently storms are allowed to happen
long stormLength = 0;        // base length for storms

void setup()  { 
  pinMode(ledMaster, OUTPUT);  // Set the LED master pin as output

// init I2C and One Wire  
  Wire.begin();
  Serial.begin(9600);
  //tempSensor.begin();

  // Change these values and uncomment to set RTC.
  // format is: second, minute, hour, dayOfWeek, dayOfMonth, month, year
  // setDateDs1307(10, 30, 18, 3, 22, 9, 9);
} 

/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins, int ledPin, int start, int period)  {
  if (mins > start && mins <= start + (period / 3) )  {
    analogWrite(ledPin, map(mins - start, 0, period/3, 0, 255));
  }
    if (mins > start + (period / 3) && mins <= start + 2*(period / 3))  {
    analogWrite(ledPin, 255);
  }
    if (mins > start + 2*(period / 3) && mins <= start + period)  {
    analogWrite(ledPin, map(mins - (start + 2*(period/3)), 0, (period/3), 255, 0));
  }
}

/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

/***** Main Loop ***********/
/***************************/
void loop()  { 
  // get time from RTC and put in hrs and mins variables
  getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
  minCounter = rtcHrs * 60 + rtcMins;
  //comment out these print commands to disable debugging
  Serial.print(rtcHrs, DEC);
  Serial.print(":");
  Serial.print(rtcMins, DEC);
  Serial.print(":");
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" ");
  Serial.print("Start At: ");
  Serial.print(ledStartMins);
  Serial.print(" Counter: ");
  Serial.print(minCounter);
  Serial.print(" End: ");
  Serial.println(ledStartMins + photoPeriod + 2*photoStagger);

  // determine if it is day or night, and act accordingly
  if (minCounter > ledStartMins && minCounter < ledStartMins + photoPeriod + 2*photoStagger)  {   //day
    // set LED states
    //digitalWrite(ledMaster, HIGH);
    setLed(minCounter, eastLed, ledStartMins, photoPeriod);
    setLed(minCounter, centerLed, ledStartMins + photoStagger, photoPeriod);
    setLed(minCounter, westLed, ledStartMins + 2*photoStagger, photoPeriod);
    // Determine if a storm should happen
    if (oldHrs < rtcHrs)  {
      stormChance = random(10);
    }
    if (oldMins < rtcMins)  {
      noStorm = noStorm + 1;
      if (storm > 0)  {
        storm = storm - 1;
      }
    }
    if (stormChance > 8 && noStorm > stormFreq)  {
      noStorm = 0;
      storm = stormLength + random(30);
    }

  }
  else  {   //night
    //digitalWrite(ledMaster, LOW);
    analogWrite(eastLed, 0);
    analogWrite(centerLed, 0);
    analogWrite(westLed, 0);
  }
    
  // Do some stuff with temperature probe
  /* temperature = tempSensor.getTemperature();     
  Serial.print(DallasTemperature::toFahrenheit(temperature)); // Use the inbuild Celcius to Fahrenheit conversion. Returns a float
  //Serial.print(temperature); // Print temp in C
  Serial.println("F\t");
  */
  // Get ready for next iteration of loop
  oldMins = rtcMins;
  oldHrs = rtcHrs;
  delay(1000);
}

A stripped down version, for two banks of LEDs fading on/off each day. This is probably a good starting point for people just getting in to it.

Code:
/*
 Arduino controller for reef aquariums

//** Current Functionality
// paramterized LED lighting control for reef aquariums
// use a DS1307 RTC to kick off lighting schedules
// trigger a master pin "on" when the preset start time is reached
//   then, fade up on a given slope
//         delay a set amount
//         fade back down
//   such that the photoperiod lasts the correct amount of time


//**  Circuit
// 
//  PWM pins described below connected to dimming circuits on drivers
// ledMaster pin below connected to a 120V AC relay to turn the LED drivers on and off
// grounds from drivers connected to arduino ground
// DS1307 RTC connected via I2C
//
//
//

 */

// Pins to control LEDs
int firstLed = 9;     // LED PWM channel for east end
int secondLed = 10;  // LED PWM channel for center

// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;

// Other variables. These control the behavior of lighting.
int minCounter = 0;         // counter that resets at midnight
int ledStartMins = 480;    // minute to start lights
int photoPeriod = 510;     // photoperiod in minutes
int photoStagger = 60;      // minutes to stagger photoperiods for each bank

void setup()  { 
  
// init I2C and One Wire  
  Wire.begin();
} 

/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins, int ledPin, int start, int period)  {
  if (mins > start && mins <= start + (period / 3) )  {
    analogWrite(ledPin, map(mins - start, 0, period/3, 0, 255));
  }
    if (mins > start + (period / 3) && mins <= start + 2*(period / 3))  {
    analogWrite(ledPin, 255);
  }
    if (mins > start + 2*(period / 3) && mins <= start + period)  {
    analogWrite(ledPin, map(mins - (start + 2*(period/3)), 0, (period/3), 255, 0));
  }
}

/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

/***** Main Loop ***********/
/***************************/
void loop()  { 
  // get time from RTC and put in hrs and mins variables
  getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
  minCounter = rtcHrs * 60 + rtcMins;

  // determine if it is day or night, and act accordingly
  if (minCounter > ledStartMins && minCounter < ledStartMins + photoPeriod + 2*photoStagger)  {   //day
    // set LED states
    //digitalWrite(ledMaster, HIGH);
    setLed(minCounter, firstLed, ledStartMins, photoPeriod);
    setLed(minCounter, secondLed, ledStartMins + photoStagger, photoPeriod);
  }
  else  {   //night
    analogWrite(firstLed, 0);
    analogWrite(secondLed, 0);
  }
    
  // Get ready for next iteration of loop
  oldMins = rtcMins;
  oldHrs = rtcHrs;
  delay(1000);
}
 
Last edited:
Yep:

http://arduino.cc/en/Reference/Map

You pass it a value, a "from" range, and a "to" range. It's handy for scaling (what I used it for in the second sketch above - scaling from 0-1024 analog input to 0-255 PWM output) and for things like inverting a range, i.e. if you had code written for a Meanwell and you wanted to use it on a buckpuck, which has an inverted dimming slope, you could just wrap each analog write's value with map(value,0,255,255,0).
 
I'm still trying to wrap my brain around your LED functions and exactly how they work. I remember you telling me to use the map function a while back, and I could never figure out how to implement it from the example code. Still quite confused about how that works!
 
I'm still trying to wrap my brain around your LED functions and exactly how they work. I remember you telling me to use the map function a while back, and I could never figure out how to implement it from the example code. Still quite confused about how that works!

I described it in the other Arduino thread here:

http://www.reefcentral.com/forums/showthread.php?t=1672428&page=6

Basically, imagine you have an event "a" and you want to repeat it every "x" amount of time. There are two ways to do this (warning: pseudo-simplified code). The first way is to do "a" then wait "x" length of time, then end the loop:

Code:
setup()
{
  
}

loop()
{
  event(a); //the event you want to do
  delay(x); //the amount you want to delay
}

That's the first way that comes to the mind of most people. Do the event, then set some delay. The problem is, your Arduino is just churning during that delay function - you can't do anything else (change a pump's speed, check temperature, check the state of a float switch, etc.)

The second way is to just let the loop keep looping, and somewhere in each iteration, check to see how much time has passed since the last iteration, then do "a" when "x" time has passed. You store the time that "a" last occurred, and compare that stored value to the current time, then do "a" if the difference is "x" or more:

Code:
int lastEventMillis = 0;

setup()
{
  
}

loop()
{
  if(millis() > lastEventMillis + x){
    event(a);
    lastEventMillis = millis();
  }
  
}

This is "better" because the processor only spends a couple of clock cycles each time through the loop, so it's free to do other things. In other words, it uses fewer resources but gives the same result.

The next trick is to extrapolate that out to something that you want to do "y" number of times in a row, or from time "t" to time "u" for instance. To do that, you'd also store a variable or a set of variables that help you keep track of where in that progression you were. Then, imagine that after so many instances of "a" occurring, we want to do "b" for the same number of instances. That's what my functions above do but it's a little obscure because I wrote it specifically for fading the LEDs on a certain curve based on real (absolute) time, instead of abstracting it and basing it on a millisecond counter like these examples. Imagine that "a" is "make the LEDs one step brighter" and "b" is "make the LEDs one step less bright."
 
yeah.. I understand all that.. but this

analogWrite(ledPin, map(mins - start, 0, period/3, 0, 255));

and his buddy :

analogWrite(ledPin, map(mins - (start + 2*(period/3)), 0, (period/3), 255, 0));

is really what is throwing me off..

you're great BTW.. i'm just a lost cause here.. too much :bum: and :beer: and :celeb1: and lets not forget :smokin: .. its just too much for my simple brain.. :lol:
 
Great idea for a thread, if i can find it i have some code for moon phase it needs to be run with the new time libary and rtc as its based on unix time so if the dates set right the phase should be right.
 
yeah.. I understand all that.. but this

analogWrite(ledPin, map(mins - start, 0, period/3, 0, 255));

I'm telling it to fade from 0 - 255 over the first third of the photoperiod.

analogWite() takes two arguments: pin and value. Pin refers to a PWM-capable pin. Value is a 0-255 integer.

So, I'm passing it ledPin for the pin.

For value, I'm passing it map(mins - start, 0, period/3, 0, 255))

Basically:

  • mins - start represents how far along the "fade" we are.
  • I want the fade to last from 0 to one third the photoperiod.
  • 0 - 255 is the range I want the output value to be in.
  • So, I map mins-start from 0 - 1/3 photoperiod to 0 - 255


    and his buddy :

    analogWrite(ledPin, map(mins - (start + 2*(period/3)), 0, (period/3), 255, 0));

    Same thing, in reverse! Fade from 255 to zero over the last third of the photoperiod.
 
Great idea for a thread, if i can find it i have some code for moon phase it needs to be run with the new time libary and rtc as its based on unix time so if the dates set right the phase should be right.

Please do. Ive seen some of your thread on arduino.cc. The last one about the moon phase (I have it bookmarked :D) you said you'd have to tweak it, but no updates since then.
 
Someone asked me about this sketch today:

A stripped down version, for two banks of LEDs fading on/off each day. This is probably a good starting point for people just getting in to it.

There are all sorts of problems in it and it's got some obscurities. Here it is cleaned up a bit. Plus added some comments near the section that you should change to alter the schedule and behavior of the dimming.

Code:
/*
 Arduino LED controller for reef aquariums

// paramterized LED lighting control for reef aquariums
// use a DS1307 RTC to kick off lighting schedules
//   fade up on a given slope
//         delay a set amount
//         fade back down
//   such that the photoperiod lasts the correct amount of time


//  Circuit
// 
// PWM pins described below connected to dimming circuits on drivers
// ledMaster pin below connected to a 120V AC relay to turn the LED drivers on and off (optional)
// grounds from drivers connected to arduino ground
// DS1307 RTC connected via I2C
//
//
//

*/

// Pins to control LEDs. Change these if you're using different pins.
int blueLed = 9;     // LED PWM channel for blues
int whiteLed = 10;   // LED PWM channel for whites

// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;

// Other variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0;         // counter that resets at midnight. Don't change this.
int blueStartMins = 480;    // minute to start blues. Change this to the number of minutes past
                            //    midnight you want the blues to start.
int whiteStartMins = 480;   // minute to start whites. Same as above.
int bluePhotoPeriod = 510;  // photoperiod in minutes, blues. Change this to alter the total
                            //    photoperiod for blues.
int whitePhotoPeriod = 510; // photoperiod in minutes, whites. Same as above.
int fadeDuration = 60;      // duration of the fade on and off for sunrise and sunset. Change
                            //    this to alter how long the fade lasts.
int blueMax = 255;          // max intensity for blues. Change if you want to limit max intensity.
int whiteMax = 255;         // max intensity for whites. Same as above.


/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins,    // current time in minutes
            int ledPin,  // pin for this channel of LEDs
            int start,   // start time for this channel of LEDs
            int period,  // photoperiod for this channel of LEDs
            int fade,    // fade duration for this channel of LEDs
            int ledMax   // max value for this channel
            )  {
  if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
  }
    if (mins > start + period && mins <= start + period - fade)  {
    analogWrite(ledPin, ledMax);
  }
    if (mins > start + period - fade && mins <= start + period)  {
    analogWrite(ledPin, map(mins - start + period - fade, 0, fade, ledMax, 0));
  }
}

/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers.
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

void setup()  { 
  
// init I2C  
  Wire.begin();
} 

/***** Main Loop ***********/
/***************************/
void loop()  { 
  // get time from RTC and put in hrs and mins variables
  getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
  minCounter = rtcHrs * 60 + rtcMins;

  // determine if it is day or night, and act accordingly
  if ((minCounter > blueStartMins || minCounter > whiteStartMins)
           && (minCounter < blueStartMins + bluePhotoPeriod || minCounter < whiteStartMins + whitePhotoPeriod))  {   //day
    // set LED states
    setLed(minCounter, blueLed, blueStartMins, bluePhotoPeriod, fadeDuration, blueMax);
    setLed(minCounter, whiteLed, whiteStartMins, whitePhotoPeriod, fadeDuration, whiteMax);
  }
  else  {   //night
    analogWrite(blueLed, 0);
    analogWrite(whiteLed, 0);
  }
    
  // Get ready for next iteration of loop
  delay(1000);
}
 
Reading this is the digital version of watching paint dry! LOL. I can't believe how far my programming days are behind me!
 
DZW, I was looking at the 2 LED sketch you posted. Im trying to expand it to fit 8 channels. Can I just add the ledPins, then put the stagger the time the photoperiod starts right? Just edit those times in minutes to start in later terms. Then it will pick up in the loop according to the RTC?
Also, what about making my "clouds" mid day. Again, can I just add a loop cloud and in the if ((minCounter > blueStartMins || minCounter > whiteStartMins), I can add a cloudStartMins. Then add an else //Clouds etc. I know Ill ahve to add all the other stuff as well, cloud duration, etc. Pretty much adding a thrid state for the main loop to be in.

Or am I completely off base?
 
Use that latest one I posted as a starting point, the earlier one(s) are kind of junky.

You should be able to add as many channels as you want, no problem. Just add the additional ledPin and other variables up top accordingly, and call the setLed function from the main loop for each channel.

To integrate clouds, you're probably going to want a big "if" statement in the middle of the main loop, such that it checks some status variable to determine if a cloud event is currently happening. If not, proceed with the code above (the setLed calls) as normal. If there is a cloud event going on right now, proceed with some other series of setLed statements, or something similar. You could even just make the same calls, but use a smaller number for the "max" for that channel - that would have the effect of just cutting a certain channel, but continuing the overall flow through the regular dimming for that day. Then after the if statement you'll want some logic to determine when the next cloud event will happen, how long it will be, etc.
 
Does this make any sense to add to the if?
Code:
""if (mins > start + period && mins <= start + period - fade)  {
    analogWrite(randPin, randNumber)
    delay (randTime);""
int randPin = random(1-8); //I know not exact pins, Ill have to look at my Mega and shield to get exact
int randTime = random (1500, 3500);
int randDim = random (85, 255) //Random dimming from 33% to 100%


Ill have to change the mins equation to figure out what time to run it at. How will the delay time mess with the RTC time if any?
 
OK, can y'all look over this. This is all 8 channels. You can add or delete as you need. Again, I am using the Mega, so YMMV. I got it to compile so I guess its something. I think I need to change the fade duration, but I am not sure with the 15 minute stagger. I know they are out of order, but thats for a reason so it will rise E->W and reverse.
The next thing Id like to add is a callDayofWeek. Im thinking maybe clouds on even days, full on the next. That way I don't have to figure out how to split the day up even more.
EDIT: Looking back over I think I need to lower the fadeDuration. Otherwise wont it take 8 hours just to fade up?
Code:
/*
//This was taken from DZW post above. I give credit to him, I just added and changed a couple of things. 

// Pins to control LEDs. Change these if you're using different pins.
int blue1Led = 3;     // LED PWM channel for blues
int blue2Led = 4;
int blue3Led = 5;
int blue4Led = 6;
int white1Led = 11;   // LED PWM channel for whites
int white2Led = 12; 
int white3Led = 13;
int white4Led = 14;

// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;

// Other variables. These control the behavior of lighting. Change these to customize behavior
int minCounter = 0;         // counter that resets at midnight. Don't change this.
int blue1StartMins = 480;    
int blue2StartMins = 495;
int blue3StartMins = 525;
int blue4StartMins = 555;    
int white1StartMins = 510;       
int white2StartMins = 540;
int white3StartMins = 570;
int white4StartMins = 585;   

int bluePhotoPeriod = 510;  
int whitePhotoPeriod = 510; // photoperiod in minutes, whites. Same as above.
int fadeDuration = 60;      // duration of the fade on and off for sunrise and sunset. 
int blueMax = 255;          // max intensity for blues. Change if you want to limit max intensity.
int whiteMax = 255;         // max intensity for whites. Same as above.

/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins,    // current time in minutes
            int ledPin,  // pin for this channel of LEDs
            int start,   // start time for this channel of LEDs
            int period,  // photoperiod for this channel of LEDs
            int fade,    // fade duration for this channel of LEDs
            int ledMax   // max value for this channel
            )  {
  if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
  }
    if (mins > start + period && mins <= start + period - fade)  {
    analogWrite(ledPin, ledMax);
  }
    if (mins > start + period - fade && mins <= start + period)  {
    analogWrite(ledPin, map(mins - start + period - fade, 0, fade, ledMax, 0));
  }
}

/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers.
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

void setup()  { 
  
// init I2C  
  Wire.begin();
} 

/***** Main Loop ***********/
/***************************/
void loop()  { 
  // get time from RTC and put in hrs and mins variables
  getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
  minCounter = rtcHrs * 60 + rtcMins;

  // determine if it is day or night, and act accordingly
  if ((minCounter > blue1StartMins || minCounter > white1StartMins)
           && (minCounter < blue1StartMins + bluePhotoPeriod || minCounter < white1StartMins + whitePhotoPeriod))  {   //day
    // set LED states
    setLed(minCounter, blue1Led, blue1StartMins, bluePhotoPeriod, fadeDuration, blueMax);
    setLed(minCounter, white1Led, white1StartMins, whitePhotoPeriod, fadeDuration, whiteMax);
    setLed(minCounter, blue2Led, blue2StartMins, bluePhotoPeriod, fadeDuration, blueMax);
    setLed(minCounter, white2Led, white2StartMins, whitePhotoPeriod, fadeDuration, whiteMax);
    setLed(minCounter, blue3Led, blue3StartMins, bluePhotoPeriod, fadeDuration, blueMax);
    setLed(minCounter, white3Led, white3StartMins, whitePhotoPeriod, fadeDuration, whiteMax);
    setLed(minCounter, blue4Led, blue4StartMins, bluePhotoPeriod, fadeDuration, blueMax);
    setLed(minCounter, white4Led, white4StartMins, whitePhotoPeriod, fadeDuration, whiteMax);
}
  else  {   //night
    analogWrite(blue1Led, 0);
    analogWrite(white1Led, 100);
    analogWrite(blue2Led, 0);
    analogWrite(white2Led, 100);
    analogWrite(blue3Led, 0);
    analogWrite(white3Led, 100);
    analogWrite(blue4Led, 0);
    analogWrite(white4Led, 100);
  }
    
  // Get ready for next iteration of loop
  delay(1000);
}
 
Last edited:
Back
Top