Newbie, created Word Clock, but time is not accurate (clock is slow)

Good day, I'm a newbie and wondering if someone might be able to help me with my word clock. The clock lights up all the right letters but the time is slow. I'm not really sure where to even start looking into this. I'm using an Elegoo Uno R3 board.

Here's a pic of my clock

Here's the word clock code:

/*

  Arduino + Neopixel Word Clock Code
  by: Alex - Super Make Something
  date: August 16, 2015
  license: Public domain.  Please use, reuse, and modify this sketch!
  additional: modified from "simple.ino" NeoPixel example sketch by Shae Erisson of Adafruit Industries.

  NOTE: REQUIRES NEOPIXEL & TIME LIBRARIES TO BE INSTALLED UNDER ...\Arduino\libraries
  NEOPIXEL LIBRARY AVAILABLE AT: https://github.com/adafruit/Adafruit_NeoPixel
  TIME LIBRARY AVAILABLE AT: https://github.com/PaulStoffregen/Time

  Explanation: This code lights up Neopixels corresponding to the current time.
  Time is kept using the time library.
  Neopixels are lit using the Adafruit Neopixel library.

  Depending on the current time, flags to light corresponding Neopixels are saved in an array
  After parsing the time, Neopixels are turned on/off according to the flags using a for loop

*/

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#include "TimeLib.h"

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN           3

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS     294

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

// Declare integer array with size corresponding to number of Neopixels in chain
// int individualPixels[NUMPIXELS];

//Declare pins for decrementing/incrementing current time by 5 minutes
#define MINUSFIVEMINS 4
#define PLUSFIVEMINS  5

//Declare pins for addition button 5V/GND sources
#define BUTTONLEDMINUS_GND1 8
#define BUTTONLEDMINUS_GND2 9
#define BUTTONLEDPLUS_GND1 10
#define BUTTONLEDPLUS_GND2 11

#define BUTTONLEDMINUS_5V1 A0
#define BUTTONLEDMINUS_5V2 A1
#define BUTTONLEDPLUS_5V1 A2
#define BUTTONLEDPLUS_5V2 A3

// Current and previous states for button pins -- in setup initialize all to HIGH
int minusPrevState = HIGH;
int minusCurrState = HIGH;
int plusPrevState = HIGH;
int plusCurrState = HIGH;

// Time variables
int h;
int m;
int s;

// RGB color variables
int red = 255;
int green = 255;
int blue = 255;



void setup()
{

  pinMode(MINUSFIVEMINS, INPUT_PULLUP); //Define pin as input, enable pull-up resistor
  pinMode(PLUSFIVEMINS, INPUT_PULLUP); //Define pin as input, enable pull-up resistor
  pinMode(BUTTONLEDMINUS_GND1, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDMINUS_GND2, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDPLUS_GND1, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDPLUS_GND2, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDMINUS_5V1, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDMINUS_5V2, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDPLUS_5V1, OUTPUT); //Define pin as output
  pinMode(BUTTONLEDPLUS_5V2, OUTPUT); //Define pin as output

  digitalWrite(BUTTONLEDMINUS_GND1, LOW); //Set pin value to LOW
  digitalWrite(BUTTONLEDMINUS_GND2, LOW); //Set pin value to LOW
  digitalWrite(BUTTONLEDPLUS_GND1, LOW); //Set pin value to LOW
  digitalWrite(BUTTONLEDPLUS_GND2, LOW); //Set pin value to LOW
  digitalWrite(BUTTONLEDMINUS_5V1, HIGH); //Set pin value to HIGH
  digitalWrite(BUTTONLEDMINUS_5V2, HIGH); //Set pin value to HIGH
  digitalWrite(BUTTONLEDPLUS_5V1, HIGH); //Set pin value to HIGH
  digitalWrite(BUTTONLEDPLUS_5V2, HIGH); //Set pin value to HIGH

  setTime(10, 21, 2, 30, 10, 2021); //Initialize current time as Midnight/noon 06/12/2020
  pixels.begin(); //Begin Neopixel string
  Serial.begin(9600); //Begin Serial for debugging purposes

}

