Fade at specific time - help needed

Hi all,
I am working on an arduino project to control the light and monitor temperature in my aquarium.

I have an arduino UNO setup with a 16x2 LCD, DS3231 Real-time clock, DS18B20 one-wire temperature sensor and I will use a MOSFET from pin 10 to control the LED lights.

I have successfully got the LCD to display the correct time, date and temperature. But I am really stuck with a couple of things.

  1. I am unsure how to make the 2 loops in my code happen at specific times, for example I want the sunrise loop to happen at 9am and the sunset loop happen at 10pm. I know I need an "if" statement somewhere to check what hour it is and if it is 9am or later then it will execute the loop.

  2. I know how to fade an LED but I have no idea how to make the LED fade over a longer period of time. I want the LED to start off and fade all the way up to full brightness over the period of say 1 hour and remain there until it is time for sunset where I want the opposite to happen.

Is there anyone who can help with this?

My code so far is:

#include <DS3231.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal.h>

int lights = 10;

DS3231 rtc(SDA, SCL); // Init the DS3231 using the hardware interface
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte temp[8] = { //Temp Symbol
0b00100,
0b01010,
0b01010,
0b01110,
0b01110,
0b11111,
0b11111,
0b01110
};

#define ONE_WIRE_BUS 8 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup()
{
// Setup Serial connection
Serial.begin(4800);
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
pinMode(lights, OUTPUT);
lcd.clear(); //Clear the LCD Screen
lcd.createChar(0, temp); //Create temperature symbol
rtc.begin(); // Initialize the rtc object
sensors.begin();
// The following lines can be uncommented to set the date and time
//rtc.setDOW(SUNDAY); // Set Day-of-Week to SUNDAY
//rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format)
//rtc.setDate(15, 05, 2016); // Set the date to January 1st, 2014
}

void loop()
{
// Send Day-of-Week
lcd.setCursor(1, 0);
lcd.print(rtc.getDOWStr(FORMAT_SHORT)); //Send day of week to LCD
lcd.setCursor(7,0);
lcd.print(rtc.getDateStr(FORMAT_SHORT)); //Send date to LCD
lcd.setCursor(1, 1);
lcd.print(rtc.getTimeStr()); //Send time to LCD
lcd.setCursor(10,1);
lcd.write(byte(0)); //Print temperature symbol to LCD
lcd.setCursor(11, 1);
sensors.requestTemperatures(); //Get temperature from DS18B20
lcd.print(sensors.getTempCByIndex(0)); // Send temperature to LCD
lcd.setCursor(13, 1);
lcd.print((char)223); //Send "Degree" symbol to LCD
lcd.setCursor(14, 1);
lcd.print("C "); //Send C (Celsius) to LCD
delay (1000); // Wait one second before repeating
}

void sunrise()
{
//Code here to fade LED from 0 to 255
}

void sunset()
{
//Code here to fad LED from 255 to 0
}

Any help would be appreciated,
Thanks

I have been working on a home sentry system which includes monitoring two aquaria. It will monitor temperature, pump activity, nag me if I forget to feed them, and alter lighting as the day proceeds.

When it comes to fading the lights, I use a photoresistor, pointed at the window. It's resistance decreases as the outside light increases, so it can track daylight versus nighttime with no need for an internal schedule. Just set the photoresistor up in a voltage divider, analog read it on an analog pin, and use the resulting value to change the lighting. My LEDs are a neopixel strand, so I fade them to a low blue level for overnight.

