//Clock_v0_2
/*
Showing clock in 10x9 matrix
Two buttons for Mode and Changing HourMinute
Function rtc.adjust not tested
*/
#include <FastLED.h>
#include <TimeLib.h>
#include <RTClib.h>
#include "Button.h"
//Include RTC version
RTC_DS1307 rtc;
//------------ Define buttons for adjusting the rtc
Button button1{A1}; // Connect your button between pin A1 and GND
Button button2{A2}; // Connect your button between pin A2 and GND
//------------ Define leds and the matrix
#define LED_PIN 3
#define COLOR_ORDER GRB
#define CHIPSET WS2811
#define BRIGHTNESS 64
// Params for width and height
const uint8_t kMatrixWidth = 10;
const uint8_t kMatrixHeight = 9;
// Param for different pixel layouts
const bool kMatrixSerpentineLayout = true;
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
CRGB* const leds( leds_plus_safety_pixel + 1);
//Use limited number of leds
const int myNumLeds = kMatrixWidth * kMatrixHeight;
//--------- Arrays specifying text in Swedish
//Arrays for text in clock
const int klockanAr[9] = {1,2,3,4,5,6, 8,9};
const int femMinOver[7]= {19,18,17, 38,37,36,35};
const int femMinI[4]= {19,18,17, 15};
const int femMinOverHalv[11] = {19,18,17, 38,37,36,35, 33,32,31,30};
const int femMinIHalv[8] = {19,18,17, 15, 33,32,31,30};
const int tioMinOver[7] = {25,26,27, 38,37,36,35};
const int tioMinI[4] = {25,26,27, 29};
const int femtonMinOver[9] = {14,13,12,11,10, 38,37,36,35};
const int femtonMinI[6]= {14,13,12,11,10, 26};
const int tjugoMinOver[9] = {20,21,22,23,24, 38,37,36,35};
const int tjugoMinI[6] = {20,21,22,23,24, 26};
const int trettioMinI[4] = {33,32,31,30};
const int ettTim[3] = {67,68,69};
const int tvaTim[3] = {83,84,85};
const int treTim[3] = {80,81,82};
const int fyraTim[4] = {74,73,72,71};
const int femTim[3] = {60,61,62};
const int sexTim[3] = {47,48,49};
const int sjuTim[3] = {40,41,42};
const int attaTim[4] = {78,77,76,75};
const int nioTim[3] = {53,52,51};
const int tioTim[3] = {43,44,45};
const int elvaTim[4]= {63,64,65,66};
const int tolvTim[4] = {58,57,56,55};
const int minutPunkter[4] = {86,87,88,89};
//Length of arrays specifing the time in Swedish
int sizeOfCurrentArray;
const int klockanArLength = 9;
const int femMinOverLength = 7;
const int femMinILength = 4;
const int femMinOverHalvLength = 11;
const int femMinIHalvLength =8;
const int tioMinOverLength = 7;
const int tioMinILength = 4;
const int femtonMinOverLength = 9;
const int femtonMinILength = 6;
const int tjugoMinOverLength = 9;
const int tjugoMinILength = 6;
const int trettioMinILength = 4;
//Length hours (always three och four)
const int timLengthTre = 3;
const int timLengthFyra = 4;
//Arrays for adjusting rtc
const int textNyTim[5] = {6,7, 25,26,28};
const int textNyMin[5] = {6,7, 28,29,70};
const int textNySave[4] = {31,33,65,67}; //SAVE
const int textNyExit[4] = {48,49,52,69}; //EXIT
//---------- Parameters for calculating the hour
//Current date and time according to rtc
int cur_year = 2023;
int cur_month = 1;
int cur_day = 1;
int cur_tt = 10;
int cur_mm = 00;
//Date and time displayed
int display_year = 99;
int display_month = 99;
int display_day = 99;
int display_tt = 99;
int display_mm = 99;
//Calculated number of current minutes and leds displayed
int cur_dots = 99;
int display_dots = 99;
//The first time in the loop handles an exception
bool first_loop = true;
// ------------ Prameters for adjusting the rtc
bool B1_active = false;
int buttonMode = 0;
int temp = 99;
bool rtc_lostPower = true; // Används till vad?
// ----------------------- SETUP ------------
void setup() {
button1.begin();
button2.begin();
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
FastLED.setBrightness( BRIGHTNESS );
while (!Serial) { };
Serial.begin(9600);
//Check if there is a working rtc
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
/*
//Print current time, store in now
DateTime now = rtc.now();
Serial.print(" (");
Serial.print(__DATE__);
Serial.print(' ');
Serial.print(__TIME__);
Serial.print(") ");
Serial.print("Current time: ");
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.println(now.unixtime());
*/
Serial.print("Initial buttonMode "); Serial.println (buttonMode);
Serial.println("Delay 2000");
delay(2000);
if (button1.pressed() ) { //Activate mode for adjusting RTC
B1_active = true;
Serial.print("SETUP B1 pressed. B1_active: "); Serial.println (B1_active);
Serial.print("SETUP Old buttonMode: "); Serial.println (buttonMode);
funcSelectMode ();
Serial.print("SETUP New buttonMode: "); Serial.println (buttonMode);
Serial.println();
}
} //end setup
//============== START LOOP ==========================
void loop() {
switch (B1_active) {
case 0: //False
Serial.println (" ");
Serial.print("LOOP no button. B1_active: "); Serial.println (B1_active);
// -----GET CURRENT DATE AND TIME FROM RTC --------------
funcGetCurrentDateTime ();
//----- If first time in loop since power was turned on --------------------
Serial.print("first_loop: "); Serial.println(first_loop);
if (first_loop) {
funcFirstLoop ();
}
//----- If current time is divided by five, continue
Serial.print("CHECK cur_mm divided by five? -- ");
Serial.print("cur_mm: ");
Serial.print(cur_mm);
Serial.print(" / display_mm ");
Serial.println(display_mm);
if ( (cur_mm % 5 == 0 ) && (cur_mm != display_mm) ) {
display_mm = cur_mm;
Serial.print("display_mm = cur_mm = ");
Serial.println(display_mm);
//---------- TURN OFF ALLS LEDS ---------------------
funcTurnOffAllLeds();
//funcHartOrTree (); //+++ NotHart and Tree not defined in this version of code
//---------- ADJUST HOUR DEPENDING ON MINUTES BEFORE/AFTER ----
funcAdjustHours();
//----------- LIGHT UP ALL LEDS ---------
funcLightUppAll ();
//----------- SHOW ALL LEDS!! -----------------------
Serial.println("FastLED.show ---------");
FastLED.show();
} // End of new five minutes intervall
//------------- FIND OUT NUMBER OF MINUTE DOTS AND SHOW THEM -------
funcLightUpDots();
delay(3000);
break;
case 1: //True: Button pressed for adjusting the rtc
if (button1.pressed() ) { //Step by step to next buttonMode
Serial.println(" ");
Serial.println("LOOP B1 pressed.");
Serial.print("Old buttonMode: "); Serial.println (buttonMode);
funcSelectMode ();
}
if (button2.pressed() ) { //change datetime depending on mode
Serial.print("B2 pressed when buttonMode = ");
Serial.println(buttonMode);
funcSelectDateTime ();
Serial.println("DateTime is: ");
funcPrintDateTime (cur_year, cur_month, cur_day, cur_tt, cur_mm);
}
break;
} //end switch
} //end loop
//------------------ FUNCTIONS --------------------
void funcPrintDateTime (int x_year, int x_month, int x_day, int x_tt, int x_mm) {
Serial.print(x_tt);
Serial.print(':');
Serial.print(x_mm);
Serial.print(' ');
Serial.print(x_year);
Serial.print('/');
Serial.print(x_month);
Serial.print('/');
Serial.print(x_day );
Serial.println(' ');
}
void funcGetCurrentDateTime () {
//----- Save current date and time in variable to
// make sure it does not change during the loop
DateTime now = rtc.now();
cur_tt = now.hour();
cur_mm = now.minute();
cur_year = now.year();
cur_month = now.month();
cur_day = now.day();
/*
cur_year = 2022 // ***
cur_month = 12; // ***
cur_day=24; // ***
cur_mm = 25; // ***
cur_tt=12; // ***
*/
//----- Adjust hour to 12-hour clock
if (cur_tt >12) {
cur_tt=cur_tt - 12;
}
Serial.print("FUNCGetCurrentDateTime -- ");
funcPrintDateTime (cur_year, cur_month, cur_day, cur_tt, cur_mm);
}
void funcFirstLoop () {
//When rtc turned on (first time in loop) adjust minutes to a five-intervall
Serial.println("FIRST time in loop -- ");
Serial.print("first_loop: "); Serial.println(first_loop);
funcGetCurrentDateTime ();
cur_dots = (cur_mm % 5);
cur_mm = cur_mm - cur_dots;
cur_dots = 99;
first_loop = false;
Serial.print("cur_mm: ");
Serial.println(cur_mm);
}
void funcTurnOffAllLeds() {
Serial.print("funcTurnOffAllLeds ");
Serial.println(" ");
for (int i = 0; i < myNumLeds; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();
delay(500);
}
void funcAdjustHours () {
//Adjust the hour depending on current five minute intervall
//8:00 to 8:20 show ÅTTA,
//8:25 to 8:55 show NIO
//12:20 show TOLV. 12:25 show ETT.
if (display_mm >= 25 && cur_tt < 12 ) {
display_tt = cur_tt+1;
}
else if (display_mm >= 25 && cur_tt == 12){
display_tt = 1;
}
else display_tt = cur_tt;
Serial.print("ADJUST hours -- ");
Serial.print("cur_tt: ");
Serial.print(cur_tt);
Serial.print(" / display_tt_ ");
Serial.println(display_tt);
}
void funcLightUppAll (){
//----------- LIGHT UP FIXED TEXT "KLOCKA ÄR" ---------
funcLightUpFixedText();
//----------- LIGHT UP MINUTES ------------------------
funcLightUpMinutes(display_mm);
//----------- LIGHT UP HOUR --------------------------
funcLightUpHour(display_tt);
}
void funcLightUpFixedText() {
sizeOfCurrentArray = klockanArLength;
lightUpLed(klockanAr,sizeOfCurrentArray,CRGB::Blue);
}
void funcLightUpMinutes(int x) {
//Light up leds showing minutes (and över/i/halv)
Serial.print("FUNCLightUpMinutes -- ");
Serial.print("x = ");
Serial.println (x);
switch (x) {
case 0:
//heltimme
break;
case 5:
sizeOfCurrentArray = femMinOverLength;
lightUpLed(femMinOver,sizeOfCurrentArray,CRGB::Orange);
break;
case 10:
sizeOfCurrentArray = tioMinOverLength;
lightUpLed(tioMinOver, sizeOfCurrentArray, CRGB::Purple);
break;
case 15:
sizeOfCurrentArray = femtonMinOverLength;
lightUpLed(femtonMinOver, sizeOfCurrentArray, CRGB::Red);
break;
case 20:
sizeOfCurrentArray = tjugoMinOverLength;
lightUpLed(tjugoMinOver, sizeOfCurrentArray, CRGB::Blue);
break;
case 25:
sizeOfCurrentArray = femMinIHalvLength;
lightUpLed(femMinIHalv, sizeOfCurrentArray, CRGB::Red);
break;
case 30:
sizeOfCurrentArray = trettioMinILength;
lightUpLed(trettioMinI, sizeOfCurrentArray, CRGB::Pink);
break;
case 35:
sizeOfCurrentArray = femMinOverHalvLength;
lightUpLed(femMinOverHalv, sizeOfCurrentArray, CRGB::Magenta);
break;
case 40:
sizeOfCurrentArray = tjugoMinILength;
lightUpLed(tjugoMinI, sizeOfCurrentArray, CRGB::Orange);
break;
case 45:
sizeOfCurrentArray = femtonMinILength;
lightUpLed(femtonMinI, sizeOfCurrentArray, CRGB::Yellow);
break;
case 50:
sizeOfCurrentArray = tioMinILength;
lightUpLed(tioMinI, sizeOfCurrentArray, CRGB::Magenta);
break;
case 55:
sizeOfCurrentArray = femMinILength;
lightUpLed(femMinI, sizeOfCurrentArray, CRGB::LightPink);
break;
}
}
void funcLightUpHour(int x) {
//Light up leds showing the hour
Serial.print("FUNCLightUpHour -- ");
Serial.print("x = ");
Serial.println (x);
switch (x) {
case 1:
sizeOfCurrentArray = timLengthTre;
lightUpLed(ettTim, sizeOfCurrentArray, CRGB::Blue);
break;
case 2:
sizeOfCurrentArray = timLengthTre;
lightUpLed(tvaTim, sizeOfCurrentArray, CRGB::Red);
break;
case 3:
sizeOfCurrentArray = timLengthTre;
lightUpLed(treTim, sizeOfCurrentArray, CRGB::Yellow);
break;
case 4:
sizeOfCurrentArray = timLengthFyra;
lightUpLed(fyraTim, sizeOfCurrentArray, CRGB::Green);
break;
case 5:
sizeOfCurrentArray = timLengthTre;
lightUpLed(femTim, sizeOfCurrentArray, CRGB::Blue);
break;
case 6:
sizeOfCurrentArray = timLengthTre;
lightUpLed(sexTim, sizeOfCurrentArray, CRGB::Red);
break;
case 7:
sizeOfCurrentArray = timLengthTre;
lightUpLed(sjuTim, sizeOfCurrentArray, CRGB::Yellow);
break;
case 8:
sizeOfCurrentArray = timLengthFyra;
lightUpLed(attaTim, sizeOfCurrentArray, CRGB::Green);
break;
case 9:
sizeOfCurrentArray = timLengthTre;
lightUpLed(nioTim, sizeOfCurrentArray, CRGB::Blue);
break;
case 10:
sizeOfCurrentArray = timLengthTre;
lightUpLed(tioTim, sizeOfCurrentArray, CRGB::Red);
break;
case 11:
sizeOfCurrentArray = timLengthFyra;
lightUpLed(elvaTim, sizeOfCurrentArray, CRGB::Yellow);
break;
case 12:
sizeOfCurrentArray = timLengthFyra;
lightUpLed(tolvTim, sizeOfCurrentArray, CRGB::Green);
break;
case 0:
sizeOfCurrentArray = timLengthFyra;
lightUpLed(tolvTim, sizeOfCurrentArray, CRGB::Green);
break;
}
}
void funcLightUpDots() {
//Find out number of dots to light up
cur_dots = (cur_mm % 5);
Serial.print("FUNCLightUpDots -- ");
Serial.print("cur_dots: ");
Serial.print(cur_dots);
Serial.print(" / display_dots: ");
Serial.println(display_dots);
//If number of dots > 0 and it is a new number, light up dots
if ((cur_dots > 0) && (cur_dots != display_dots)) { // new dot
display_dots = cur_dots ;
Serial.print("display_dots ");
Serial.println(display_dots);
sizeOfCurrentArray = display_dots;
lightUpLed(minutPunkter, sizeOfCurrentArray, CRGB::Red);
//----------- Show all leds once again ----------
FastLED.show();
}
}
void funcSelectMode () {
// Change to next buttonMode and show corresponding text
buttonMode = buttonMode + 1;
if (buttonMode > 4) {buttonMode = 1;}
Serial.print("New buttonMode: "); Serial.println (buttonMode);
funcTurnOffAllLeds();
display_tt = 99;
display_mm = 99;
switch (buttonMode) {
case 1: //NY TIM
sizeOfCurrentArray = 5;
lightUpLed(textNyTim, sizeOfCurrentArray, CRGB::Blue);
FastLED.show();
break;
case 2: //NY MIN
sizeOfCurrentArray = 5;
lightUpLed(textNyMin, sizeOfCurrentArray, CRGB::Blue);
FastLED.show();
break;
case 3: //SAVE
sizeOfCurrentArray = 4;
lightUpLed(textNySave, sizeOfCurrentArray, CRGB::Blue);
FastLED.show();
Serial.println("SAVE ");
break;
case 4: //EXIT
sizeOfCurrentArray = 4;
lightUpLed(textNyExit, sizeOfCurrentArray, CRGB::Blue);
FastLED.show();
Serial.println("EXIT ");
break;
} //end switch
}
void funcSelectDateTime () {
funcTurnOffAllLeds();
switch (buttonMode) {
case 1: // add one hour (but not the first time) and show tt and mm
if (display_tt == 99) {
display_tt = 98; funcSelectHourMinutes(); break;
}
cur_tt = cur_tt + 1;
if (cur_tt > 12) {cur_tt = 1;}
funcSelectHourMinutes();
break;
case 2: // add fime minutes (but not the first time) and show tt and mm
if (display_mm == 99) {
display_mm = 98; funcSelectHourMinutes(); break;
}
cur_mm = cur_mm + 5;
if (cur_mm > 55) {cur_mm = 0;}
funcSelectHourMinutes();
break;
case 3: //Save: Set RTC to new DateTime
funcAdjustRTC ();
break;
case 4: //Exit
B1_active = false;
Serial.print("EXIT confirmed with Button 2. B1_active: ");
Serial.println(B1_active);
break;
} //end switch
}
void funcAdjustRTC () {
// Set RTC-clock
Serial.println("Adjust RTC ");
funcReversAdjustHours ();
Serial.println("Check RTC input is valid data. HOW TO?? ");
//if (no change of DateTime) skip rtc.adjust -- HOW?
//++++++ rtc.adjust(DateTime (cur_year, cur_month, cur_day, cur_tt, cur_mm, 0));
Serial.println("RTC updated: ");
funcPrintDateTime (cur_year, cur_month, cur_day, cur_tt, cur_mm);
/*
Example found:
setTime(19,14,59,14,9,2013);
setTime (display_tt, display_mm, 0, display_day, display_month, display_year);
RTC.set(now());
eller
RTC.adjust(DateTime(2014,12,30,8,45,0));//year,month,day,hour,minute,second
RTC.adjust(DateTime(yearupg,monthupg,dayupg,hourupg,minupg,0));
RTC.adjust(DateTime(__DATE__, __TIME__));//compile time
RTC.adjust(DateTime(1388534400));//unixTimeStamp
RTC.adjust(DateTime(unixTimeStamp));//by reference
How to use DateTime::isValid() ???
*/
}
void funcReversAdjustHours () {
Serial.print("funcReversAdjustHours: ");
funcPrintDateTime (cur_year, cur_month, cur_day, cur_tt, cur_mm);
//Adjust the hour depending on current five minute intervall
//Selected "tjugo över åtta" save kl 08,
//Selected "fem i halv åtta" to "fem i åtta" save kl 07
//Selected "tjugo över ett" save kl 01.
//Selected "fem i halv ett" save 12.
if (cur_mm >= 25 && cur_tt > 1 ) {
cur_tt = cur_tt-1;
}
else if (cur_mm >= 25 && cur_tt == 1){
cur_tt = 12;
}
else cur_tt = cur_tt;
Serial.print("Reversed Adjust Hours: ");
funcPrintDateTime (cur_year, cur_month, cur_day, cur_tt, cur_mm);
}
void funcSelectHourMinutes () {
funcLightUpHour(cur_tt);
funcLightUpMinutes(cur_mm);
FastLED.show();
}
int lightUpLed(int* ledArray,int ledArraySize, CRGB colorOfLed) {
//Light up specified leds
Serial.print(" ledArraySize ");
Serial.println(ledArraySize);
for (byte i = 0; i < ledArraySize; i++) {
leds[ledArray[i]] = colorOfLed;
}
}
/*
void funcShowLedsOneByOne () {
// *** Show all leds one by one to make sure they are ok
funcTurnOffAllLeds();
for (int i = 0; i < 100; i++) {
// Turn one LED on, then pause
leds[i] = CRGB::Blue;
Serial.print("loop i = ");
Serial.println(i);
FastLED.show();
delay(500);
// Now turn the LED off, then pause
leds[i] = CRGB::Black;
FastLED.show();
//delay(500);
}
}
*/