LED Color changing according to time

Hello! I don't have any code to show because I can't even get one part of this working. For now, I'm looking for someone to point me to the right resources to learn what I need.

I want my WS2812B RGB 5050SMD light strip to

  1. turn on at a certain time to a predefined color (cRGB color codes here)
  2. change that color to another color at a certain time
  3. turn off at a certain time

I have an Adruino Uno R3 and a D3231. This seems like it's a super simple thing, but for the life of me I haven't been able to find anything to adapt. I did find WakeUpDarling code that a user here, LarryD, posted back in 2020, but I wasn't able to modify that in any meaningful way.

Edit: Using this as more of a record for other people to learn from me as I progress through the project. Answers and help are always appreciated, however.

Always show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.
Use the < CODE / > icon from the ‘posting menu’ to attach the copied sketch.

Might be better to rephrase- I’m looking for a starting point to learn what this code will look like. Maybe someone can advise/point me to something that shows how the ds3231 would be set up for a single event, or maybe some terms and tags I can read up on that would provide some progress.

Edit: LarryD, it was actually you who posted this way back when! It seemed the most promising jumping off point, so maybe it will fulfill the code requirement.


// WakeUpDarling!
// *Dedicated to my wife.
// License: MIT License
// Copyright (c) 2017 Niam Moltta 
// Downloaded from: https://circuits.io/circuits/3126865-wakeupdarling

#include <DS3231.h> //download if you don't have it yet.
#include <LiquidCrystal.h>

DS3231  rtc(SDA, SCL);
Time t;
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


void setup()
{
  // Setup Serial connection
  Serial.begin(115200);
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  rtc.begin();

  rtc.setTime(6, 59, 50);     // Set the real time for the module 
  //<hour, minutes, seconds> (24hr format)
  //rtc.setDate(1, 8, 2017);   // Uncomment to set the date to January 1st, 2014 (optional)
}

void loop()
{
  t = rtc.getTime();
 
  lcd.begin(16, 2);
  lcd.clear();
  // Send time
  lcd.setCursor(1,0);
  lcd.print("Wake up Darling");
  lcd.setCursor(0,1);
  lcd.print(t.hour, DEC);
  lcd.print("hrs ");
  lcd.print(t.min, DEC);
  lcd.print("min ");
  lcd.print(t.sec, DEC);
  lcd.print("sec");
  delay(1000);
  
  //set alarm:
 
  if (t.hour == 7 && t.min == 0) //time to wake up
  {
    digitalWrite (9, HIGH); //turns on coffee machine
  }
  if (t.hour == 9 && t.min == 0) //time to leave
  {
    digitalWrite (9, LOW); //turn off coffee machine
  }
  
}

Do you understand what the above does ?


If you do, what is the difference in these lines of code ?


  if (t.hour == 7 && t.min == 0 && t.sec == 0) //time to wake up
  {
    digitalWrite (9, HIGH); //turns on coffee machine
  }

I do. I see the second example has a more specific conditional to include the seconds, which, I imagine, will be important for my purposes.

In this specific code, I also notice that the ‘Time t;’ line doesn’t change color or seem to register as anything beyond normal text. Is it possible this would stop the code from getting the time or understand that variable?

‘Time t;’ line doesn’t change color

If you are referring to the colour of the letters shown in the Arduino IDE editor, colour means nothing to the compiler.

Understood. I’ll try writing up a sketch to turn on a single led tonight and post here. I’ve seen a few setups for the rtc, could you point me to a good one to learn from for this scenario?

There are plenty of "alarm clock" program examples for Arduino + DS3231 to study.

You will probably want a state variable to keep track of what the strip is supposed to be doing, and execute actions only when the time should lead to a change from one state and another. See the Arduino StateChangeExample code in Files>Examples> ...

Also look at DS3231 videos on YouTube, lots to learn from.

Excellent, thank you, those terms are very helpful. I’ll spend tomorrow looking in to this and come back when I have a decent sketch for it.

DronebotWorkshop does great work on many subjects. This one is on the RTC:

And Adafruit for the NeoPixel

I cut out as much as I could from the Adafruit code to show a complete example of the hours, minutes and seconds... feel free to make itook how you want.

Hello again!

So taking this step by step, I'm trying to get the time in the serial monitor to make sure that part is correct since everything else will be built on this. This code, when run, displays this in the serial monitor:

