BuckPuck/Arduino LED controller for reef aquariums

I have this working code below that i currently use on one of my aquariums to ramp on, hold and ramp off the lights with a 0 - 5v signal. Everything works great.

Now I am building a new set of lights and the drivers work opposite of my current drivers. I need 5v to turn them off and 0v for them to run at 100%. I tried changing my timing parameters so that they come on when the Arduino turns them off and visa versa. Issue is when the code turns them off (the lights are on) I loose my ability to adjust the brightness, cause the controller is at 0, thus the lights are at 100% and adjusting my ledMax does nothing (of course, cause they are off).

I'm sure I could do it with circuitry, but since it's already wired up code would be much easier.

/*
 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 togSwitch = 10;  // RTC Overide Switch
int blueLed = 3;     // LED PWM channel for blues
int whiteLed = 9;   // LED PWM channel for whites
int uvLed = 11;      // select the pin for the LED
int moonLed = 6;      // select the pin for the LED
int whitePot = A0;    // select the input pin for the potentiometer
int bluePot = A1;    // select the input pin for the potentiometer
int uvPot = A2;    // select the input pin for the potentiometer
int moonPot = A3;    // select the input pin for the potentiometer

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

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

// 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 = 420;    // minute to start blues. Change this to the number of minutes past
                            //    midnight you want the blues to start.
int whiteStartMins = 420;   // minute to start whites. Same as above.
int uvStartMins = 420;   // minute to start ultra violet. Same as above.
int moonStartMins = 1200;   // minute to start moon lights. Same as above.

int bluePhotoPeriod = 720;  // photoperiod in minutes, blues. Change this to alter the total
                            //    photoperiod for blues.
int whitePhotoPeriod = 720; // photoperiod in minutes, whites. Same as above.
int uvPhotoPeriod = 720; // photoperiod in minutes, ultra violets. Same as above.
int moonPhotoPeriod = 420; // photoperiod in minutes, moon lights. Same as above.
int fadeDuration = 120;      // duration of the fade on and off for sunrise and sunset. Change
                            //    this to alter how long the fade lasts.
int togState = 0;         // variable for reading the toggle switch status

/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three 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 <= mins > start + period)  {
    analogWrite(ledPin, 0);
  }
  if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
  }
    if (mins > start + fade && 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.write(0);
   Wire.write(decToBcd(second));
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(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.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

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

void setup()  { 
  
pinMode(togSwitch, INPUT);
  Wire.begin();
//  Serial.begin(9600);
} 

/***** 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;
  
//  Serial.println(second);
//  Serial.print("MinCount");
//  Serial.println(minCounter);     
  
int sensorValueb = analogRead (bluePot);
int blueMax = map (sensorValueb, 0, 1023, 0, 255);

int sensorValuew = analogRead (whitePot);
int whiteMax = map (sensorValuew, 0, 1023, 0, 255);

int sensorValueu = analogRead (uvPot);
int uvMax = map (sensorValueu, 0, 1023, 0, 255);

int sensorValuem = analogRead (moonPot);
int moonMax = map (sensorValuem, 0, 1023, 0, 255);
 
int togState = digitalRead(togSwitch);

if (psecond != second){ 
    psecond = second;}    

   if(togState == HIGH)
   {
     analogWrite(whiteLed, whiteMax);
     analogWrite(blueLed, blueMax);
     analogWrite(uvLed, uvMax);
     analogWrite(moonLed, moonMax);
   }

  else
   {
     setLed(minCounter, whiteLed, whiteStartMins, whitePhotoPeriod, fadeDuration, whiteMax);
     setLed(minCounter, blueLed, blueStartMins, bluePhotoPeriod, fadeDuration, blueMax);
     setLed(minCounter, uvLed, uvStartMins, uvPhotoPeriod, fadeDuration, uvMax);
     setLed(minCounter, moonLed, moonStartMins, moonPhotoPeriod, fadeDuration, moonMax);
   }
 
  delay(50);
}

Thanks in advance and if anybody is looking for a simple dawn to dusk LED controller with a separate moon light channel this works great.

I need 5v to turn them off and 0v for them to run at 100%.

So, the second argument to analogWrite() changes from n to 255 - n.

Issue is when the code turns them off (the lights are on) I loose my ability to adjust the brightness, cause the controller is at 0, thus the lights are at 100% and adjusting my ledMax does nothing (of course, cause they are off).

I didn't follow all that hand waving.

PaulS:

I need 5v to turn them off and 0v for them to run at 100%.

So, the second argument to analogWrite() changes from n to 255 - n.

Like this?

 {

if (mins <= start || mins <= mins > start + period)  {
    analogWrite(ledPin, 255);
  }
  if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start,- 0,- fade,- 0, - ledMax));
  }
    if (mins > start + fade && 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));
  }




The hand waving was my simple solution of turning them on when I want them off.

Like this?

No. Create a variable, n. Assign it a value. Use that in the analogWrite() call.

You had:

    analogWrite(ledPin, map(mins - start,- 0,- fade,- 0, - ledMax));

so,

   int n = map(mins - start,- 0,- fade,- 0, - ledMax);

Then,

   analogWrite(ledPin, 255 - n);

Like this?

No. Create a variable, n. Assign it a value. Use that in the analogWrite() call.

You had:

    analogWrite(ledPin, map(mins - start,- 0,- fade,- 0, - ledMax));

so,

   int n = map(mins - start,- 0,- fade,- 0, - ledMax);

Then,

   analogWrite(ledPin, 255 - n);

I tried all kinds of variations of that. I couldn't get it to work.

I tried all kinds of variations of that. I couldn't get it to work.

Post one of them. Describe what values you see for n. Describe what the code actually does. Of, buy all of us the same hardware you have, and send each of us a copy, so we can try it for ourselves.

Here is the modification that is the closest. The first 3 commands work as expected. Stage 1 - Light off. Stage 2 - Ramp to full. Stage 3 - Full Power. Stage 4 - dims, then brightens and goes back to full power (as it was written to do). I've modified it several ways and haven been able to get the results needed. So I posted it as It was originally written. I need the final line to take me back to 255 and not to zero. Just don't know how to map it.

 if (mins <= start || mins <= mins > start + period)  {
    analogWrite(ledPin, 255);  //Lights off before RTC starts them.
  }
    if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start, 0, fade, ledMax, 0)); // Ramp up to full power
    
  }
    if (mins > start + fade && mins <= start + period - fade)  {
    analogWrite(ledPin, ledMax -255);            // Full power
  }
    if (mins > start + period - fade && mins <= start + period)  {
    analogWrite(ledPin, map(mins - start - period + fade, 0, fade, ledMax, 0));  // Ramp down to off. This is the one that's broke
  }

I'll gladly send you a RTC, 10k Pot, 1/4w LED and a toggle. That's all I use to test it. In fact I have the toggle and the Pot bypassed currently to simplify the circuit. Pulled the LED and threw a meter on the pin output. Looking for 5v ramp to 0v, ramp back to 5v and stay that way till RTC says it's time to wake up and start over.

 if (mins <= start || mins <= mins > start + period)  {
    analogWrite(ledPin, 255);  //Lights off before RTC starts them.
  }

You started with a 0 as the 2nd argument. You changed that to 255 - 0, to get correct results. Why did you then abandon that pattern?

if (mins <= start || mins <= mins > start + period)  {

In the middle of that:

mins <= mins

When will mins not be <= mins?