Another LED Aquarium Controller posts

So, i am still working on my LED controller using a few LEDs and a Meanwell dimmable driver, all controlled from an arduino Uno

below is a copy of my current Fading Code:

  #include <DS3231.h>
  DS3231 rtc(A4, A5); // define rtc pins
  Time  t; // Init time structure
  
const byte pwmLED = 9; // Define LED Pin


int StartHr = 19; //hour value to start
int StartMn = 02; //min value to start
 
 
// define directions for LED fade
#define UP 0
#define DOWN 1
 
// constants for min and max PWM
const int minPWM = 0;
const int maxPWM = 255;
 
// State Variable for Fade Direction
byte fadeDirection = UP;
 
// Global Fade Value
// but be bigger than byte and signed, for rollover
int fadeValue = 0;
 
// How smooth to fade?
byte fadeIncrement = 5;
 
// millis() timing Variable, just for fading
unsigned long previousFadeMillis;
 
// How fast to increment?
int fadeInterval = 500;
 
void setup() {
  pinMode (pwmLED,OUTPUT);
  analogWrite(pwmLED, fadeValue); // put pwmLED into known state (off)
  
  Serial.begin(9600);
  rtc.begin();
}
 
void doTheFade(unsigned long thisMillis) {
  
 
  
  // is it time to update yet?
  // if not, nothing happens
  if ((t.hour >= StartHr) && (t.min >= StartMn)&&(thisMillis - previousFadeMillis >= fadeInterval)) {
    
    if (fadeDirection == UP) {
      fadeValue = fadeValue + fadeIncrement;  
      if (fadeValue >= maxPWM) {
        // At max, limit and change direction
        Serial.print("Fade Complete");
      }
    } else {
      //if we aren't going up, we're going down
      fadeValue = fadeValue - fadeIncrement;
      if (fadeValue <= minPWM) {
        // At min, limit and change direction
        fadeValue = minPWM;
        fadeDirection = UP;
      }
    }
    // Only need to update when it changes
    analogWrite(pwmLED, fadeValue);  
 
    // reset millis for the next iteration (fade timer only)
    previousFadeMillis = thisMillis;
  }
}
 
void loop() {

// Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");  
// Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");
// Send time
  Serial.println(rtc.getTimeStr());

  // pointer to a time string
  char *strTime;
  // Get formatted Time 
  strTime = rtc.getTimeStr(FORMAT_LONG);
  t = rtc.getTime(); 

   
// The following lines can be uncommented to set the date and time
  //rtc.setDOW(TUESDAY);       // Set Day-of-Week to SUNDAY
  //rtc.setTime(19, 24, 00);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(11, 01, 2017);   // Set the date 

 
  // get the current time, for this time around loop
  // all millis() timer checks will use this time stamp
  unsigned long currentMillis = millis();
    
  doTheFade(currentMillis);
 
}

Excuse how messy it is! I will tidy it up soon

So, i took the millis approach to avoid Delays in my code, however i was wondering if there is a way to get the LEDs to power back on if it is within the set start and finish time

or example if at mid-day i needed to unplug the lights - when i plug it back in id like the arduino to boot and check the time, if its the right time the lights continue where they were in the cycle.

all suggestions will be welcomed!

Many thanks

Here is a sketch I wrote for someone else who was running four channels of LED for their aquarium. It calculates the time of day in seconds, then compares that current time to the fade-up and fade-down intervals for the various channels. It calculates the instantaneous brightness for each channel so it recovers immediately when reset.

It currently uses 2-hour fade-in and fade-out intervals (that’s what the poster wanted). It would not be hard to specify fade-in/-out start and end times for each channel. Just make sure none of the intervals cross midnight.

#include "Wire.h"
#define DS1307_ADDRESS 0x68  // This is the I2C address

const int Blue1Pin = 3;
const int Blue2Pin = 5;
const int White3Pin = 6;
const int White4Pin = 9;

const unsigned long HOUR = 60 * 60;
const unsigned long MINUTE = 60;

const int TARGET_BRIGHTNESS = (255 * 3) / 4;  // Target brightness is 3/4 of full

void setup() {
  Wire.begin();
}

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

void loop() {
  /////  Get time from RTC into RTCHour, RTCMinute, RTCSecond

  // Set the register pointer to 0 (Second)
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write((byte)0);
  Wire.endTransmission();

  //  Read Second, Minute, and Hour
  Wire.requestFrom(DS1307_ADDRESS, 3);

  int RTCSecond = bcdToDec(Wire.read());
  int RTCMinute = bcdToDec(Wire.read());
  int RTCHour = bcdToDec(Wire.read() & 0b111111); //24 hour time

  unsigned long time = RTCHour * HOUR + RTCMinute * MINUTE + RTCSecond;  // Time in seconds

  analogWrite(Blue1Pin,   brightness(time, 7 * HOUR,                 17 * HOUR));
  analogWrite(Blue2Pin,   brightness(time, 7 * HOUR + 30 * MINUTE,   16 * HOUR + 30 * MINUTE));
  analogWrite(White3Pin,  brightness(time, 8 * HOUR,                 15 * HOUR));
  analogWrite(White4Pin,  brightness(time, 9 * HOUR,                 14 * HOUR));

  delay(1000);
}

// Calculate brightness based on a 2 hour fade-up period starting at
// a specified time in the morning and a 2 hour fade-down period
// starting at a specified time in the evening.
byte brightness(unsigned long time, unsigned long fadeUpStart,
                unsigned long fadeDownStart) {
  //  Mid day, light is at maximum brightness
  if (time >= fadeUpStart + 2 * HOUR  && time <= fadeDownStart)
    return TARGET_BRIGHTNESS;

  // Dawn:  fade up the light
  if (time >= fadeUpStart && time <= fadeUpStart + 2 * HOUR) // Fading up
  {
    unsigned long seconds = time - fadeUpStart;  // Number of seconds into the fade time
    return TARGET_BRIGHTNESS * seconds / (HOUR * 2); // Fade up based on portion of interval completed.
  }

  // Evening: Fade down the light
  if (time >= fadeDownStart && time <= fadeDownStart + 2 * HOUR) // Fading down
  {
    unsigned long seconds = (fadeDownStart + (HOUR * 2)) - time; // Number of seconds remaining in the fade time
    return TARGET_BRIGHTNESS * seconds / (HOUR * 2); // Fade down based on portion of interval left.
  }

  // The remaining times are night and the lights is off
  return 0;
}

Thank you for your reply, i will look through it and try figure things out!
i did notice you have a delay in there? is that needed?

Many thanks!

The delay is not needed. The code will behave the same without it but will be repeating the decision making using the same data many times per second. That seemed somehow wasteful to me but is really no more wasteful than delay().