09:56:30.035 -> 
09:56:30.035 -> C:\Users\bryan\Ap
09:56:30.035 -> al\Temp\.arduinoIDE-unsaved202376-3680-gw8g0r.uhv8s\SetSerial\SetSerial.ino
09:56:30.035 -> Aug  6 2023 09:56:25
09:56:30.035 -> RTC Sync
09:56:30.035 -> 31Dec2095 00:03:53 
09:56:31.593 -> ,��n�>��ɗ�֙��@*����,��8҉����,������8҉

this is the code I'm currently running:

// Arduino DS3232RTC Library
// https://github.com/JChristensen/DS3232RTC
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
//
// Example sketch to display the date and time from a DS3231
// or DS3232 RTC every second. Display the temperature once per
// minute. (The DS3231 does a temperature conversion once every
// 64 seconds. This is also the default for the DS3232.)
//
// Set the date and time by entering the following on the Arduino
// serial monitor:
//  year,month,day,hour,minute,second,
//
// Where
//  year can be two or four digits,
//  month is 1-12,
//  day is 1-31,
//  hour is 0-23, and
//  minute and second are 0-59.
//
// Entering the final comma delimiter (after "second") will avoid a
// one-second timeout and will allow the RTC to be set more accurately.
//
// No validity checking is done, invalid values or incomplete syntax
// in the input will result in an incorrect RTC setting.
//
// Jack Christensen 08Aug2013

#include <DS3232RTC.h>      // https://github.com/JChristensen/DS3232RTC
#include <Streaming.h>      // https://github.com/janelia-arduino/Streaming
#include <TimeLib.h>
DS3232RTC myRTC;

void setup()
{
    Serial.begin(115200);
    Serial << F( "\n" __FILE__ "\n" __DATE__ " " __TIME__ "\n" );
    myRTC.begin();

    // setSyncProvider() causes the Time library to synchronize with the
    // external RTC by calling RTC.get() every five minutes by default.
    setSyncProvider(myRTC.get);
    Serial << F("RTC Sync");
    if (timeStatus() != timeSet) Serial << F(" FAIL!");
    Serial << endl;
}

void loop()
{
    static time_t tLast;
    time_t t;
    tmElements_t tm;

    // check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
    if (Serial.available() >= 12) {
        // note that the tmElements_t Year member is an offset from 1970,
        // but the RTC wants the last two digits of the calendar year.
        // use the convenience macros from the Time Library to do the conversions.
        int y = Serial.parseInt();
        if (y >= 100 && y < 1000)
            Serial << F("Error: Year must be two digits or four digits!") << endl;
        else {
            if (y >= 1000)
                tm.Year = CalendarYrToTm(y);
            else    // (y < 100)
                tm.Year = y2kYearToTm(y);
            tm.Month = Serial.parseInt();
            tm.Day = Serial.parseInt();
            tm.Hour = Serial.parseInt();
            tm.Minute = Serial.parseInt();
            tm.Second = Serial.parseInt();
            t = makeTime(tm);
            myRTC.set(t);   // use the time_t value to ensure correct weekday is set
            setTime(t);
            Serial << F("RTC set to: ");
            printDateTime(t);
            Serial << endl;
            // dump any extraneous input
            while (Serial.available() > 0) Serial.read();
        }
    }

    t = now();
    if (t != tLast) {
        tLast = t;
        printDateTime(t);
        if (second(t) == 0) {
            float c = myRTC.temperature() / 4.;
            float f = c * 9. / 5. + 32.;
            Serial << F("  ") << c << F(" C  ") << f << F(" F");
        }
        Serial << endl;
    }
}

// print date and time to Serial
void printDateTime(time_t t)
{
    printDate(t);
    Serial << ' ';
    printTime(t);
}

// print time to Serial
void printTime(time_t t)
{
    printI00(hour(t), ':');
    printI00(minute(t), ':');
    printI00(second(t), ' ');
}

// print date to Serial
void printDate(time_t t)
{
    printI00(day(t), 0);
    Serial << monthShortStr(month(t)) << _DEC(year(t));
}

// Print an integer in "00" format (with leading zero),
// followed by a delimiter character to Serial.
// Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
{
    if (val < 10) Serial << '0';
    Serial << _DEC(val);
    if (delim > 0) Serial << delim;
    return;
}

I entered the time in the serial monitor message bar according to the parameters laid out in the opening comments (at the time, it was 2023,8,6,09,56,30)

I'm expecting the time code to update every second on the serial monitor. Why am I getting just these initial ones with characters it wont recognize?