void loop()
{

  //Declare integer array with size corresponding to number of Neopixels in chain
  int individualPixels[NUMPIXELS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

  /* Check for button presses & reset time if necessary */
  minusCurrState = digitalRead(MINUSFIVEMINS); //Get current state of MINUSFIVEMINS button
  /* If current state is different from previous state and value is now LOW, subtract five minutes from current time */
  if ((minusCurrState != minusPrevState) && (minusCurrState == LOW)) {
    adjustTime(-5 * 60); //Shift time five minutes backwards
    minusPrevState = minusCurrState;
  }
  else {
    minusPrevState = minusCurrState;
  }

  plusCurrState = digitalRead(PLUSFIVEMINS); //Get current state of PLUSFIVEMINS button
  /* If current state is different from previous state and value is now LOW, add five minutes from current time */
  if ((plusCurrState != plusPrevState) && (plusCurrState == LOW)) {
    adjustTime(5 * 60); //Shift time five minutes forwards
    plusPrevState = plusCurrState;
  }
  else {
    plusPrevState = plusCurrState;
  }

  /* Get current time */
  h = hourFormat12();  // Returns the hour of current time between 1-12
  m = minute();      // Returns the minute of current time
  s = second();      // Returns the second of current time (not used, included for completeness)

  Serial.print(h);
  Serial.print(":");
  Serial.print(m);
  Serial.print(":");
  Serial.println(s);

  /* Parse time values to light corresponding pixels */
  individualPixels[15] = 1; //Light "IS"
  individualPixels[16] = 1; //Light "IS"
  individualPixels[17] = 1; //Light "IS"
  individualPixels[18] = 1; //Light "IT"
  individualPixels[19] = 1; //Light "IS"
  individualPixels[20] = 1; //Light "IS"
  individualPixels[14] = 1; //Light "IS"



  /* Minutes between 0-5 - Light "O CLOC" */
  if ((m >= 0 && m < 5)) {
    individualPixels[288] = 1;
    individualPixels[287] = 1;
    individualPixels[286] = 1;
    individualPixels[285] = 1;
    individualPixels[284] = 1;
    individualPixels[283] = 1;
    individualPixels[282] = 1;
    individualPixels[281] = 1;
    individualPixels[280] = 1;
    individualPixels[279] = 1;
    individualPixels[278] = 1;
    individualPixels[277] = 1;
  }

  /* Minutes between 5-10 or 55-60 - Light "FIVE," "MINUTES" */
  if ((m >= 5 && m < 10) || (m >= 55 && m < 60)) {
    individualPixels[35] = 1;
    individualPixels[36] = 1;
    individualPixels[37] = 1;
    individualPixels[37] = 1;
    individualPixels[38] = 1;
    individualPixels[39] = 1;
    individualPixels[40] = 1;
    individualPixels[41] = 1;
    individualPixels[34] = 1;
    individualPixels[63] = 1; /* minutes */
    individualPixels[64] = 1;
    individualPixels[65] = 1;
    individualPixels[66] = 1;
    individualPixels[67] = 1;
    individualPixels[68] = 1;
    individualPixels[69] = 1;
    individualPixels[70] = 1;
    individualPixels[71] = 1;
    individualPixels[72] = 1;
    individualPixels[73] = 1;
    individualPixels[74] = 1;
    individualPixels[75] = 1;






  }

  /* Minutes between 10-15 or 50-55 - Light "TEN," "MINUTES" */
  if ((m >= 10 && m < 15) || (m >= 50 && m < 55)) {
    individualPixels[62] = 1; /* ten */
    individualPixels[61] = 1;
    individualPixels[60] = 1;
    individualPixels[59] = 1;
    individualPixels[58] = 1;

    individualPixels[63] = 1; /* minutes */
    individualPixels[64] = 1;
    individualPixels[65] = 1;
    individualPixels[66] = 1;
    individualPixels[67] = 1;
    individualPixels[68] = 1;
    individualPixels[69] = 1;
    individualPixels[70] = 1;
    individualPixels[71] = 1;
    individualPixels[72] = 1;
    individualPixels[73] = 1;
    individualPixels[74] = 1;
    individualPixels[75] = 1;


  }

  /* Minutes between 15-20 or 45-50 - Light "QUARTER" */
  if ((m >= 15 && m < 20) || (m >= 45 && m < 50)) {
    individualPixels[55] = 1;
    individualPixels[54] = 1;
    individualPixels[53] = 1;
    individualPixels[52] = 1;
    individualPixels[51] = 1;
    individualPixels[50] = 1;
    individualPixels[49] = 1;
    individualPixels[48] = 1;
    individualPixels[47] = 1;
    individualPixels[46] = 1;
    individualPixels[45] = 1;
    individualPixels[44] = 1;
    individualPixels[43] = 1;
    individualPixels[42] = 1;
    individualPixels[56] = 1;

  }

  /* Minutes between 20-25 or 40-45 - Light "TWENTY," "MINUTES" */
  if ((m >= 20 && m < 25) || (m >= 40 && m < 45)) {
    individualPixels[21] = 1; /*twenty */
    individualPixels[22] = 1;
    individualPixels[23] = 1;
    individualPixels[24] = 1;
    individualPixels[25] = 1;
    individualPixels[26] = 1;
    individualPixels[27] = 1;
    individualPixels[28] = 1;
    individualPixels[29] = 1;
    individualPixels[30] = 1;
    individualPixels[31] = 1;
    individualPixels[31] = 1;
    individualPixels[32] = 1;
    individualPixels[63] = 1; /* minutes */
    individualPixels[64] = 1;
    individualPixels[65] = 1;
    individualPixels[66] = 1;
    individualPixels[67] = 1;
    individualPixels[68] = 1;
    individualPixels[69] = 1;
    individualPixels[70] = 1;
    individualPixels[71] = 1;
    individualPixels[72] = 1;
    individualPixels[73] = 1;
    individualPixels[74] = 1;
    individualPixels[75] = 1;

  }

  /* Minutes between 25-30 or 35-40 - Light "TWENTY," "FIVE," "MINUTES" */
  if ((m >= 25 && m < 30) || (m >= 35 && m < 40)) {
    individualPixels[21] = 1; /*twenty */
    individualPixels[22] = 1;
    individualPixels[23] = 1;
    individualPixels[24] = 1;
    individualPixels[25] = 1;
    individualPixels[26] = 1;
    individualPixels[27] = 1;
    individualPixels[28] = 1;
    individualPixels[29] = 1;
    individualPixels[30] = 1;
    individualPixels[31] = 1;
    individualPixels[31] = 1;
    individualPixels[32] = 1;
    individualPixels[33] = 1;


    individualPixels[34] = 1; /* five*/
    individualPixels[35] = 1;
    individualPixels[36] = 1;
    individualPixels[37] = 1;
    individualPixels[38] = 1;
    individualPixels[39] = 1;
    individualPixels[40] = 1;
    individualPixels[41] = 1;


    individualPixels[63] = 1; /* minutes */
    individualPixels[64] = 1;
    individualPixels[65] = 1;
    individualPixels[66] = 1;
    individualPixels[67] = 1;
    individualPixels[68] = 1;
    individualPixels[69] = 1;
    individualPixels[70] = 1;
    individualPixels[71] = 1;
    individualPixels[72] = 1;
    individualPixels[73] = 1;
    individualPixels[74] = 1;
    individualPixels[75] = 1;



  }

  /* Minutes between 30-35 - Light "HALF" */
  if ((m >= 30 && m < 35)) {
    individualPixels[10] = 1;
    individualPixels[9] = 1;
    individualPixels[8] = 1;
    individualPixels[7] = 1;
    individualPixels[6] = 1;
    individualPixels[5] = 1;
    individualPixels[5] = 1;
    individualPixels[3] = 1;
    individualPixels[11] = 1;


  }

  /* Minutes between 5-35 - Light "PAST" */
  if ((m >= 5) && (m < 35)) {

    individualPixels[99] = 1;
    individualPixels[100] = 1;
    individualPixels[101] = 1;
    individualPixels[102] = 1;
    individualPixels[103] = 1;
    individualPixels[104] = 1;
    individualPixels[98 ] = 1;




  }

  /* Minutes between 35-60 - Light "TO" & MODIFY CURRENT HOUR VALUE */
  if (m >= 35) {
    individualPixels[80] = 1;
    individualPixels[81] = 1;
    individualPixels[82] = 1;
    individualPixels[83] = 1;
    individualPixels[79] = 1;


    h++; //Add 1 from current hour
    /*Set time to twelve for hour around midnight, noon */
    if (h == 0) {
      h = 12;
    }
    /*Corner case for 12:35-12:59 */
    if (h == 13) {
      h = 1;
    }
  }

  /* Hour=1 - Light "ONE" */
  if (h == 1) {
    individualPixels[109] = 1; /* one */
    individualPixels[108] = 1;
    individualPixels[107] = 1;
    individualPixels[106] = 1;
    individualPixels[105] = 1;



  }

  /* Hour=2 - Light "TWO" */
  if (h == 2) {

    individualPixels[111] = 1;
    individualPixels[112] = 1;
    individualPixels[113] = 1;
    individualPixels[114] = 1;
    individualPixels[115] = 1;


  }

  /* Hour=3 - Light "THREE" */
  if (h == 3) {
    individualPixels[94] = 1;
    individualPixels[93] = 1;
    individualPixels[92] = 1;
    individualPixels[91] = 1;
    individualPixels[90] = 1;
    individualPixels[89] = 1;
    individualPixels[88] = 1;
    individualPixels[87] = 1;
    individualPixels[86] = 1;
    individualPixels[85] = 1;
    individualPixels[84] = 1;

  }

  /* Hour=4 - Light "FOUR" */
  if (h == 4) {

    individualPixels[118] = 1;
    individualPixels[119] = 1;
    individualPixels[120] = 1;
    individualPixels[121] = 1;
    individualPixels[122] = 1;
    individualPixels[123] = 1;
    individualPixels[124] = 1;
    individualPixels[125] = 1;
    individualPixels[117] = 1;


  }

  /* Hour=5 - Light "FIVE" */
  if (h == 5) {

    individualPixels[133] = 1;
    individualPixels[132] = 1;
    individualPixels[131] = 1;
    individualPixels[130] = 1;
    individualPixels[129] = 1;
    individualPixels[128] = 1;
    individualPixels[127] = 1;
    individualPixels[126] = 1;





  }

  /* Hour=6 - Light "SIX" */
  if (h == 6) {
    individualPixels[215] = 1; /* six */
    individualPixels[214] = 1;
    individualPixels[213] = 1;
    individualPixels[212] = 1;
    individualPixels[211] = 1;
    individualPixels[210] = 1;

  }

  /* Hour=7 - Light "SEVEN" */
  if (h == 7) {
    individualPixels[189] = 1; /* seven */
    individualPixels[190] = 1;
    individualPixels[191] = 1;
    individualPixels[192] = 1;
    individualPixels[192] = 1;
    individualPixels[193] = 1;
    individualPixels[194] = 1;
    individualPixels[195] = 1;
    individualPixels[196] = 1;
    individualPixels[197] = 1;



  }

  /* Hour=8 - Light "EIGHT" */
  if (h == 8) {

    individualPixels[220] = 1;
    individualPixels[221] = 1;
    individualPixels[222] = 1;
    individualPixels[223] = 1;
    individualPixels[224] = 1;
    individualPixels[225] = 1;
    individualPixels[226] = 1;
    individualPixels[227] = 1;
    individualPixels[228] = 1;



  }

  /* Hour=9 - Light "NINE" */
  if (h == 9) {
    individualPixels[182] = 1;
    individualPixels[183] = 1;
    individualPixels[184] = 1;
    individualPixels[185] = 1;
    individualPixels[186] = 1;
    individualPixels[187] = 1;
    individualPixels[188] = 1;



  }

  /* Hour=10 - Light "TEN" */
  if (h == 10) {

    individualPixels[201] = 1;
    individualPixels[202] = 1;
    individualPixels[203] = 1;
    individualPixels[204] = 1;
    individualPixels[205] = 1;



  }

  /* Hour=11 - Light "ELEVEN" */
  if (h == 11) {
    individualPixels[180] = 1;
    individualPixels[179] = 1;
    individualPixels[178] = 1;
    individualPixels[177] = 1;
    individualPixels[176] = 1;
    individualPixels[175] = 1;
    individualPixels[174] = 1;
    individualPixels[173] = 1;
    individualPixels[172] = 1;
    individualPixels[171] = 1;
    individualPixels[170] = 1;
    individualPixels[169] = 1;
    individualPixels[168] = 1;


  }

  /* Hour=12 - Light "TWELVE" */
  if (h == 12) {
    individualPixels[268] = 1;
    individualPixels[267] = 1;
    individualPixels[266] = 1;
    individualPixels[265] = 1;
    individualPixels[264] = 1;
    individualPixels[263] = 1;
    individualPixels[262] = 1;
    individualPixels[261] = 1;
    individualPixels[260] = 1;
    individualPixels[259] = 1;
    individualPixels[258] = 1;


  }

  /* covid */
  individualPixels[154] = 2;
  individualPixels[155] = 2;
  individualPixels[156] = 2;
  individualPixels[157] = 2;
  individualPixels[158] = 2;
  individualPixels[159] = 2;
  individualPixels[160] = 2;
  individualPixels[161] = 2;
  individualPixels[162] = 2;
  individualPixels[163] = 2;
  individualPixels[164] = 2;
  individualPixels[165] = 2;

  /* 1830 */
  individualPixels[153] = 3;
  individualPixels[152] = 3;
  individualPixels[151] = 3;
  individualPixels[150] = 3;
  individualPixels[149] = 3;
  individualPixels[148] = 3;
  individualPixels[147] = 3;

  /* JM */

  individualPixels[239] = 3;
  individualPixels[240] = 3;
  individualPixels[241] = 3;

  /* SS */
  individualPixels[238] = 3;
  individualPixels[237] = 3;
  individualPixels[236] = 3;
  individualPixels[235] = 3;

  /* SS */

  /* JS */
  individualPixels[242] = 3;
  individualPixels[243] = 3;
  individualPixels[244] = 3;
  individualPixels[245] = 3;

  /* JS */
  individualPixels[242] = 3;
  individualPixels[243] = 3;
  individualPixels[244] = 3;
  individualPixels[245] = 3;

  /* KM */
  individualPixels[246] = 3;
  individualPixels[247] = 3;
  individualPixels[248] = 3;
  individualPixels[249] = 3;


  /* Light pixels corresponding to current time */
  for (int i = 0; i < sizeof(individualPixels); i++) {
    if (individualPixels[i] == 1) {
      pixels.setPixelColor(i, pixels.Color(255, 255, 255)); //Set Neopixel color
    }

    else if (individualPixels[i] == 2) {
      pixels.setPixelColor(i, pixels.Color(255, 0, 0)); //Set Neopixel color
    }

    else if (individualPixels[i] == 3) {
      pixels.setPixelColor(i, pixels.Color(0, 0, 0)); //Set Neopixel color
    }

    else {
      pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    }
  }

  pixels.show(); //Display Neopixel color

  //  /* Clear pixel values for re-assignment during next iteration */
  //  for (int j=0; j<sizeof(individualPixels); j++){
  //      individualPixels[j]=0; //Set array values to 0
  //      pixels.setPixelColor(j, pixels.Color(0,0,0)); //Set Neopixel color to 0 brightness, i.e. off
  //  }

}
1 Like

The Arduino internal clock is not very accurate. To get accurate time you need a way to update the Time library. Often this is a DS3231 Real-Time Clock (RTC) module. You could, alternatively, use a GPS receiver (which requires a view of the sky), or a network time server (which requires Ethernet or WiFi Internat access).

You could reduce the drift by calculating how often the clock drifts a second and adjusting the clock periodically.

Thank you for the help! Gees, I'm probably way in over my head here. lol What a shame because I love the look of this clock and I put a lot of work in to get to this point. The drift doesn't seem to be consistent. I'll have to do a lot more study into the RTC module as you suggested.

Please edit your post, select all code and click the </> button to apply so-called code tags and next save your post. It makes it easier to read, easier to copy and prevents the forum software from incorrect interpretation of the code (e.g. the italics in your code).

In this case however it easily pointed out that a lot of statements are commented out; e.g.

/* Minutes between 20-25 or 40-45 - Light "TWENTY," "MINUTES" */
if ((m >= 20 && m < 25) || (m >= 40 && m < 45)) {
individualPixels[21] = 1; /*twenty /
individualPixels[22] = 1;
individualPixels[23] = 1;
individualPixels[24] = 1;
individualPixels[25] = 1;
individualPixels[26] = 1;
individualPixels[27] = 1;
individualPixels[28] = 1;
individualPixels[29] = 1;
individualPixels[30] = 1;
individualPixels[31] = 1;
individualPixels[31] = 1;
individualPixels[32] = 1;
individualPixels[63] = 1; / minutes */

Pixels 22 to 32 and 63 are commented out.

Not the cause of the problem but just noticing and maybe it was on purpose.

Thanks for the heads up. :slight_smile:

I've order these guys. They should work right?

edit: actually I have one already! yay!

You are using TimeLib.h. There are various versions, so make sure you are using one that offers synching with an external RTC or network connection, for example Time Library, Timekeeping and Time/Date Manipulation on Teensy

If you want a genuine DS3231, avoid ordering cheap imitations from Amazon, Alibaba and the like. They are often counterfeit, reject or downright fakes. Reputable suppliers like Adafruit, Sparkfun, Digikey and Mouser offer the genuine item, and they support their products.

I use the DS3231 RTC in combination with a DCF77 Module (works great in Europe). The DCF time frequently synchronizes the RTC clock and the Arduino internal time is aligned with the RTC.

Thus, time is very accurate.

Note that the library you linked is invoked by including <TimeLib.h>, so the OP may already be using it.

You also have to be careful that you are getting a DS3231 and not a DS3231M, the M version uses a microelectromechanical systems (MEMS) resonator instead of a crystal, resulting an an accuracy of +/- 5ppm instead of +/- 2ppm.

I agree, however there are some really responsible companies selling there. For example, JY-MCU, Robodyne, DevEbox, and others. Most of those do supply pinouts and full schematics online, sometimes source code packages as well. When not, they will often supply it to you on purchase. The build quality of the good stuff is equal to the ones you mentioned, and their products reflect extensive R&D, they are not just cloning stuff.

1 Like

So I have an RTC module and I have it wired to the ardiuno. I have this code for the module. No idea how I plug this into my current code. lol

// Written by John Boxall from http://tronixstuff.com

#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );
}
void setup(){
  Wire.begin();
  Serial.begin(9600);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
  setDS3231time(30,42,16,5,13,10,16);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year){
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime(){
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10){
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10){
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:
    Serial.println("Sunday");
    break;
  case 2:
    Serial.println("Monday");
    break;
  case 3:
    Serial.println("Tuesday");
    break;
  case 4:
    Serial.println("Wednesday");
    break;
  case 5:
    Serial.println("Thursday");
    break;
  case 6:
    Serial.println("Friday");
    break;
  case 7:
    Serial.println("Saturday");
    break;
  }
}
void loop(){
  displayTime(); // display the real-time clock data on the Serial Monitor,
  delay(1000); // every second
}

Oh, come on. 3 minutes on a problem? Have some patience! That is just....

Unlikely to work in this case, because FastLED is blocking the interrupt for the millis counter, and then adjusting the millis count for its estimate of how much time was lost. That results in a highly inaccurate millis count.

Isn't that estimate based on the value of timer0, which isn't affected by disabling interrupts? Surely, that would allow you to make a very good estimate? At least, in theory?

hahaha! I plan on spending as much time on this as it takes!

Download and play with a good RTC library. The Sparkfun/Jeelabs one for example...

I've never looked at just how FastLED adjusts the millis count, but 294 LEDs will take 8.82mS to update, so it would need to be keeping track of each rollover of the timer, without using interrupts, and also adjusting the internal counter that the millis code used to determine when to adjust for the 1.024mS interrupt intervals.

Those would of course be included in my non-exhaustive list of "reputable suppliers".

Amazon could conceivably also be included, because they at least allow you to return the defective and counterfeit items for full refund.

Yeah, if the timer rolls over you have lost the time.

Have a look at the DS3232RTC library (note that is DS3232), it integrates with the Time library mentioned in reply #6 to synchronize the time with the RTC at 5 minute intervals (can be done more often). You should only need to change a line or two of code in setup, all the other time related functions remain unchanged.

Yes, with that arrangement, the only extra code you need is one line in setup to designate a time sync provider (the RTC).

It also lessens the burden if you want to use a different sync source later on.