Fading LED using RTC

Hi there! I'm a new Arduino user and would like some guidance on how to fade a single LED using the DS1307 RTC. I currently have the LED connected and fading from brightness level 0 to 255.

Are there any examples where the LED begins to brighten and fade at specified times? For example, in the daytime, I would want the LED to be at full brightness while after 7PM, I would want for it to be at 0.

I'm such a noob at programming, so please go easy on me!
The Arduino I'm using is the Arduino Wifi Rev 2 and I'm using the DS1307 RTC from SparkFun!

Do you know how to get the hour from the RTC ?
I presume that you are using a library for the RTC. Does it have any examples with it ?

UKHeliBob:
Do you know how to get the hour from the RTC ?
I presume that you are using a library for the RTC. Does it have any examples with it ?

I think that's my biggest issue.

From a logical standpoint, I would assume to take the time from the RTC module and use that as reference for the LED. Upon doing research on this topic, I noticed there are many libraries available for the same module. That's a bit confusing.. How do I know what would be the best library to use for this module?

As you have a Sparkfun RTC you might just as well use their library DS1307 library

Okay! I managed to find a pretty good example on how to turn on/off the LED using set times. Great! This is a very important step for me.

I was able to wire up the Arduino with the LED and RTC module successfully.

My next step I’m trying to tackle is getting this LED to dim accordingly. I guess the best bet is to have the LED dim gradually until 11:00AM (a time I consider to be when there should be the most light) and have it stay on at brightness level 255 until 3:00PM. At that point, I’d like for it to gradually dim until 7:00PM and have it stay off until 6:00AM, every single day.

What is the best way to go about this?
Below is the code I’m using:

#include <TimeLib.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t

const int led = 9;

void setup() {
// prepare pin as output
pinMode(led, OUTPUT);
digitalWrite(led, LOW);

Serial.begin(9600);
// wait for Arduino Serial Monitor
while (!Serial) ;

// get and set the time from the RTC
setSyncProvider(RTC.get);
if (timeStatus() != timeSet)
Serial.println(“Unable to sync with the RTC”);
else
Serial.println(“RTC has set the system time”);

// To test your project, we can set the time manually by uncommenting bottom line
//setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

// create the alarms, to trigger functions at specific times
Alarm.alarmRepeat(3,35,0,MorningAlarm); // 9:00am every day
Alarm.alarmRepeat(3,34,0,EveningAlarm); // 19:00 → 7:00pm every day
}

void loop() {
digitalClockDisplay();
// wait one second between each clock display in serial monitor
Alarm.delay(1000);
}

// functions to be called when an alarm triggers
void MorningAlarm() {
// write here the task to perform every morning
Serial.println(“Turn light off”);
digitalWrite(led, LOW);
}
void EveningAlarm() {
// write here the task to perform every evening
Serial.println(“Turn light on”);
digitalWrite(led, HIGH);
}

void digitalClockDisplay() {
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}
void printDigits(int digits) {
Serial.print(":");
if (digits < 10)
Serial.print(‘0’);
Serial.print(digits);
}

Please post your code as described in Read this before posting a programming question

UKHeliBob:
Please post your code as described in Read this before posting a programming question

Yes sir! Sorry about that.

#include <TimeLib.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t

const int led = 9; 
int brightness = 0; // how bright the LED is
int fadeAmount = 1; // how many points to fade the LED by 

