Fastled wordclock dimming issue

Hi All,

I consider myself to be a noob when it comes to arduino programming. However i managed to take an English word clock code and convert it to Dutch language. Also i have spend quite a few days to add OTA and NTP functionality and make it work properly. I am aware that the code is by no means perfect, has incorrect formatting and is not 100% optimal. But so far it worked for me...

After running the code for a while i noticed there is a small bug, and i really can not seem to find the cause of the issue. For some reason the DimAll and LitAll functions do not always seem to run as intended.

Upon time change (every 5 minutes) the leds would start dimming, but would stop at +/-10% brightness. The LitAll function then takes off from that 10% value (if that makes sense) Unfortunately this behaviour is not the same for every time change. Most of the times the leds will fade down to 0, but sporadically they stop before that.

My first thought was that the Wemos must be performing other tasks at the same time, causing the interrupt. I have experimented with delays on various positions with diffent values but i can not seem to get rid of the problem. I would be more then pleased if someone can take a look at the code below:

#include <Arduino.h>
#include <Wire.h>
#include <FastLED.h>
#include <DS3231.h> //https://github.com/jarzebski/Arduino-DS3231
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <ESP8266mDNS.h>

#define bcd2dec(bcd_in) (bcd_in >> 4) * 10 + (bcd_in & 0x0f)
#define dec2bcd(dec_in) ((dec_in / 10) << 4) + (dec_in % 10)

#define LED_PIN     14
#define NUM_LEDS    110
#define BRIGHTNESS  80
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

const char* ssid = "iamnotpostingmyssid";
const char* password = "ormypassword";

DS3231 clock1;
RTCDateTime dt;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

byte mByte[0x03]; 
byte tByte[0x03]; 
const long gmtOffset = 7200;

int minutes;
int hours;
int CurrentTime[5];
int PreviousTime[4];

int Time_Comp[22][6]{ { 56, 57, 58,999,999,999},
                      { 44, 45, 46, 47,999,999},
                      { 51, 52, 53, 54,999,999},
                      { 40, 41, 42, 43,999,999},
                      { 36, 37, 38, 39,999,999},
                      { 33, 34, 35,999,999,999},
                      { 22, 23, 24, 25, 26,999},
                      { 18, 19, 20, 21,999,999},
                      { 28, 29, 30, 31, 32,999},
                      { 14, 15, 16, 17,999,999},
                      { 11, 12, 13,999,999,999},
                      {  0,  1,  2,  3,  4,  5},
                      { 73, 74, 75, 76,999,999}, 
                      { 95, 96, 97, 98,999,999},              
                      { 99,100,101,102,999,999}, 
                      { 88, 89, 90, 91,999,999}, 
                      { 77, 78, 79, 80, 81,999}, 
                      {  8,  9, 10,999,999,999},
                      { 66, 67, 68, 69,999,999},
                      {104,105,107,108,109,999},
                      { 84, 85, 86, 87,999,999}, 
                      { 62, 63, 64, 65,999,999}};

void LitAll(){
  for(int i=0;i<=80;i++){
  LEDS.setBrightness(i);  
  FastLED.show();
  delay(60);
  }
}

void DimAll(){
  for(int i=80;i>=0;i--){
  LEDS.setBrightness(i);
  FastLED.show();
  delay(60);
  }
}

void setup(){
  Serial.begin(9600);
  delay(500);
  Wire.begin();
  WiFi.begin(ssid, password);
  ArduinoOTA.begin();
  delay(5000);
   
  UpdateTime();
  
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(  BRIGHTNESS );
}

void loop() {
  ArduinoOTA.handle();
  
  WordTime();
  
  if (PreviousTime[0]!=CurrentTime[0] or PreviousTime[1]!=CurrentTime[1]) {
  DimAll();
  delay(1000);
   
  if (PreviousTime[0]!=99) for (int j=0;j<6;j++) leds[Time_Comp[PreviousTime[0]][j]]=CHSV( 0 , 0, 0); 
  if (PreviousTime[1]!=99) for (int j=0;j<6;j++) leds[Time_Comp[PreviousTime[1]][j]]=CHSV( 0 , 0, 0);
  if (PreviousTime[2]!=99) for (int j=0;j<6;j++) leds[Time_Comp[PreviousTime[2]][j]]=CHSV( 0 , 0, 0); 
  if (PreviousTime[3]!=99) for (int j=0;j<6;j++) leds[Time_Comp[PreviousTime[3]][j]]=CHSV( 0 , 0, 0);
  
  if (CurrentTime[0]!=99) for (int j=0;j<6;j++) leds[Time_Comp[CurrentTime[0]][j]]=CRGB::Blue;
  if (CurrentTime[1]!=99) for (int j=0;j<6;j++) leds[Time_Comp[CurrentTime[1]][j]]=CRGB::Blue;
  if (CurrentTime[2]!=99) for (int j=0;j<6;j++) leds[Time_Comp[CurrentTime[2]][j]]=CRGB::Blue; 
  if (CurrentTime[3]!=99) for (int j=0;j<6;j++) leds[Time_Comp[CurrentTime[3]][j]]=CRGB::Blue;
  if (CurrentTime[4]!=99) for (int j=0;j<6;j++) leds[Time_Comp[CurrentTime[4]][j]]=CRGB::Blue; 

  LitAll();
  UpdateTime();
  }
}

