cguy450

Binary Clock on ESP32 UNO - Code

Jul 2nd, 2025
43
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 40.03 KB | Source Code | 0 0
  1. // Binary Clock Shield for Arduino by Marcin Saj https://nixietester.com
  2. // https://github.com/marcinsaj/Binary-Clock-Shield-for-Arduino
  3. //
  4. // Binary Clock RTC 24H with Interrupt, Alarm and Buttons Example
  5. // This example demonstrates complete Binary Clock with Time and Alarm settings
  6. //
  7. // *It is recommended that the first start should be carried out with the serial terminal,
  8. // for better knowing the setting options.
  9. //
  10. // The buttons allows you to set the time and alarm - exact hour, minute, second/alarm status.
  11. // Alarm causes melody to play.  
  12. // How to use piezo with the tone() command to generate notes you can find here:
  13. // http://www.arduino.cc/en/Tutorial/Tone
  14. //
  15. // A falling edge at the RTC INT/SQW output causes an interrupt,
  16. // which is uses for regular - 1 per second - reading time from RTC and
  17. // checking alarm status flag 'A2F'. Since we use RTC INT/SQW output for
  18. // regular reading current time - square wave output SQW option,
  19. // global interrupt flag INTCN is set to 0, this disables the interrupts from both RTC alarms.
  20. // Referring to the documentation: when the INTCN is set to logic 0,
  21. // the 'A2F' bit does not initiate an interrupt signal. By turning off the interrupts from the alarms,
  22. // we can use the interrupt flag 'A2IE' as an info flag whether the alarm has been activated or not.
  23. // Check RTC datasheet page 11-13 http://bit.ly/DS3231-RTC
  24. //
  25. // Hardware:
  26. // Arduino Uno, Binary Clock Shield for Arduino
  27. // Battery CR1216/CR1220
  28. // INT/SQW   connected to Arduino pin 3  INT1 ESP32_D1-R32 UNO 25
  29. // PIEZO     connected to Arduino pin 11 PWM  ESP32_D1-R32 UNO 23
  30. // S3 button connected to Arduino pin A0      ESP32_D1-R32 UNO  2
  31. // S2 button connected to Arduino pin A1      ESP32_D1-R32 UNO  4
  32. // S1 button connected to Arduino pin A2      ESP32_D1-R32 UNO 35
  33. // LEDs      connected to Arduino pin A3      ESP32_D1-R32 UNO 34
  34. // RTC SDA   connected to Arduino pin A4      ESP32_D1-R32 UNO 36
  35. // RTC SCL   connected to Arduino pin A5      ESP32_D1-R32 UNO 39
  36. //
  37. //                        +------+       +------+       +------+       +------+       +------+
  38. //                        |LED 16|---<---|LED 15|---<---|LED 14|---<---|LED 13|---<---|LED 12|--<-+
  39. //                        +------+       +------+       +------+       +------+       +------+    |
  40. //                                                                                                |
  41. //    +--------------->-------------->-------------->-------------->-------------->---------------+
  42. //    |
  43. //    |    +------+       +------+       +------+       +------+       +------+       +------+
  44. //    +----|LED 11|---<---|LED 10|---<---|LED 09|---<---|LED 08|---<---|LED 07|---<---|LED 06|--<-+
  45. //         +------+       +------+       +------+       +------+       +------+       +------+    |
  46. //                                                                                                |
  47. //    +--------------->-------------->-------------->-------------->-------------->---------------+
  48. //    |
  49. //    |    +------+       +------+       +------+       +------+       +------+       +------+
  50. //    +----|LED 05|---<---|LED 04|---<---|LED 03|---<---|LED 02|---<---|LED 01|---<---|LED 0 |--<-- DATA_PIN
  51. //         +------+       +------+       +------+       +------+       +------+       +------+
  52.  
  53. #include <FastLED.h>            // https://github.com/FastLED/FastLED
  54. #include <DS3232RTC.h>          // https://github.com/JChristensen/DS3232RTC
  55. #include <Streaming.h>          // https://github.com/janelia-arduino/Streaming                            
  56. #include "pitches.h"            // Need to create the pitches.h library: https://arduino.cc/en/Tutorial/ToneMelody
  57.  
  58. #define DEBUG         1         // If 1 - serial debug ON, if 0 serial debug OFF  
  59.  
  60. // #define INT           3         // Interrupt. Arduino pin no.3 <-> Shield RTC INT/SQW pin          
  61. // #define PIEZO         11        // The number of the Piezo pin
  62. // #define LED_PIN       A3        // Data pin that LEDs data will be written out over
  63.  
  64. // #define S1  A2                  // Push buttons connected to the A0, A1, A2 Arduino pins
  65. // #define S2  A1    
  66. // #define S3  A0
  67.  
  68. #define INT          25        // Interrupt. Arduino pin no.3 <-> Shield RTC INT/SQW pin          
  69. #define PIEZO        23        // The number of the Piezo pin
  70. #define LED_PIN      34        // Data pin that LEDs data will be written out over
  71. #define DATA_PIN     34        // SPI MISO Data pin
  72. // #define CLOCK_PIN    18        // SPI SCK Clock pin
  73.  
  74. #define S1  35                 // Push buttons connected to the A0, A1, A2 Arduino pins
  75. #define S2   4    
  76. #define S3   2
  77.  
  78. #define NUM_LEDS     17        // All LEDs on shield
  79. #define BRIGHTNESS   30        // The best tested LEDs brightness 20-60
  80. #define LED_TYPE     WS2812B   // Datasheet: http://bit.ly/LED-WS2812B
  81. #define COLOR_ORDER  GRB       // For color ordering use this sketch: http://bit.ly/RGBCalibrate  
  82.  
  83. #define ALARM_REPEAT  3         // How many times play the melody alarm
  84.  
  85. DS3232RTC RTC;
  86.  
  87. // Array of LEDs
  88. CRGB leds[NUM_LEDS];        
  89.  
  90. // t variable for Arduino Time Library
  91. time_t t;
  92. tmElements_t tm;
  93. // See the Arduino Time Library for details on the tmElements_t structure:
  94. // http://playground.arduino.cc/Code/Time
  95. // https://github.com/PaulStoffregen/Time  
  96.  
  97. // Interrupt flag true/false
  98. volatile bool RTCinterruptWasCalled = false;
  99.  
  100. // Bit array for storing binary format
  101. bool binaryArray[NUM_LEDS];      
  102.  
  103. // Notes in the melody:
  104. const int melodyAlarm[] PROGMEM =
  105. {
  106.     NOTE_A4,  NOTE_A4,  NOTE_A4,  NOTE_F4,  NOTE_C5,  NOTE_A4,  NOTE_F4,  NOTE_C5,
  107.     NOTE_A4,  NOTE_E5,  NOTE_E5,  NOTE_E5,  NOTE_F5,  NOTE_C5,  NOTE_GS4, NOTE_F4,
  108.     NOTE_C5,  NOTE_A4,  NOTE_A5,  NOTE_A4,  NOTE_A4,  NOTE_A5,  NOTE_GS5, NOTE_G5,
  109.     NOTE_FS5, NOTE_F5,  NOTE_FS5, 0,        NOTE_AS4, NOTE_DS5, NOTE_D5,  NOTE_CS5,
  110.     NOTE_C5,  NOTE_B4,  NOTE_C5,  0,        NOTE_F4,  NOTE_GS4, NOTE_F4,  NOTE_A4,
  111.     NOTE_C5,  NOTE_A4,  NOTE_C5,  NOTE_E5,  NOTE_A5,  NOTE_A4,  NOTE_A4,  NOTE_A5,
  112.     NOTE_GS5, NOTE_G5,  NOTE_FS5, NOTE_F5,  NOTE_FS5, 0,        NOTE_AS4, NOTE_DS5,
  113.     NOTE_D5,  NOTE_CS5, NOTE_C5,  NOTE_B4,  NOTE_C5,  0,        NOTE_F4,  NOTE_GS4,
  114.     NOTE_F4,  NOTE_C5,  NOTE_A4,  NOTE_F4,  NOTE_C5,  NOTE_A4,                            
  115. };
  116.  
  117. // Note durations: 4 = quarter note, 8 = eighth note, etc.:
  118. // Some notes durations have been changed (1, 3, 6) to make them sound better
  119. const byte noteDurations[] PROGMEM =
  120. {
  121.     2, 2, 2, 3, 6, 2, 3, 6,
  122.     1, 2, 2, 2, 3, 6, 2, 3,
  123.     6, 1, 2, 3, 6, 2, 4, 4,
  124.     8, 8, 4, 3, 4, 2, 4, 4,
  125.     8, 8, 4, 3, 6, 2, 3, 6,
  126.     2, 3, 6, 1, 2, 3, 8, 2,
  127.     4, 4, 8, 8, 4, 4, 4, 2,
  128.     4, 4, 8, 8, 4, 4, 4, 2,
  129.     3, 8, 2, 3, 8, 1,                                      
  130. };
  131.  
  132. // Counter of button presses
  133. int countButtonPressed = 0;
  134.  
  135. // The current reading from the input pins
  136. bool S1state = LOW;                  
  137. bool S2state = LOW;    
  138. bool S3state = LOW;  
  139.  
  140. // The previous reading from the input pins
  141. bool lastreadS1 = LOW;                
  142. bool lastreadS2 = LOW;
  143. bool lastreadS3 = LOW;
  144.  
  145. // The following variables are unsigned longs because the time, measured in
  146. // milliseconds, will quickly become a bigger number than can be stored in an int.
  147. unsigned long lastDebounceTime = 0;   // The last time the input pin was toggled
  148. unsigned long debounceDelay = 50;     // The debounce time. Increase if the output flickers
  149.  
  150. // Variables that store the current settings option
  151. int settingsOption = 0;               // Time = 1, Alarm = 3  
  152. int settingsLevel = 0;                // Hours = 1, Minutes = 2, Seconds / On/Off Alarm = 3
  153.  
  154. // Variables that store the current alarm time and status
  155. int hourAlarm;
  156. int minuteAlarm;
  157. int alarmStatus;
  158.  
  159. //################################################################################//
  160. // SETUP
  161. //################################################################################//
  162. void setup()
  163. {
  164.   #if DEBUG
  165.     Serial.begin(115200);
  166.   #endif
  167.  
  168.     RTC.begin();
  169.     // Important power-up safety delay
  170.     delay(3000);
  171.  
  172.     // Limit my draw to 450mA at 5V of power draw
  173.     FastLED.setMaxPowerInVoltsAndMilliamps(5,450);
  174.  
  175.     // Initialize LEDs
  176.     FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  177.     FastLED.setBrightness(BRIGHTNESS);
  178.  
  179.     // Initialize the buttons pins as an input
  180.     pinMode(S1, INPUT);
  181.     pinMode(S2, INPUT);
  182.     pinMode(S3, INPUT);
  183.  
  184.     getAlarmTimeAndStatus();
  185.     serialDebugStartInfo();
  186.  
  187.     // Configure an interrupt on the falling edge from the RTC INT/SQW output
  188.     pinMode(INT, INPUT_PULLUP);
  189.     attachInterrupt(digitalPinToInterrupt(INT), RTCinterrupt, FALLING);
  190.  
  191.     // Clear the alarm status flag 'A2F'
  192.     RTC.alarm(DS3232RTC::ALARM_2);
  193.  
  194.     // Enable 1 Hz square wave RTC SQW output
  195.     RTC.squareWave(DS3232RTC::SQWAVE_1_HZ);    
  196. }
  197.  
  198. void RTCinterrupt()
  199. {
  200.     RTCinterruptWasCalled = true;
  201. }
  202.  
  203. //################################################################################//
  204. // MAIN LOOP
  205. //################################################################################//
  206. void loop ()
  207. {  
  208.     settingsMenu();
  209.    
  210.     if (RTCinterruptWasCalled && (settingsOption == 0))   // Display time but not during settings
  211.     {
  212.         RTCinterruptWasCalled = false;                    // Clear the interrupt flag
  213.         getAndDisplayTime();                              // Get time from RTC, convert to binary format and display on LEDs
  214.         serialDebugTime();                                // Use serial monitor for showing current time
  215.    
  216.         if ((RTC.alarm(DS3232RTC::ALARM_2)) & (alarmStatus == 2))
  217.         {  
  218.           #if DEBUG
  219.             Serial << "   ALARM!\n";
  220.           #endif  
  221.             playAlarm();
  222.         }                    
  223.     }        
  224. }              
  225.  
  226. //################################################################################//
  227. // SETTINGS
  228. //################################################################################//
  229. //
  230. //                       +-------------------------------+
  231. //                       |           SETTINGS            |
  232. //           +-----------+-------------------------------+
  233. //           |  BUTTONS  |    S3   |     S2    |   S1    |
  234. // +---------+-----------+---------+-----------+---------+
  235. // |         |           |         |   ALARM   |         |
  236. // |         |     0     |  ALARM  |   MELODY  |  TIME   |
  237. // |   S     |           |         |   STOP    |         |
  238. // +   E L   +-----------+---------+-----------+---------+
  239. // |   T E   | ROW H = 1 |    +    |   SAVE    |    -    |
  240. // |   T V   |           |         | LEVEL = 2 |         |
  241. // +   I E   +-----------+---------+-----------+---------+
  242. // |   N L   | ROW M = 2 |    +    |   SAVE    |    -    |
  243. // |   G     |           |         | LEVEL = 3 |         |
  244. // +   S     +-----------+---------+-----------+---------+
  245. // |         | ROW S = 3 |    +    |   SAVE    |    -    |
  246. // |         |           |         | LEVEL = 0 |         |
  247. // +---------+-----------+---------+-----------+---------+
  248. //
  249. //                       +-------------------------------+
  250. //                       |        SETTINGS OPTION        |
  251. //                       +---------------+---------------+
  252. //                       |   ALARM = 3   |   TIME = 1    |
  253. // +---------------------+---------------+---------------+
  254. // |   S     | ROW H = 1 |     3/1       |     1/1       |
  255. // |   E L   |           |     HOUR      |     HOUR      |
  256. // +   T E   +-----------+---------------+---------------+
  257. // |   T V   | ROW M = 2 |     3/2       |     1/2       |
  258. // |   I E   |           |    MINUTE     |    MINUTE     |
  259. // +   N L   +-----------+---------------+---------------+
  260. // |   G     | ROW S = 3 |     3/3       |     1/3       |
  261. // |   S     |           | ALARM STATUS  |    SECOND     |
  262. // +---------+-----------+---------------+---------------+
  263. //
  264. // The core of the settings menu
  265. void settingsMenu ()
  266. {
  267.     // Main menu
  268.     if ((settingsOption == 0) & (settingsLevel == 0))
  269.     {  
  270.         // Time settings
  271.         if (checkS1() == HIGH)
  272.         {
  273.             t = RTC.get();                          // Read time from RTC
  274.             settingsOption = 1;                     // Set time option settings
  275.             settingsLevel = 1;                      // Set hour level settings
  276.             setCurrentModifiedValue();              // Assign hours for modify +/-
  277.             serialDebugSettings();                  // Use serial monitor for showing settings
  278.             displayCurrentModifiedValue();          // Display current hour on LEDs
  279.         }
  280.  
  281.         // Alarm settings
  282.         if (checkS3() == HIGH)                  
  283.         {
  284.             getAlarmTimeAndStatus();                // Read alarm time and status from RTC
  285.             settingsOption = 3;                     // Set Alarm time option settings
  286.             settingsLevel = 1;                      // Set hour level settings
  287.             setCurrentModifiedValue();              // Assign hours for modify +/-
  288.             serialDebugSettings();                  // Use serial monitor for showing settings
  289.             displayCurrentModifiedValue();          // Display current alarm hour on LEDs
  290.         }
  291.     }
  292.  
  293.     // Any settings option level except main menu
  294.     if (settingsLevel != 0)
  295.     {
  296.         // Decrement
  297.         if (checkS1() == HIGH)
  298.         {
  299.             countButtonPressed--;                   // Decrement current value e.g. hour, minute, second, alarm status
  300.             checkCurrentModifiedValueFormat();      // Check if the value has exceeded the range e.g minute = 60 and correct
  301.             displayCurrentModifiedValue();          // Display current modified value on LEDs
  302.             serialDebugCurrentModifiedValue();      // Use serial monitor for showing settings
  303.         }
  304.  
  305.         // Increment
  306.         if (checkS3() == HIGH)
  307.         {
  308.             countButtonPressed++;                   // Increment current value e.g. hour, minute, second, alarm status
  309.             checkCurrentModifiedValueFormat();      // Check if the value has exceeded the range e.g minute = 60 and correct
  310.             displayCurrentModifiedValue();          // Display current modified value on LEDs  
  311.             serialDebugCurrentModifiedValue();      // Use serial monitor for showing settings
  312.         }            
  313.  
  314.         // Save
  315.         if (checkS2() == HIGH)
  316.         {
  317.             saveCurrentModifiedValue();             // Save current value e.g. hour, minute, second, alarm status    
  318.             settingsLevel++;                        // Go to next settings level - hour => minute => second / alarm status
  319.  
  320.             if (settingsLevel > 3)                  // If escape from settings then return to main menu
  321.             {
  322.                 if (settingsOption == 1)            // If you were in the process of setting the time:  
  323.                 {
  324.                     setNewTime ();                  // Save time to the RTC
  325.                 }
  326.  
  327.                 if (settingsOption == 3)            // If you were in the process of setting the alarm:
  328.                 {
  329.                     setAlarmTimeAndStatus();        // Save time and alarm status to the RTC    
  330.                 }
  331.                
  332.                 serialDebugAlarmInfo();             // Show the time and alarm status info when you exit to the main menu
  333.                 settingsLevel = 0;                  // Escape to main menu  
  334.                 settingsOption = 0;                 // Escape to main menu
  335.             }
  336.             else                                    // If you do not go to the main menu yet
  337.             {
  338.                 checkCurrentModifiedValueFormat();  // Check if the value has exceeded the range e.g minute = 60 and correct                  
  339.                 setCurrentModifiedValue();          // Assign next variable for modify +/- hour => minute => second / alarm status
  340.                 displayCurrentModifiedValue();      // Display current modified value on LEDs                
  341.                 serialDebugSettings();              // Use serial monitor for showing settings
  342.             }
  343.         }
  344.     }
  345. }
  346.  
  347. ////////////////////////////////////////////////////////////////////////////////////
  348. // Depending on the options and settings level, assign to the
  349. // countButtonPressed variable to be able modify the value
  350. ////////////////////////////////////////////////////////////////////////////////////
  351. void setCurrentModifiedValue ()
  352. {
  353.     // Assign current time value stored in time_t t variable for modification
  354.     if(settingsOption == 1)
  355.     {
  356.         if(settingsLevel == 1)  countButtonPressed = hour(t);
  357.         if(settingsLevel == 2)  countButtonPressed = minute(t);  
  358.         if(settingsLevel == 3)  countButtonPressed = second(t);    
  359.     }    
  360.  
  361.     // Alarm time and alarm status
  362.     if(settingsOption == 3)
  363.     {
  364.         if(settingsLevel == 1)  countButtonPressed = hourAlarm;
  365.         if(settingsLevel == 2)  countButtonPressed = minuteAlarm;  
  366.         if(settingsLevel == 3)  countButtonPressed = alarmStatus;  
  367.     }    
  368. }
  369.  
  370. ////////////////////////////////////////////////////////////////////////////////////
  371. // Check current modified value format of the countButtonPressed variable
  372. ////////////////////////////////////////////////////////////////////////////////////
  373. void checkCurrentModifiedValueFormat()
  374. {  
  375.     // Hours 0-23      
  376.     if (settingsLevel == 1)
  377.     {
  378.         if(countButtonPressed < 0) countButtonPressed = 23;
  379.         if(countButtonPressed > 23) countButtonPressed = 0;              
  380.     }
  381.  
  382.     // Minutes 0-59
  383.     if (settingsLevel == 2)
  384.     {
  385.         if(countButtonPressed < 0) countButtonPressed = 59;
  386.         if(countButtonPressed > 59) countButtonPressed = 0;              
  387.     }
  388.  
  389.     // Seconds & Alarm status
  390.     if (settingsLevel == 3)
  391.     {
  392.         // Seconds 0-59
  393.         if (settingsOption == 1)
  394.         {
  395.             if(countButtonPressed < 0) countButtonPressed = 59;
  396.             if(countButtonPressed > 59) countButtonPressed = 0;              
  397.         }
  398.  
  399.         // Alarm status 1/2
  400.         if (settingsOption == 3)
  401.         {
  402.             if(countButtonPressed < 1) countButtonPressed = 2;
  403.             if(countButtonPressed > 2) countButtonPressed = 1;              
  404.         }
  405.     }    
  406. }
  407.  
  408. ////////////////////////////////////////////////////////////////////////////////////
  409. // Depending on the options and settings level, save the current modified value
  410. ////////////////////////////////////////////////////////////////////////////////////
  411. void saveCurrentModifiedValue ()
  412. {
  413.     // Save current value in the tmElements_t tm structure
  414.     if(settingsOption == 1)
  415.     {
  416.         if(settingsLevel == 1)  tm.Hour = countButtonPressed;
  417.         if(settingsLevel == 2)  tm.Minute = countButtonPressed;  
  418.         if(settingsLevel == 3)  tm.Second = countButtonPressed;      
  419.     }    
  420.  
  421.     // Alarm time and alarm status
  422.     if(settingsOption == 3)
  423.     {
  424.         if(settingsLevel == 1)  hourAlarm = countButtonPressed;
  425.         if(settingsLevel == 2)  minuteAlarm = countButtonPressed;  
  426.         if(settingsLevel == 3)  alarmStatus = countButtonPressed;      
  427.     }    
  428. }
  429.  
  430. ////////////////////////////////////////////////////////////////////////////////////
  431. // Display on LEDs only currently modified value
  432. // convertDecToBinaryAndDisplay(bottom row, middle row, upper row)
  433. ////////////////////////////////////////////////////////////////////////////////////
  434. void displayCurrentModifiedValue ()
  435. {
  436.     if (settingsLevel == 1) convertDecToBinaryAndDisplay(0, 0, countButtonPressed);
  437.     if (settingsLevel == 2) convertDecToBinaryAndDisplay(0, countButtonPressed, 0);
  438.     if (settingsLevel == 3) convertDecToBinaryAndDisplay(countButtonPressed, 0, 0);    
  439. }
  440.  
  441. //################################################################################//
  442. // ALARM HANDLING
  443. //################################################################################//
  444.  
  445. ////////////////////////////////////////////////////////////////////////////////////
  446. // Get alarm time and convert it from BCD to DEC format
  447. // Get alarm status active/inactive
  448. ////////////////////////////////////////////////////////////////////////////////////
  449. void getAlarmTimeAndStatus ()
  450. {
  451.     // Alarm Time HH:MM
  452.     // 0x0B - alarm2 minute register address - check DS3231 datasheet
  453.     // minutes using 7 bits of that register
  454.     minuteAlarm = RTC.readRTC(0x0B);
  455.     minuteAlarm = ((minuteAlarm & 0b01110000) >> 4)*10 + (minuteAlarm & 0b00001111);
  456.  
  457.     // 0x0C - alarm2 hour register address - check DS3231 datasheet
  458.     // hours using 6 bits of that register
  459.     hourAlarm = RTC.readRTC(0x0C);
  460.     hourAlarm = ((hourAlarm & 0b00110000) >> 4)*10 + (hourAlarm & 0b00001111);  
  461.  
  462.     // Alarm Status active/inactive
  463.     // Check bit 2 of the control register - A2IE
  464.     // if 1 - alarm active, if 0 - alarm inactive
  465.     byte currentAlarmStatus = RTC.readRTC(0x0E) && 0b00000010;
  466.    
  467.     // alarmStatus: 1 - alarm inactive, 2 - alarm active  
  468.     // it is the simplest way to display alarm status on LEDs (bottom S-row)
  469.     // because with 0 and 1 - for 0 no LEDs lit, and this could be misleading
  470.     if (currentAlarmStatus == 0) alarmStatus = 1;
  471.     else if (currentAlarmStatus == 1) alarmStatus = 2;
  472. }
  473. ////////////////////////////////////////////////////////////////////////////////////
  474. // Set alarm time and status
  475. ////////////////////////////////////////////////////////////////////////////////////
  476. void setAlarmTimeAndStatus ()
  477. {
  478.     // Set alarm time  
  479.     RTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, 0, minuteAlarm, hourAlarm, 0);
  480.    
  481.     // Read RTC control register  
  482.     byte controlRegister = RTC.readRTC(0x0E);
  483.  
  484.     // If the current alarm status is active, set bit 2 of the control register - A2IE
  485.     // If inactive, clear bit 2 of the control register - A2IE  
  486.     if (alarmStatus == 2) controlRegister = controlRegister | 0b00000010;
  487.     else controlRegister = controlRegister & 0b11111101;
  488.  
  489.     // Update the control register
  490.     RTC.writeRTC(0x0E, controlRegister);
  491. }
  492.  
  493. //################################################################################//
  494. // RTC TIME & BINARY FORMAT
  495. //################################################################################//
  496.  
  497. ////////////////////////////////////////////////////////////////////////////////////
  498. // Write time to RTC
  499. ////////////////////////////////////////////////////////////////////////////////////
  500. void setNewTime ()
  501. {
  502.     // Save the time stored in tmElements_t tm structure
  503.     RTC.write(tm);  
  504. }
  505.  
  506. ////////////////////////////////////////////////////////////////////////////////////
  507. // Get time from RTC and convert to BIN format
  508. ////////////////////////////////////////////////////////////////////////////////////
  509. void getAndDisplayTime()
  510. {
  511.     // Read time from RTC  
  512.     t = RTC.get();
  513.     // Convert time to binary format and display    
  514.     convertDecToBinaryAndDisplay(second(t), minute(t), hour(t));
  515. }
  516.  
  517. ////////////////////////////////////////////////////////////////////////////////////
  518. // Convert values from DEC to BIN format and display
  519. ////////////////////////////////////////////////////////////////////////////////////
  520. void convertDecToBinaryAndDisplay(int bottomRow, int middleRow, int upperRow)
  521. {  
  522.     bool oneBit;
  523.     // A fast and efficient way to convert decimal to binary format and to set the individual LED colors
  524.     // The original code ran in a hard-coded loop extracting on bit at a time from the decimal value
  525.     // and setting the corresponding LED color based on whether the bit was 0 or 1
  526.     // This code just does a bitwise AND and tests if the bit was non-zero, then sets the corresponding LED color
  527.     // Using a MACRO to handle debugging compiles where the serial output is used, where 'binaryArray[]' is required.
  528.     // Performing the assignment to 'binaryArray[]' then testing the result for non-zero to assign the colour
  529.     #ifdef DEBUG
  530.         #define SET_LEDS(led_num, value, bitmask, on_color, off_color) \
  531.             leds[led_num] = (binaryArray[led_num] = ((value) & (bitmask))) ? on_color : off_color;
  532.     #else
  533.         #define SET_LEDS(led_num, value, bitmask, on_color, off_color) \
  534.             leds[led_num] = ((value) & (bitmask)) ? on_color : off_color;
  535.     #endif
  536.  
  537.     //
  538.     // H - upper row LEDs where the hour is displayed, left most bit, the MSB, is led 16, LSB is LED 12
  539.     // leds[16] = (upperRow & 0b00010000) ? CRGB::Blue : CRGB::Black; // LED 16 - dot[4] for hour 16 (msb)
  540.     // leds[15] = (upperRow & 0b00001000) ? CRGB::Blue : CRGB::Black; // LED 15 - dot[3] for hour  8
  541.     // leds[14] = (upperRow & 0b00000100) ? CRGB::Blue : CRGB::Black; // LED 14 - dot[2] for hour  4
  542.     // leds[13] = (upperRow & 0b00000010) ? CRGB::Blue : CRGB::Black; // LED 13 - dot[1] for hour  2
  543.     // leds[12] = (upperRow & 0b00000001) ? CRGB::Blue : CRGB::Black; // LED 12 - dot[0] for hour  1 (lsb)
  544.  
  545.     // This is an expensive and slow way to convert decimal to binary format and to set the individual LED colors
  546.     for(int i = 12; i < 17; i++)                        // H - upper row
  547.     {
  548.         oneBit = upperRow & 0b00000001;                 // Extraction of individual bits 0/1
  549.         binaryArray[i] = oneBit;                        // Save bit in binary array
  550.         upperRow = upperRow >> 1;                       // Bit shift
  551.  
  552.         if(binaryArray[i] == 1) leds[i] = CRGB::Blue;   // If 1 - turn on LED
  553.         else leds[i] = CRGB::Black;                     // If 0 - turn off LED            
  554.     }
  555.  
  556.     // M - middle row LEDs where the minute is displayed, left most bit, the MSB, is led 12, LSB is LED 6
  557.     // leds[11] = (upperRow & 0b00100000) ? CRGB::Green : CRGB::Black; // LED 11 - dot[5] for minute 32 (msb)
  558.     // leds[10] = (upperRow & 0b00010000) ? CRGB::Green : CRGB::Black; // LED 10 - dot[4] for minute 16
  559.     // leds[9]  = (upperRow & 0b00001000) ? CRGB::Green : CRGB::Black; // LED  9 - dot[3] for minute  8
  560.     // leds[8]  = (upperRow & 0b00000100) ? CRGB::Green : CRGB::Black; // LED  8 - dot[2] for minute  4
  561.     // leds[7]  = (upperRow & 0b00000010) ? CRGB::Green : CRGB::Black; // LED  7 - dot[1] for minute  2
  562.     // leds[6]  = (upperRow & 0b00000001) ? CRGB::Green : CRGB::Black; // LED  6 - dot[0] for minute  1 (lsb)
  563.  
  564.     for(int i = 6; i < 12; i++)                         // M - middle row
  565.     {
  566.         oneBit = middleRow & 0b00000001;                 // Extraction of individual bits 0/1
  567.         binaryArray[i] = oneBit;                        // Save bit in binary array
  568.         middleRow = middleRow >> 1;                     // Bit shift
  569.  
  570.         if(binaryArray[i] == 1) leds[i] = CRGB::Green;  // If 1 - turn on LED
  571.         else leds[i] = CRGB::Black;                     // If 0 - turn off LED  
  572.     }
  573.  
  574.     // S - bottom row LEDs where the second is displayed, left most bit, the MSB, is led 5, LSB is LED 0
  575.     // leds[5] = (upperRow & 0b00100000) ? CRGB::Red : CRGB::Black; // LED  5 - dot[5] for second 32 (msb)
  576.     // leds[4] = (upperRow & 0b00010000) ? CRGB::Red : CRGB::Black; // LED  4 - dot[4] for second 16
  577.     // leds[3] = (upperRow & 0b00001000) ? CRGB::Red : CRGB::Black; // LED  3 - dot[3] for second  8
  578.     // leds[2] = (upperRow & 0b00000100) ? CRGB::Red : CRGB::Black; // LED  2 - dot[2] for second  4
  579.     // leds[1] = (upperRow & 0b00000010) ? CRGB::Red : CRGB::Black; // LED  1 - dot[1] for second  2
  580.     // leds[0] = (upperRow & 0b00000001) ? CRGB::Red : CRGB::Black; // LED  0 - dot[0] for second  1 (lsb)
  581.  
  582.     for(int i = 0; i <6; i++)                           // S - bottom row                          
  583.     {
  584.         oneBit = bottomRow & 0b00000001;                 // Extraction of individual bits 0/1
  585.         binaryArray[i] = oneBit;                        // Save bit in binary array
  586.         bottomRow = bottomRow >> 1;                     // Bit shift
  587.    
  588.         if(binaryArray[i] == 1) leds[i] = CRGB::Red;    // If 1 - turn on LED
  589.         else leds[i] = CRGB::Black;                     // If 0 - turn off LED    
  590.     }
  591.  
  592.     FastLED.show();    
  593. }
  594.  
  595. //################################################################################//
  596. // MELODY ALARM
  597. //################################################################################//
  598.  
  599. ////////////////////////////////////////////////////////////////////////////////////
  600. // During playing the alarm melody, time display function is disabled
  601. ////////////////////////////////////////////////////////////////////////////////////
  602. void playAlarm ()
  603. {
  604.     bool stopAlarm = LOW;
  605.     int howManyTimes = 0;
  606.     unsigned long millis_time_now = 0;
  607.    
  608.     // Count how many notes are in the melody
  609.     int allNotes = sizeof(noteDurations);
  610.  
  611.     while ((howManyTimes < ALARM_REPEAT) & (stopAlarm == LOW))
  612.     {
  613.         for (int thisNote = 0; thisNote < allNotes; thisNote++)
  614.         {    
  615.             // To calculate the note duration, take one second divided by the note type.
  616.             // e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
  617.             int noteDuration = 1000 / pgm_read_byte(&noteDurations[thisNote]);
  618.             tone(PIEZO, pgm_read_word(&melodyAlarm[thisNote]), noteDuration);
  619.  
  620.             // To distinguish the notes, set a minimum time between them.
  621.             // The note's duration + 30% seems to work well:
  622.             int pauseBetweenNotes = noteDuration * 1.30;
  623.  
  624.             // Millis time start
  625.             millis_time_now = millis();
  626.    
  627.             // Pause between notes
  628.             while(millis() < millis_time_now + pauseBetweenNotes)
  629.             {
  630.                 // Stop alarm melody and go to main menu
  631.                 if (checkS2() == HIGH)
  632.                 {
  633.                     // Prepare for escape to main menu
  634.                     settingsLevel = 0;              
  635.                     settingsOption = 0;
  636.                     stopAlarm = 1;
  637.  
  638.                     // Stop the tone playing
  639.                     noTone(PIEZO);
  640.                 }
  641.             }
  642.  
  643.             // Escape to main menu
  644.             if (stopAlarm == 1) break;
  645.  
  646.             // Stop the tone playing
  647.             noTone(PIEZO);
  648.         }
  649.         howManyTimes++;
  650.     }  
  651. }
  652.  
  653. //################################################################################//
  654. // CHECK BUTTONS
  655. //################################################################################//
  656.  
  657. ////////////////////////////////////////////////////////////////////////////////////
  658. // Check if the S1 button has been pressed
  659. ////////////////////////////////////////////////////////////////////////////////////
  660. int checkS1()
  661. {
  662.     // Read the state of the push button into a local variable:
  663.     bool currentreadS1 = digitalRead(S1);
  664.  
  665.     // Check to see if you just pressed the button
  666.     // (i.e. the input went from LOW to HIGH), and you've waited long enough
  667.     // since the last press to ignore any noise:
  668.  
  669.     // Check if button changed, due to noise or pressing:
  670.     if (currentreadS1 != lastreadS1)
  671.     {
  672.         // Reset the debouncing timer
  673.         lastDebounceTime = millis();
  674.     }
  675.  
  676.     if ((millis() - lastDebounceTime) > debounceDelay)
  677.     {
  678.         // Whatever the reading is at, it's been there for longer than the debounce
  679.         // delay, so take it as the actual current state:
  680.  
  681.         // If the button state has changed:
  682.         if (currentreadS1 != S1state)
  683.         {
  684.             S1state = currentreadS1;
  685.  
  686.             // Return 1 only if the new button state is HIGH
  687.             if (S1state == HIGH)
  688.             {
  689.                 lastreadS1 = currentreadS1;
  690.                 return 1;
  691.             }
  692.         }
  693.     }
  694.  
  695.     // Save S1 button state. Next time through the loop, it'll be the lastreadS2:
  696.     lastreadS1 = currentreadS1;
  697.     return 0;
  698. }
  699.  
  700. ////////////////////////////////////////////////////////////////////////////////////
  701. // Check if the S2 button has been pressed
  702. ////////////////////////////////////////////////////////////////////////////////////
  703. int checkS2()
  704. {
  705.     // Read the state of the push button into a local variable:
  706.     bool currentreadS2 = digitalRead(S2);
  707.  
  708.     // Check to see if you just pressed the button
  709.     // (i.e. the input went from LOW to HIGH), and you've waited long enough
  710.     // since the last press to ignore any noise:
  711.  
  712.     // Check if button changed, due to noise or pressing:
  713.     if (currentreadS2 != lastreadS2)
  714.     {
  715.         // Reset the debouncing timer
  716.         lastDebounceTime = millis();
  717.     }
  718.  
  719.     if ((millis() - lastDebounceTime) > debounceDelay)
  720.     {
  721.         // Whatever the reading is at, it's been there for longer than the debounce
  722.         // delay, so take it as the actual current state:
  723.  
  724.         // If the button state has changed:
  725.         if (currentreadS2 != S2state)
  726.         {
  727.             S2state = currentreadS2;
  728.  
  729.             // Return 1 only if the new button state is HIGH
  730.             if (S2state == HIGH)
  731.             {
  732.                 lastreadS2 = currentreadS2;
  733.                 return 1;
  734.             }
  735.         }
  736.     }
  737.  
  738.     // Save S2 button state. Next time through the loop, it'll be the lastreadS2:
  739.     lastreadS2 = currentreadS2;
  740.     return 0;
  741. }
  742.  
  743. ////////////////////////////////////////////////////////////////////////////////////
  744. // Check if the S3 button has been pressed
  745. ////////////////////////////////////////////////////////////////////////////////////
  746. int checkS3()
  747. {
  748.     // Read the state of the push button into a local variable:
  749.     bool currentreadS3 = digitalRead(S3);
  750.  
  751.     // Check to see if you just pressed the button
  752.     // (i.e. the input went from LOW to HIGH), and you've waited long enough
  753.     // since the last press to ignore any noise:
  754.  
  755.     // Check if button changed, due to noise or pressing:
  756.     if (currentreadS3 != lastreadS3)
  757.     {
  758.         // Reset the debouncing timer
  759.         lastDebounceTime = millis();
  760.     }
  761.  
  762.     if ((millis() - lastDebounceTime) > debounceDelay)
  763.     {
  764.         // Whatever the reading is at, it's been there for longer than the debounce
  765.         // delay, so take it as the actual current state:
  766.  
  767.         // If the button state has changed:
  768.         if (currentreadS3 != S3state)
  769.         {
  770.             S3state = currentreadS3;
  771.  
  772.             // Return 1 only if the new button state is HIGH
  773.             if (S3state == HIGH)
  774.             {
  775.                 lastreadS3 = currentreadS3;
  776.                 return 1;
  777.             }
  778.         }
  779.     }
  780.    
  781.     // Save S3 button state. Next time through the loop, it'll be the lastreadS3:
  782.     lastreadS3 = currentreadS3;
  783.     return 0;  
  784. }
  785.  
  786. //################################################################################//
  787. // SERIAL DEBUG INFO
  788. //################################################################################//
  789.  
  790. ////////////////////////////////////////////////////////////////////////////////////
  791. // Print Time in DEC & BIN format
  792. ////////////////////////////////////////////////////////////////////////////////////
  793. void serialDebugTime()
  794. {
  795.   #if DEBUG
  796.     Serial << ("DEC:");
  797.     Serial << ((hour(t)<10) ? "0" : "") << _DEC(hour(t)) << (":");
  798.     Serial << ((minute(t)<10) ? "0" : "") << _DEC(minute(t)) << (":");
  799.     Serial << ((second(t)<10) ? "0" : "") << _DEC(second(t)) << ("  ");
  800.  
  801.     Serial << ("BIN:");
  802.     for(int i = 16; i >= 0; i--)
  803.     {                
  804.         if(i == 11 || i == 5) Serial << (" ");      
  805.         Serial << (binaryArray[i] ? "1" : "0"); // Print 1 or 0 for each LED
  806.     }
  807.     Serial << endl;
  808.   #endif
  809. }
  810.  
  811. ////////////////////////////////////////////////////////////////////////////////////
  812. // Show the Shield settings menu and alarm status
  813. ////////////////////////////////////////////////////////////////////////////////////
  814. void serialDebugStartInfo ()
  815. {
  816.   #if DEBUG
  817.     Serial << F("-------------------------------------") << endl;
  818.     Serial << F("------- BINARY CLOCK SHIELD ---------") << endl;
  819.     Serial << F("----------- FOR ARDUINO -------------") << endl;
  820.     Serial << F("-------------------------------------") << endl;
  821.     Serial << F("------------- Options ---------------") << endl;
  822.     Serial << F("S1 - Alarm Settings -----------------") << endl;
  823.     Serial << F("S2 - Disable Alarm Melody -----------") << endl;
  824.     Serial << F("S3 - Time Settings ------------------") << endl;
  825.     Serial << F("-------------------------------------");
  826.    
  827.     serialDebugAlarmInfo();
  828.        
  829.     Serial << F("#####################################") << endl;
  830.     Serial << F("START WITHIN 10 SECONDS -------------") << endl;
  831.    
  832.     // Show progress bar: #37 * 270ms = ~10s delay
  833.     for (int i = 0; i < 37; i++)
  834.     {
  835.         delay (270);
  836.         Serial << ("#");    
  837.     }
  838.      
  839.     Serial << endl << endl;
  840.   #endif  
  841. }
  842.  
  843. ////////////////////////////////////////////////////////////////////////////////////
  844. // Show alarm settings
  845. ////////////////////////////////////////////////////////////////////////////////////
  846. void serialDebugSettings ()
  847. {
  848.   #if DEBUG    
  849.     if (settingsOption == 1)
  850.     {
  851.         Serial << endl << endl;
  852.         Serial << F("-------------------------------------") << endl;
  853.         Serial << F("---------- Time Settings ------------") << endl;
  854.         Serial << F("-------------------------------------") << endl;
  855.     }    
  856.  
  857.     if (settingsOption == 3)
  858.     {
  859.         Serial << endl << endl;
  860.         Serial << F("-------------------------------------") << endl;
  861.         Serial << F("---------- Alarm Settings -----------") << endl;
  862.         Serial << F("-------------------------------------") << endl;
  863.     }
  864.  
  865.     if (settingsLevel == 1) Serial << F("--------------- Hour ----------------") << endl;  
  866.     if (settingsLevel == 2) Serial << F("-------------- Minute ---------------") << endl;
  867.     if (settingsLevel == 3)
  868.     {
  869.         if(settingsOption == 1) Serial << F("-------------- Second ---------------") << endl;
  870.         if(settingsOption == 3) Serial << F("-------------- ON/OFF ---------------") << endl;
  871.     }
  872.    
  873.     Serial << F("S1 - Decrement ----------------------") << endl;
  874.     Serial << F("S3 - Increment ----------------------") << endl;
  875.     Serial << F("S2 - Save Current Settings Level ----") << endl;
  876.     Serial << F("-------------------------------------") << endl;
  877.  
  878.     if (settingsLevel == 1) Serial << F("Current Hour: ") << countButtonPressed << (" ");
  879.     if (settingsLevel == 2) Serial << F("Current Minute: ") << countButtonPressed << (" ");
  880.     if (settingsLevel == 3)
  881.     {
  882.         if (settingsOption == 1) Serial << F("Current Second: ") << countButtonPressed << (" ");
  883.         if (settingsOption == 3)
  884.         {
  885.             Serial << F("Alarm Status: ");
  886.             Serial << (countButtonPressed == 2 ? "ON" : "");
  887.             Serial << (countButtonPressed == 1 ? "OFF" : "");        
  888.             Serial << (" ");
  889.         }
  890.     }
  891.   #endif      
  892. }
  893.  
  894. ////////////////////////////////////////////////////////////////////////////////////
  895. // Show the set alarm time and current alarm status
  896. ////////////////////////////////////////////////////////////////////////////////////
  897. void serialDebugAlarmInfo ()
  898. {
  899.   #if DEBUG
  900.     Serial << endl << endl;
  901.     Serial << F("-------------------------------------") << endl;
  902.     Serial << F("---- Alarm Time: ");
  903.     Serial << (hourAlarm < 10 ? "0" : "") << hourAlarm << ":";
  904.     Serial << (minuteAlarm < 10 ? "0" : "") << minuteAlarm;
  905.     Serial << endl;
  906.     Serial << F("-------------------------------------") << endl;
  907.  
  908.     Serial << F("---- Alarm Status: ");
  909.     Serial << (alarmStatus == 2 ? "ON" : "");
  910.     Serial << (alarmStatus == 1 ? "OFF" : "");
  911.     Serial << endl;
  912.     Serial << F("-------------------------------------") << endl;      
  913.     Serial << endl;
  914.   #endif  
  915. }
  916.  
  917. ////////////////////////////////////////////////////////////////////////////////////
  918. // Show current alarm status during settings
  919. ////////////////////////////////////////////////////////////////////////////////////
  920. void serialDebugCurrentModifiedValue ()
  921. {    
  922.   #if DEBUG  
  923.     if((settingsLevel == 3) & (settingsOption == 3))
  924.     {
  925.         Serial << (countButtonPressed == 2 ? "ON" : "");
  926.         Serial << (countButtonPressed == 1 ? "OFF" : "");  
  927.     }
  928.     else
  929.     {
  930.         Serial << countButtonPressed;  
  931.     }
  932.    
  933.     Serial << (" ");
  934.   #endif  
  935. }
  936.  