void setup() {
  // prepare pin as output
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  
  Serial.begin(9600);
  // wait for Arduino Serial Monitor
  while (!Serial) ; 
  
  // get and set the time from the RTC
  setSyncProvider(RTC.get);   
  if (timeStatus() != timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");     
  
  // To test your project, we can set the time manually by uncommenting bottom line
  //setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

  // create the alarms, to trigger functions at specific times
  Alarm.alarmRepeat(4,01,0,MorningAlarm);  // 9:00am every day
  Alarm.alarmRepeat(4,03,0,EveningAlarm);  // 19:00 -> 7:00pm every day
}

void loop() {
  // set the brightness of pin 9:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
  
  digitalClockDisplay();
  // wait one second between each clock display in serial monitor
  Alarm.delay(1000); 
}

// functions to be called when an alarm triggers
void MorningAlarm() {
  // write here the task to perform every morning
  Serial.println("Turn light on");
  digitalWrite(led, HIGH);
}
void EveningAlarm() {
  // write here the task to perform every evening
  Serial.println("Turn light off");
  digitalWrite(led, LOW);
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}
void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

I also want to mention that I feel like I’m pretty close. You see, I think somewhere in the loop, I have it messed up. I want the LED to be dimming/brightening gradually (so this portion would require some form of a loop). However, I want a conditional statement that would allow the LED to be a constant brightness for a certain time period. Then, when it’s time for the LED to dim and turn off, I would want this to occur for another time period. I’m so close but I can’t seem to wrap my finger around where or what.

Count (as in calculate based on current time) seconds from 6:00-11:00, that's 18,000 seconds, and then use the map() function to correlate that to the 0-255 range for the PWM. Likewise for the dimming in the evening.

Of note: if you want it to dim linearly to your eyes, it's a whole lot more complex than a linear PWM change. The first 50 points or so of the scale make the LED go to near half brightness, the next 200 or so for the second half. Your eyes are highly non-linear in response.

wvmarle:
Count (as in calculate based on current time) seconds from 6:00-11:00, that’s 18,000 seconds, and then use the map() function to correlate that to the 0-255 range for the PWM. Likewise for the dimming in the evening.

Of note: if you want it to dim linearly to your eyes, it’s a whole lot more complex than a linear PWM change. The first 50 points or so of the scale make the LED go to near half brightness, the next 200 or so for the second half. Your eyes are highly non-linear in response.

I’m sorry but this is the first time I’ve heard of map(). What good is it and are there any examples with LED lighting that utilizes this function?

PWM is the dimming part.
map() gives you the value for the analogWrite() function. See also the examples that come with the IDE.

wvmarle:
PWM is the dimming part.
map() gives you the value for the analogWrite() function. See also the examples that come with the IDE.

So for the code that I posted, am I not essentially writing a different value after each 30 ms delay? Why is the significance of the value generated by map() ?

I can't seem to find any examples from the Arduino IDE. Does this fall under a certain section I may be overlooking? The information I'm finding on Google doesn't seem to help much as it goes super deep into a different topic that uses map(). I'm sorry if I seem a bit slow on picking this up.

map() function reference

UKHeliBob:
map() function reference

Yes I have read this page. I'm sorry but I can't seem to understand how this would help.

Couldn't I use a while-loop to produce my desired outcome?

while loops are blocking, they have their place but not for handing a 18,000 second time range.

map() offers a very easy way to calculate a 0-255 PWM range based on a 0-18000 time range. Of course there are many other ways to do this.

If you want your LED's brightness change to look linear to the human eye, you'll have to roll your own function anyway.

wvmarle:
while loops are blocking, they have their place but not for handing a 18,000 second time range.

map() offers a very easy way to calculate a 0-255 PWM range based on a 0-18000 time range. Of course there are many other ways to do this.

If you want your LED’s brightness change to look linear to the human eye, you’ll have to roll your own function anyway.

Yeah I was able to get what I wanted out of an if/else statement. Can you explain to me why a while-loop would be bad for this type of situation?

Here’s my new code:

/*
 *
 * Complete project details at https://randomnerdtutorials.com    
 * Based on TimeAlarmExample from TimeAlarms library created by Michael Margolis
 *
 */

#include <TimeLib.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t

const int led = 9; 
int brightness = 0; // how bright the LED is
int fadeAmount = 1; // how many points to fade the LED by 
int targetbrightness = 255; // target brightness

void setup() {
  // prepare pin as output
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  
  Serial.begin(9600);
  // wait for Arduino Serial Monitor
  while (!Serial) ; 
  
  // get and set the time from the RTC
  setSyncProvider(RTC.get);   
  if (timeStatus() != timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");     
  
  // To test your project, we can set the time manually by uncommenting bottom line
  //setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

  // create the alarms, to trigger functions at specific times
  Alarm.alarmRepeat(6,00,0,MorningAlarm);  // 9:00am every day
  Alarm.alarmRepeat(19,00,0,EveningAlarm);  // 19:00 -> 7:00pm every day
}


void loop() {
  analogWrite(led, brightness);
  if (hour() >= 6 && hour()<= 11) {
    brightness = brightness + fadeAmount/18000;
  }
  else if (hour() > 11 && hour() <= 19) {
    brightness = brightness - fadeAmount/28800;
  }
  else { brightness = 0;
  }
  
  digitalClockDisplay();
  // wait one second between each clock display in serial monitor
  Alarm.delay(500); 
}

// functions to be called when an alarm triggers
void MorningAlarm() {
  // write here the task to perform every morning
  Serial.println("Turn light on");
  digitalWrite(led, HIGH);
}
void EveningAlarm() {
  // write here the task to perform every evening
  Serial.println("Turn light off");
  digitalWrite(led, LOW);
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}
void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

vutnguyen:
Yeah I was able to get what I wanted out of an if/else statement. Can you explain to me why a while-loop would be bad for this type of situation?

18,000 seconds and a while loop don't sound like a good combination. It may of course work for your particular application, doesn't make it pretty or so. Also I'm very much a proponent of instilling proper programming habits even for simple projects, such as writing non-blocking code, even if it's a bit more work now. It can save you heaps of time and frustration later: when your project has to do a second thing that's independent of that alarm, for example, but you don't realise that you're locked up in that loop blocking your program from doing the other thing.

Let loop() do the looping of anything that's more than a trivial amount of time. Check the seconds every time loop() loops. Try to finish each iteration of loop() as soon as possible - no blocking along the way, not even for half a second which is a very long time for a microcontroller.