void getRTCdatetime(){
  Wire.beginTransmission (0x68);
  Wire.write (0x00); 
  Wire.endTransmission ();
  Wire.requestFrom(0x68, 0x03, true);
  int idx = 0;
   while(Wire.available()){
    byte input = Wire.read(); 
    mByte[idx] = input;    
    idx++;
   }
  Serial.print(F("Register[0] Seconds: ")); Serial.println(bcd2dec(mByte[0]));
  Serial.print(F("Register[1] Minutes: ")); Serial.println(bcd2dec(mByte[1]));
  Serial.print(F("Register[2] Hours:   ")); Serial.println(bcd2dec(mByte[2]));
  Serial.println("\n");
}
 
void UpdateTime(){
  timeClient.begin();
  timeClient.setTimeOffset(gmtOffset); 
  
  Serial.println(F("DS3231 register content...\n"));  
  getRTCdatetime();
  
  if (WiFi.status() == WL_CONNECTED) timeClient.update();

  unsigned long epochTime = timeClient.getEpochTime();  
  tByte[0] = (int)timeClient.getSeconds();  
  tByte[1] = (int)timeClient.getMinutes();  
  tByte[2] = (int)timeClient.getHours();  
 
  Serial.print(F("NTP Webtime...\n\n"));
  Serial.print("Seconds: "); Serial.println(tByte[0]);
  Serial.print("Minutes: "); Serial.println(tByte[1]);
  Serial.print("Hours:   "); Serial.println(tByte[2]);
  Serial.print("\n");

  if((mByte != tByte) and (WiFi.status() == WL_CONNECTED)){
    Wire.beginTransmission (0x68);
    Wire.write (0x00);
     for (int idx = 0; idx < 3; idx++){
       Wire.write (dec2bcd(tByte[idx]));
   }   
    Wire.endTransmission ();
    Serial.println(F("New DS3231 register content...\n"));  
    getRTCdatetime(); 
   }
}

void WordTime(){
  PreviousTime[0]=CurrentTime[0];
  PreviousTime[1]=CurrentTime[1];
  PreviousTime[2]=CurrentTime[2];
  PreviousTime[3]=CurrentTime[3];
  
  dt = clock1.getDateTime(); 
  minutes=int((dt.minute)/5)*5;
  if (minutes<20 and minutes>=0) hours=dt.hour ;else hours=dt.hour+1;
  if (minutes==0)                      {CurrentTime[0]=17;CurrentTime[1]=99;}
  if ((minutes==5)  or (minutes==55))  {CurrentTime[0]=14;CurrentTime[1]=99;}
  if ((minutes==10) or (minutes==50))  {CurrentTime[0]=15;CurrentTime[1]=99;}
  if ((minutes==15) or (minutes==45))  {CurrentTime[0]=16;CurrentTime[1]=99;}
  if ((minutes==20) or (minutes==40))  {CurrentTime[0]=15;CurrentTime[1]=18;}
  if ((minutes==25) or (minutes==35))  {CurrentTime[0]=14;CurrentTime[1]=18;}
  if (minutes==30)                     {CurrentTime[0]=18;CurrentTime[1]=99;}  
  if (minutes>= 5 and minutes<20)  CurrentTime[2]=12; 
  if (minutes>=20 and minutes<=29) CurrentTime[2]=13; 
  if (minutes>=30 and minutes<=34) CurrentTime[2]=99;
  if (minutes>=35 and minutes<=44) CurrentTime[2]=20; 
  if (minutes>=45 and minutes<=59) CurrentTime[2]=21; 
  if (minutes==0)   CurrentTime[2]=99;
  CurrentTime[3]=hours - int(hours/12)*12-1;
  CurrentTime[4]=19;
  if (CurrentTime[3]<0) CurrentTime[3]=CurrentTime[3]+12;
}

Pretty difficult to read your code.
I would like to suggest that you write some functions to get rid of all repetitive code.
Using this much delay in a clock code is not best practice. Better would be to use millis timers.
You have this ota handle in loop. Does that update your time via internet every loop? Maybe you can update time from ntp once in setup and then close this process. After all you have an RTC that should be reasonably accurate. I am not familiar with this wifi ota libraries, but it might use interrupts.

As far as i understand the coding, the IF statement in the loop is only true every 5 minutes.

The CurrentTime table and PreviousTime tables are compared, they only change every 5 minutes based on the code in the WordTime function. The delay inside that IF statement makes sure that after dimming, the leds stay off for that period of time.

The UpdateTime function updates the time, and is also placed inside the IF statement in the loop so it should also update once per 5 minutes. I have tried removing this update like you mention, so just in setup. But the dimming problem remains.

I will however remove the OTAhandle to see if that interferes somehow...

Edit: typos

Welcome to the forum.

The array with all the led settings is called "leds"

CRGB leds[NUM_LEDS];

But the functions LitAll() and DimAll() use "LEDS" with capitals. Does that even compile ?

A few notes:

  1. The Arduino IDE has a "auto format" to get the indents right. It is in the menu or with Arduino IDE 2.0 you can also use right-click and "Format Document". If you make the text layout look good, it is easier to find a bug.
  2. The DS3231 library by jarzebski has minor bugs when using the Wire library. Despite my Issue, he is hanging on to those bugs.
  3. You forgot to mention the source that you used for the clock.
  4. For a programmer/nerd it is easier to use the 'epoch' time or millis() and use that for all the timing. The way it is presented is just output. But if you want to compare the hours and minutes and everything and it works, that is fine.
  5. Have a look at TimeLib and TimeAlarms. If you want to set an alarm, then you can use that library.
  6. I would like to know more about the hardware. Do you have the protection resistor, the large capacitor and a power supply. How do the leds make a clock ?
  7. I did not check carefully the overall working of the sketch.

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