Comments
  • cguy450
    21 days
    # text 1.90 KB | 0 0
    1. The full errors generated:
    2. Compiling .pio\build\wemos_d1_uno32\src\11_BinaryClock_24H_RTCInterruptAlarmButtons_ESP32UNO_20250701.ino.cpp.o
    3. In file included from .pio/libdeps/wemos_d1_uno32/FastLED/src/platforms/esp/32/clockless_rmt_esp32.h:37,
    4. from .pio/libdeps/wemos_d1_uno32/FastLED/src/platforms/esp/32/fastled_esp32.h:22,
    5. from .pio/libdeps/wemos_d1_uno32/FastLED/src/platforms.h:44,
    6. from .pio/libdeps/wemos_d1_uno32/FastLED/src/FastLED.h:85,
    7. from C:/Users/Chris/Documents/PlatformIO/Projects/250701-192200-wemos_d1_uno32/src/11_BinaryClock_24H_RTCInterruptAlarmButtons_ESP32UNO_20250701.ino:53:
    8. .pio/libdeps/wemos_d1_uno32/FastLED/src/platforms/esp/32/rmt_4/idf4_clockless_rmt_esp32.h: In instantiation of 'class ClocklessController<34, 60, 150, 90, (EOrder)66, 0, false, 5>':
    9. .pio/libdeps/wemos_d1_uno32/FastLED/src/chipsets.h:1069:7: required from 'class WS2812Controller800Khz<34, (EOrder)66>'
    10. .pio/libdeps/wemos_d1_uno32/FastLED/src/FastLED.h:228:7: required from 'class WS2812B<34, (EOrder)66>'
    11. .pio/libdeps/wemos_d1_uno32/FastLED/src/FastLED.h:569:39: required from 'static CLEDController& CFastLED::addLeds(CRGB*, int, int) [with CHIPSET = WS2812B; unsigned char DATA_PIN = 34; EOrder RGB_ORDER = (EOrder)66]'
    12. C:/Users/Chris/Documents/PlatformIO/Projects/250701-192200-wemos_d1_uno32/src/11_BinaryClock_24H_RTCInterruptAlarmButtons_ESP32UNO_20250701.ino:176:68: required from here
    13. .pio/libdeps/wemos_d1_uno32/FastLED/src/platforms/esp/32/rmt_4/idf4_clockless_rmt_esp32.h:81:46: error: static assertion failed: Invalid pin specified
    14. static_assert(FastPin<DATA_PIN>::validpin(), "Invalid pin specified");
    15. ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
    16. Compiling .pio\build\wemos_d1_uno32\FrameworkArduino\HardwareSerial.cpp.o
    17. *** [.pio\build\wemos_d1_uno32\src\11_BinaryClock_24H_RTCInterruptAlarmButtons_ESP32UNO_20250701.ino.cpp.o] Error 1
Add Comment
Please, Sign In to add comment