Help Creating WS2812B Countdown Timer Strip (FastLED)

Hey All -

I've got a 4 year old who is supposed to stay in her room until a certain time when nap time is over, but not knowing how to tell time, asks over the monitor if it's time yet every minute or so. To try to remedy this, I'm wanting to take a WS2812B strip (~60 LEDs) with the following behavior:

  • All light up at a certain time
  • 1 LED goes out each minute (Would take an hour, obviously)
  • Optional Once time's up (LEDs are all off), they flash or do something fun

So far, I've got the code (below) to light up all 60 initially using red, yellow, & green as desired. When it comes to how to make one turn off each minute + implement the timing feature, I'm stuck. I've found some various code online which seems to relate, but am not having luck with it. Using a NodeMCU so implemented which is getting the correct time, too.

Any suggestions? Thanks!!

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN D1
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
#define BRIGHTNESS 60
#define VOLTS 5
#define MAX_AMPS 500

const char *ssid     = "XXXXXXXX";
const char *password = "XXXXXXXX";
const long utcOffsetInSeconds = -21600;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

CRGB leds[NUM_LEDS];

void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  timeClient.begin();

  FastLED.addLeds<CHIPSET,DATA_PIN,COLOR_ORDER>(leds,NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps (VOLTS,MAX_AMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();
}

void loop() {
  timeClient.update();
  Serial.println(timeClient.getFormattedTime());

  for (int i=0; i<10; i++) {
  leds[i] = CRGB::Red;
  }

  for (int i=10; i<20; i++) {
  leds[i] = CRGB::Yellow;
  }

  for (int i=20; i<60; i++) {
  leds[i] = CRGB::Green;
  }
FastLED.show();
delay(1000);

}

Hi
I liked your project, I'll see if I can help you.

That was fast - Thanks!

Why?

"Analog" clock?

Reading what I typed, I can see how that may look bad if that's what you're after, but isn't. She's only in there for 2 hours total and usually has to be woken up. If she comes out early, she awakens her 2 year old brother who is napping at the same time.

Yes, an analog might work; but why not make it something fun?

Hi
The project is well under way.
But I have some doubts:

  1. Why use NTP time?
  2. How will you set the 1 hour start time?

Hey -

I choose NTP because I want it to start daily at 2:30pm CST. I've got some RTCs, but didn't want to use extra hardware. I choose a NodeMCU over Arduino because I'd like to eventually evolve it to where a custom timer could be started via our phones if needed or at least be able to flash OTA initially.

Can't answer your second one as that's part of the reason I posted. Not sure how to set the time then make LEDs follow suite. Did find this project (video / code) which is similar to perhaps test code from, but the timing method seemed confusing plus not exactly what I'm after.

Same thought.

That library you are using, in addition to .getFormattedTime(), has .getHours() and .getMinutes(). This may be all you need.

You can calculate the minutes since midnight as timeClient.getHours()*60+timeClient.getMinutes(). Then subtract that from 15*60+30 to calculate how many minutes nap time are remaining. Over 60 means it's not nap time yet. Zero/negative means nap time is over. Use remaining minutes of nap-time to determine how many LEDs should be lit.

Hi @bzowk
Test it out with this code.
It starts at 14:30 pm and counts from 59 to 0.
From 59 to 40 in red, from 40 to 20 in yellow and from 20 to 0 in green.
When finished he is shown a rainbow of colors.

The LED strip is connected to D1 (GPIO5).

Then say the result.

// by RV mineirn

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

//                                                            https://github.com/FastLED/FastLED/wiki/ESP8266-notes
#define FASTLED_ESP8266_RAW_PIN_ORDER                         // Require for FastLed on ESP8266 put before <FastLED.h>
#define FASTLED_ESP8266_NODEMCU_PIN_ORDER                     // Require for FastLed on ESP8266 put before <FastLED.h>
#define FASTLED_ESP8266_D1_PIN_ORDER                          // Require for FastLed on ESP8266 put before <FastLED.h>
#include <FastLED.h>

#define NUM_LEDS 60
#define DATA_PIN D1
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
#define BRIGHTNESS 60
#define VOLTS 5
#define MAX_AMPS 500
const char *ssid     = "XXXXXXXXX";
const char *password = "XXXXXXXXX";
const long utcOffsetInSeconds = -21600;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
CRGB leds[NUM_LEDS];
int minNTP = 0;                                                     // Each minute
int hourNTP = 0;                                                    // Each hour
int lastminNTP = 0;                                                 // Previus minute
int timePass = 0;                                                   // Set incitial time
bool countDown = false;                                             // Controle countdown ou flash
uint8_t gHue = 0;                                                   // Rotating "base color"
//--------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);                                             // Inicialize Serial
  Serial.println("\n");                                             // New line
  WiFi.begin(ssid, password);                                       // Inicialize WIFI
  while ( WiFi.status() != WL_CONNECTED ) {                         // If not connected try again
    delay ( 500 );                                                  // Delay
    Serial.print ( "." );                                           // Print
  }
  timeClient.begin();                                               // Inicialize NCP time
  FastLED.addLeds<CHIPSET, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);  // Add LEDS
  FastLED.setMaxPowerInVoltsAndMilliamps (VOLTS, MAX_AMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  for (int i = 0; i < 60; i++) {                                    // Turn off all LEDs
    leds[i] = CRGB::Black;
  }
  FastLED.show();
}
//--------------------------------------------------------------------------
void loop() {
  String tempNTP;                                                   // Work variable

  timeClient.update();                                              // Refres NTP time
  tempNTP = timeClient.getFormattedTime().substring(0, 2);          // Split hour from time
  hourNTP = tempNTP.toInt();                                        // Transform in int
  //Serial.print(hourNTP); Serial.print(" ");
  tempNTP = timeClient.getFormattedTime().substring(3, 5);          // Split minutes from time
  minNTP = tempNTP.toInt();                                         // Transform in int
  //Serial.println(minNTP);
  if (countDown == true)                                            // If countdown is allowed
  {
    tempNTP = timeClient.getFormattedTime().substring(3, 5);        // Split minutes from time
    minNTP = tempNTP.toInt();                                       // Transform in int

    if (lastminNTP !=  minNTP)                                      // If pass 1 minute
    {
      lastminNTP = minNTP;                                          // Recharge control
      //Serial.print(minNTP); Serial.print(" ");                      // Print minute
      timePass--;                                                   // Countdown time
      if (timePass < 0)                                             // If time < 0
        timePass = 0;                                               // Time = 0
      if (timePass  == 0)                                           // If time finish
        countDown = false;                                          // Disable time countdown
      //Serial.println(timePass);                                     // Print time pass
      for (int i = 0; i < 60; i++) {                                // Turn off all LEDs
        leds[i] = CRGB::Black;
      }
      if (timePass >= 41)                                           // IF time > 41 minutes  (Seconds)
      {
        for (int i = 0; i < timePass; i++) {                        // Turn LEDS RED until minutes
          leds[i] = CRGB::Red;
        }
      }
      if (timePass >= 21 and timePass < 41 )                        // IF time > 21 minutes and < 41 (Seconds)
      {
        for (int i = 0; i < timePass; i++) {                        // Turn LEDS RED until Yellow
          leds[i] = CRGB::Yellow;
        }
      }
      if (timePass >= 0 and timePass < 21)                          // IF time > 0 minutes and < 21 (Seconds)
      {
        for (int i = 0; i < timePass; i++) {                        // Turn LEDS RED until green
          leds[i] = CRGB::Green;
        }
      }
      yield();
      FastLED.show();                                               // Show LEDs
      delay(100);
    }
  }
  if (countDown == false)                                           // If time ended  show rainbow
  {
    if (hourNTP == 14 and minNTP == 30)                             // If is time to countdown
    {
      countDown = true;                                             // Block bouncing
      timePass = 59;                                                // Charge countdown time
    }
    delay(200);                                                   
    for (int i = 0; i < 60; i++) {                                  // Show rainbow
      fadeToBlackBy( leds, NUM_LEDS, 1);
      leds[i] += CHSV( gHue++, 200, 180);
    }
    FastLED.show();
  }
}

Good Morning -

Wow - Thanks! Testing now...