The advantage of using the natural lighting cycle is that the fish, who may have some seasonal behaviors, get the cues from length of day. (I can't claim any expertise in this.)

You wont be able to call a separate "sunrise()" function because that would take an hour to return and you wouldn't be able to update the display during that time.

This is a task for doing several things at once. I suggest you start with the example "Blink without delay" sketch to get a feel for how it works.

The basic building block is something like

void loop {
   now=millis();

   if (now-last1>interval1) {
      // do task 1
      last1=now;
   }
   if (now-last2>interval2) {
      // do task 2
      last2=now;
   }

}

Although you might use the rtc clock instead.

rw950431:
You wont be able to call a separate "sunrise()" function because that would take an hour to return and you wouldn't be able to update the display during that time.

This is a task for doing several things at once. I suggest you start with the example "Blink without delay" sketch to get a feel for how it works.

The basic building block is something like

void loop {

now=millis();

if (now-last1>interval1) {
      // do task 1
      last1=now;
  }
  if (now-last2>interval2) {
      // do task 2
      last2=now;
  }

}




Although you might use the rtc clock instead.

So it's not possible?

I think I may have a solution, can I not use the interrupt feature in the DS3231 to trigger a pin on the arduino? That in turn can run a "fade without delay" function?

Would this work? Would it allow my clock to run without problems? Also can anyone point me in the right direction of fading the led over a set period of time?

Thanks

Its very possible.. Interrupts not required.

I dont really know the format of the rtc stuff so the code below wont actually compile but the logic goes something like

void loop() {

   if ( rtc.time is in daylight hours) {
      brightness=daylight_brightness
   } else  if ( rtc.time is in night hours) {
      brightness=night_brightness
   } else if ( rtc.time is in dusk) {
      brightness=map(rtc.minute,0,59,daylight_brightness,night_brightness)
   } else { // dawn
      brightness=map(rtc.minute,0,59,night_brightness,daylight_brightness)
   }
   
   set_brightness(brightness)
   // update LCD data panel etc

}

Obviously you need to supply values for the various time periods and brightness levels to suit.

rw950431:
Its very possible.. Interrupts not required.

I dont really know the format of the rtc stuff so the code below wont actually compile but the logic goes something like

void loop() {

if ( rtc.time is in daylight hours) {
      brightness=daylight_brightness
  } else  if ( rtc.time is in night hours) {
      brightness=night_brightness
  } else if ( rtc.time is in dusk) {
      brightness=map(rtc.minute,0,59,daylight_brightness,night_brightness)
  } else { // dawn
      brightness=map(rtc.minute,0,59,night_brightness,daylight_brightness)
  }
 
  set_brightness(brightness)
  // update LCD data panel etc

}




Obviously you need to supply values for the various time periods and brightness levels to suit.

Thank you so much for this, basically all i need to do now is figure out how to fade over a specific amount of time (1 hour) using fade without delay, and also how to check from the RTC what time it is and how to make it do what i need to do when it reaches the correct time.

if ( rtc.time is in daylight hours) {
brightness=daylight_brightness
} else if ( rtc.time is in night hours) {
brightness=night_brightness
} else if ( rtc.time is in dusk) {
brightness=map(rtc.minute,0,59,daylight_brightness,night_brightness)
} else { // dawn
brightness=map(rtc.minute,0,59,night_brightness,daylight_brightness)
}

So do I change the "daylight_brightness" and "night_brightness" to a percentage or a PWM value?

I really don't now how to check if it is daylight hours, dusk etc etc..

I want the lights to start fading on at 9am and be fully on at 10pm, then I want the lights to start fading off at 10pm and be fully off at 11pm.

Once i can get this working I can play around with the different times etc.

I really don't now how to check if it is daylight hours, dusk etc etc..

There are many examples on the internet, but if you already have the library, there should be examples that came with it.

.

My code so far is:

#include <DS3231.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include <Time.h>

int lights = 10;

DS3231 rtc(SDA, SCL); // Init the DS3231 using the hardware interface
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte temp[8] = { //Temp Symbol
0b00100,
0b01010,
0b01010,
0b01110,
0b01110,
0b11111,
0b11111,
0b01110
};

#define ONE_WIRE_BUS 8 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

byte Year;
byte Month;
byte Date;
byte DoW;
byte Hour;
byte Minute;
byte Second;

void setup()
{
// Setup Serial connection
Serial.begin(4800);
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
pinMode(lights, OUTPUT);
lcd.clear(); //Clear the LCD Screen
lcd.createChar(0, temp); //Create temperature symbol
rtc.begin(); // Initialize the rtc object
sensors.begin();
// The following lines can be uncommented to set the date and time
//rtc.setDOW(SUNDAY); // Set Day-of-Week to SUNDAY
//rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format)
//rtc.setDate(15, 05, 2016); // Set the date to January 1st, 2014
}

void loop()
{
if (hour() >= 10 ){
brightness=255 //Lights on full
}

else if (hour() >= 22 {
brightness=0 //Lights Fully off
}

else if (hour() >= 9 {
brightness=map(minute,0,59,daylight_brightness,night_brightness)
}

else {
brightness=map(minute,0,59,night_brightness,daylight_brightness)
}

set_brightness(brightness);

lcd.setCursor(1, 0);
lcd.print(rtc.getDOWStr(FORMAT_SHORT)); //Send day of week to LCD
lcd.setCursor(7,0);
lcd.print(rtc.getDateStr(FORMAT_SHORT)); //Send date to LCD
lcd.setCursor(1, 1);
lcd.print(rtc.getTimeStr()); //Send time to LCD
lcd.setCursor(10,1);
lcd.write(byte(0)); //Print temperature symbol to LCD
lcd.setCursor(11, 1);
sensors.requestTemperatures(); //Get temperature from DS18B20
lcd.print(sensors.getTempCByIndex(0)); // Send temperature to LCD
lcd.setCursor(13, 1);
lcd.print((char)223); //Send "Degree" symbol to LCD
lcd.setCursor(14, 1);
lcd.print("C "); //Send C (Celsius) to LCD
delay (1000); // Wait one second before repeating
}

I try to compile and I get the following error:

exit status 1
'brightness' was not declared in this scope

This is really frustrating me now. Tempted just to have a switch on the lights so I can turn them on and off.

Please help.

LarryD:
There are many examples on the internet, but if you already have the library, there should be examples that came with it.

.

I have looked everywhere for hours on the internet and found nothing even close to what I want and Yes I have the library but I have looked through all the examples and found nothing. Hence why I posted on here. I like to try and figure things out for myself but this time I am totally stuck and need help!

You have to define the 'brightness' variable before you use it.
Something like this: prior to setup(), or inside loop()

byte brightness; //global definition
void setup()
{
....
}

OR

void loop()
{
static byte brightness; //local definition
....
}

Where did you get the library from?

Use the </> icon (and the resulting code tags) to show us your sketches.

So my code is now:

#include <DS3231.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include <Time.h>

int lights = 10;

DS3231  rtc(SDA, SCL); // Init the DS3231 using the hardware interface
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte temp[8] = { //Temp Symbol
  0b00100,
  0b01010,
  0b01010,
  0b01110,
  0b01110,
  0b11111,
  0b11111,
  0b01110
};

#define ONE_WIRE_BUS 8 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);


byte Year;
byte Month;
byte Date;
byte DoW;
byte Hour;
byte Minute;
byte Second;
byte brightness; //global definition

void setup()
{
  // Setup Serial connection
  Serial.begin(4800);
  lcd.begin(16, 2); // set up the LCD's number of columns and rows:
  pinMode(lights, OUTPUT);
  lcd.clear(); //Clear the LCD Screen
  lcd.createChar(0, temp); //Create temperature symbol
  rtc.begin(); // Initialize the rtc object
  sensors.begin();
  // The following lines can be uncommented to set the date and time
  //rtc.setDOW(SUNDAY);     // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(15, 05, 2016);   // Set the date to January 1st, 2014
}

void loop()
{ 
  if (hour() >= 10 ){
  brightness=255 //Lights on full
  }
    
    else  if (hour() >= 22 {
    brightness=0 //Lights Fully off
    }
        
        else if (hour() >= 9 {
        brightness=map(minute,0,59,daylight_brightness,night_brightness)
        }
          
          else {
          brightness=map(minute,0,59,night_brightness,daylight_brightness)
          }
   
   set_brightness(brightness);
    
  lcd.setCursor(1, 0);
  lcd.print(rtc.getDOWStr(FORMAT_SHORT)); //Send day of week to LCD
  lcd.setCursor(7,0);
  lcd.print(rtc.getDateStr(FORMAT_SHORT)); //Send date to LCD
  lcd.setCursor(1, 1);
  lcd.print(rtc.getTimeStr()); //Send time to LCD
  lcd.setCursor(10,1);
  lcd.write(byte(0)); //Print temperature symbol to LCD
  lcd.setCursor(11, 1);
  sensors.requestTemperatures(); //Get temperature from DS18B20
  lcd.print(sensors.getTempCByIndex(0)); // Send temperature to LCD
  lcd.setCursor(13, 1);
  lcd.print((char)223); //Send "Degree" symbol to LCD
  lcd.setCursor(14, 1);
  lcd.print("C "); //Send C (Celsius) to LCD
  delay (1000); // Wait one second before repeating
}

I got the library from GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks

Thanks

If you are using that library:

#include <DS3231.h>
Change to:
#include <DS3232RTC.h> //GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks

Better still, see if Jack's example program runs on your system.
If it does, this will tells us if things are installed properly.

.

LarryD:
If you are using that library:

#include <DS3231.h>
Change to:
#include <DS3232RTC.h> //GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks

Better still, see if Jack's example program runs on your system.
If it does, this will tells us if things are installed properly.

DS3232RTC/examples/TimeRTC/TimeRTC.ino at master · JChristensen/DS3232RTC · GitHub

.

So I tried the TimeRTC sketch and it all compiled ok... Not sure how to use my sketch in that format now.

Any help?

Thanks

We assume you connected the RTC to the Arduino and that code displayed the time to the serial monitor.

You use hour() minute() second() to identify a time of day.

.

LarryD:
We assume you connected the RTC to the Arduino and that code displayed the time to the serial monitor.

You use hour() minute() second() to identify a time of day.

.

Sure did display the time in serial monitor..

So how would I put the code together? i have no idea... do i need byte hour, minute etc at the top before setup?

how do i actually call the hour? how do i see if that hour is sunrise, sunset etc etc etc.... i am getting nowhere here

Assume a 24 hour clock.
Something like this:
if(hour() == sunRiseHour && minute() == sunRiseMinute && second() == 0 ) // have we reached the sun rise time?
{
. . .
}

LarryD:
Assume a 24 hour clock.
Something like this:
if(hour() == sunRiseHour && minute() == sunRiseMinute && second() == 0 ) // have we reached the sun rise time?
{
. . .
}

Thats very helpful, could you look through my code below and see if I am on the right track?

/*
/*
 * TimeRTC.pde
 * Example code illustrating Time library with Real Time Clock.
 * This example is identical to the example provided with the Time Library,
 * only the #include statement has been changed to include the DS3232RTC library.
 */

#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
byte brightness; //global definition

void setup(void)
{
    Serial.begin(9600);
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() != timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time");      
}

void loop(void)
{
        if(hour() == 10&& minute() == 0 && second() == 0 ) // have we reached the sun rise time?
{
brightness=255; //Lights fully on
}
    else  if(hour() == 22 && minute() == 0 && second() == 0 ) 
{
brightness=0; //Lights Fully off
}
    else  if(hour() == 21 && minute() == 0 && second() == 0 )
{
brightness=map(minute(),0,59,255,0);
}
    else
{
brightness=map(minute(),0,59,0,255);
}
    digitalClockDisplay();  
    delay(1000);
}

void digitalClockDisplay(void)
{
    Serial.print(hour());  
    printDigits(minute());
    printDigits(second());
    Serial.print(' ');
    Serial.print(day());
    Serial.print(' ');
    Serial.print(month());
    Serial.print(' ');
    Serial.print(year()); 
    Serial.println(); 
}

void printDigits(int digits)
{
    // utility function for digital clock display: prints preceding colon and leading 0
    Serial.print(':');
    if(digits < 10)
        Serial.print('0');
    Serial.print(digits);
}

Thanks

What happened when you uploaded it?

.