To anyone using this to try and learn for themselves, the problem with the above sketch was the baud rate. From what I can see, if you're getting strange characters in your serial monitor, check the baud rates first and play around with them.

How does your time output look?

As expected, thank you. Now it’s on to the LED part

Be sure to use an external power supply, a capacitor across the Vcc and GND of the Neopixel and a approximate 300 ohm resistor on the data pin addressed in Adafruit's Ueberguide. I'm prototyping a similar project for a business that will be a clock/sign in the manner of the "dark" clock above.

Working on putting the different parts of my sketch together into one. Still to go is adding the conditional section for timing and color, as well as a HSV to RGB function.

Edit: FastLED library does the conversion for you. See line 93 and note the CHSV tag before the paranthesis. This defines the color space and the library does the rest.

//Sketch for RGB lighting controlled by time of day

//includes parts of https://github.com/JChristensen/DS3232RTC Copyright (C) 2018 
//by Jack Christensen and licensed under GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html

//libraries needed
#include <DS3232RTC.h>
#include <Streaming.h>
#include <TimeLib.h>
#include <FastLED.h>

#define LED_PIN 6 //the data pin the strip is connected to 
#define NUM_LEDS 14 //the number of leds to light on the strip
DS3232RTC myRTC; //naming / defining the rtc variable
CRGB leds[NUM_LEDS]; //naming / defining the leds



void setup() {
  // put your setup code here, to run once:

  //this is the setup for the RTC module
      Serial.begin(9600);
    Serial << F( "\n" __FILE__ "\n" __DATE__ " " __TIME__ "\n" );
    myRTC.begin();

    // setSyncProvider() causes the Time library to synchronize with the
    // external RTC by calling RTC.get() every five minutes by default.
    setSyncProvider(myRTC.get);
    Serial << F("RTC Sync");
    if (timeStatus() != timeSet) Serial << F(" FAIL!");
    Serial << endl;

    //this is the setup for the RGB Strip
    FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
    FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
    FastLED.clear();
    FastLED.show();
}

void loop()
{
    static time_t tLast;
    time_t t;
    tmElements_t tm;

    // check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
    if (Serial.available() >= 12) {
        // note that the tmElements_t Year member is an offset from 1970,
        // but the RTC wants the last two digits of the calendar year.
        // use the convenience macros from the Time Library to do the conversions.
        int y = Serial.parseInt();
        if (y >= 100 && y < 1000)
            Serial << F("Error: Year must be two digits or four digits!") << endl;
        else {
            if (y >= 1000)
                tm.Year = CalendarYrToTm(y);
            else    // (y < 100)
                tm.Year = y2kYearToTm(y);
            tm.Month = Serial.parseInt();
            tm.Day = Serial.parseInt();
            tm.Hour = Serial.parseInt();
            tm.Minute = Serial.parseInt();
            tm.Second = Serial.parseInt();
            t = makeTime(tm);
            myRTC.set(t);   // use the time_t value to ensure correct weekday is set
            setTime(t);
            Serial << F("RTC set to: ");
            printDateTime(t);
            Serial << endl;
            // dump any extraneous input
            while (Serial.available() > 0) Serial.read();
        }
    }

    t = now();
    if (t != tLast) {
        tLast = t;
        printDateTime(t);
        if (second(t) == 0) {
            float c = myRTC.temperature() / 4.;
            float f = c * 9. / 5. + 32.;
            Serial << F("  ") << c << F(" C  ") << f << F(" F");
        }
        Serial << endl;
    }

    {

  //Set the RGB lighting
  // RED Green Blue
for (int i=0; i<NUM_LEDS; i++ )
leds[i] = CHSV(0, 0, 0 ); //in HSV form
FastLED.show();
  }
}

// print date and time to Serial
void printDateTime(time_t t)
{
    printDate(t);
    Serial << ' ';
    printTime(t);
}

// print time to Serial
void printTime(time_t t)
{
    printI00(hour(t), ':');
    printI00(minute(t), ':');
    printI00(second(t), ' ');
}

// print date to Serial
void printDate(time_t t)
{
    printI00(day(t), 0);
    Serial << monthShortStr(month(t)) << _DEC(year(t));
}

// Print an integer in "00" format (with leading zero),
// followed by a delimiter character to Serial.
// Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
{
    if (val < 10) Serial << '0';
    Serial << _DEC(val);
    if (delim > 0) Serial << delim;
    return;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.