// Include the required Arduino libraries:
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <RTClib.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
//Per applicazione reale
//#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
//Per simulazione
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define PAUSE_TIME 10
#define SCROLL_SPEED 150
#define CLK_PIN 13//10 //Giallo
#define CS_PIN 8//9 //Verde
#define DATA_PIN 11//8 //Blu
// Variabili per la gestione del debounce dei tasti
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 200;
// Button definitiom
const int functionButton = 3;
const int increaseButton = 4;
const int decreaseButton = 5;
// Ingresso sensore luminosità
const int ldr = 7;
// Stato del pulsante function
int functionButtonState = 0;
int increaseButtonState = 0;
int decreaseButtonState = 0;
// Ultimo stato del pulsante function
int last_functionButtonState = 0;
int last_increaseButtonState = 0;
int last_decreaseButtonState = 0;
// Create RTC_DS3231 instance
RTC_DS3231 rtc;
// Create Parola instance
//MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Date & time variable
DateTime dateTime;
// Variables to store date characters to be printed
char strDate[15] = " ";
String dateLine = String();
// Variables to store time characters to be printed
char strTime[7] = " ";
String timeLine = String();
// create array of a week days
char daysOfTheWeek[7][12] = {"Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"};
// State variable
static uint8_t state = 1;
void setup() {
// put your setup code here, to run once:
// initialize serial communication
// Per simulazione
Serial.begin(57600);
// Per applicazione reale
//Serial.begin(9600);
// start I2C communication
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
// set initial Date-Time
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
//rtc.adjust(DateTime(2023, 1, 21, 17, 20, 0));
getTime();
rtc.adjust(strTime);
// rtc.adjust(DateTime("2023-01-21T11:30:00"));
}
else Serial.println("Rtc is running....");
// Intialize the object:
myDisplay.begin();
// Set the intensity (brightness) of the display (0-15):
myDisplay.setIntensity(0);
// Clear the display:
myDisplay.displayClear();
pinMode(functionButton, INPUT);
pinMode(increaseButton, INPUT);
pinMode(decreaseButton, INPUT);
}
void getDate()
{
// read value from RTC module
dateTime = rtc.now();
dateLine.concat(daysOfTheWeek[dateTime.dayOfTheWeek()]);
dateLine.concat(" ");
dateLine.concat(dateTime.day());
dateLine.concat("/");
dateLine.concat(dateTime.month());
dateLine.concat("/");
dateLine.concat(dateTime.year());
dateLine.concat(" ");
dateLine.toCharArray(strDate, 15);
dateLine = "";
}
void setState()
{
functionButtonState = digitalRead(functionButton);
if (functionButtonState != last_functionButtonState)
{
if (functionButtonState == HIGH)
{
if (state == 3) {
state = 1;
} else {
state = state + 1;
}
}
else
{}
// Delay per evitare il bouncing
delay(300);
}
last_functionButtonState = functionButtonState;
}
void incHour()
{
increaseButtonState = digitalRead(increaseButton);
// Controlla se il pulsante è premuto E se è passato abbastanza tempo dall'ultima volta
if (increaseButtonState == HIGH && (millis() - lastDebounceTime > debounceDelay)) {
DateTime currentDateTime = rtc.now();
uint8_t hour = (currentDateTime.hour() + 1) % 24;
rtc.adjust(DateTime(currentDateTime.year(), currentDateTime.month(), currentDateTime.day(), hour, currentDateTime.minute(), currentDateTime.second()));
lastDebounceTime = millis(); // Reset del timer di debounce
myDisplay.displayClear(); // Forza il refresh del display per mostrare subito il cambio
}
}
void decHour()
{
decreaseButtonState = digitalRead(decreaseButton);
// Controlla se il pulsante è premuto E se è passato abbastanza tempo dall'ultima volta
if (decreaseButtonState == HIGH && (millis() - lastDebounceTime > debounceDelay)) {
DateTime currentDateTime = rtc.now();
uint8_t hour = (currentDateTime.hour() - 1) % 24;
rtc.adjust(DateTime(currentDateTime.year(), currentDateTime.month(), currentDateTime.day(), hour, currentDateTime.minute(), currentDateTime.second()));
lastDebounceTime = millis(); // Reset del timer di debounce
myDisplay.displayClear(); // Forza il refresh del display per mostrare subito il cambio
}
}
void incMinute()
{
// Leggi lo stato attuale del pulsante
int reading = digitalRead(increaseButton);
// 1. Rileva il fronte di salita (da LOW a HIGH)
// Questo assicura che l'azione avvenga solo nel momento in cui premi
if (reading == HIGH && last_increaseButtonState == LOW) {
// 2. Controllo anti-rimbalzo (Debounce)
if (millis() - lastDebounceTime > debounceDelay) {
// Operazioni sul tempo
DateTime currentDateTime = rtc.now();
uint8_t minute = (currentDateTime.minute() + 1) % 60;
rtc.adjust(DateTime(currentDateTime.year(),
currentDateTime.month(),
currentDateTime.day(),
currentDateTime.hour(),
minute,
currentDateTime.second()));
// 3. Feedback immediato sul display
myDisplay.displayClear(); // Pulisce il display
myDisplay.displayReset(); // Forza la libreria a ricominciare l'animazione con il nuovo dato
// Aggiorna il timestamp dell'ultima pressione valida
lastDebounceTime = millis();
}
}
// 4. Salva lo stato attuale per il confronto nel prossimo ciclo del loop
last_increaseButtonState = reading;
}
void decMinute()
{
// Leggi lo stato attuale del pulsante
int reading = digitalRead(increaseButton);
// 1. Rileva il fronte di salita (da LOW a HIGH)
// Questo assicura che l'azione avvenga solo nel momento in cui premi
if (reading == HIGH && last_increaseButtonState == LOW) {
// 2. Controllo anti-rimbalzo (Debounce)
if (millis() - lastDebounceTime > debounceDelay) {
// Operazioni sul tempo
DateTime currentDateTime = rtc.now();
uint8_t minute = (currentDateTime.minute() - 1) % 60;
rtc.adjust(DateTime(currentDateTime.year(),
currentDateTime.month(),
currentDateTime.day(),
currentDateTime.hour(),
minute,
currentDateTime.second()));
// 3. Feedback immediato sul display
myDisplay.displayClear(); // Pulisce il display
myDisplay.displayReset(); // Forza la libreria a ricominciare l'animazione con il nuovo dato
// Aggiorna il timestamp dell'ultima pressione valida
lastDebounceTime = millis();
}
}
// 4. Salva lo stato attuale per il confronto nel prossimo ciclo del loop
last_increaseButtonState = reading;
}
void getTime()
{
// read value from RTC module
dateTime = rtc.now();
if (dateTime.hour() < 10)
{
timeLine.concat("0");
timeLine.concat(dateTime.hour());
}
else
{
timeLine.concat(dateTime.hour());
}
timeLine.concat(":");
if (dateTime.minute() < 10)
{
timeLine.concat("0");
timeLine.concat(dateTime.minute());
}
else
{
timeLine.concat(dateTime.minute());
}
timeLine.concat(" ");
timeLine.concat(daysOfTheWeek[dateTime.dayOfTheWeek()]);
timeLine.concat(" ");
timeLine.concat(dateTime.day());
timeLine.concat("/");
timeLine.concat(dateTime.month());
timeLine.concat("/");
timeLine.concat(dateTime.year());
timeLine.concat(" ");
//timeLine.toCharArray(strTime, 6);
timeLine.toCharArray(strTime, 23);
timeLine = "";
}
void getHour()
{
// read value from RTC module
dateTime = rtc.now();
timeLine.concat("h ");
timeLine.concat(dateTime.hour());
timeLine.toCharArray(strTime, 6);
timeLine = "";
}
void getMinute()
{
// read value from RTC module
dateTime = rtc.now();
timeLine.concat("m ");
timeLine.concat(dateTime.minute());
timeLine.toCharArray(strTime, 6);
timeLine = "";
}
void loop() {
// 1. Leggi SEMPRE lo stato dei pulsanti (fuori da ogni IF di animazione)
setState();
// 2. Gestione degli ingressi in base allo stato attuale
if (state == 2) {
incHour();
decHour();
} else if (state == 3) {
incMinute();
decMinute();
}
// 3. Gestione Luminosità (ottimizzata)
int analogValue = analogRead(ldr);
int brightness = map(analogValue, 0, 1023, 0, 15); // Corretto errore sintassi map
myDisplay.setIntensity(brightness);
// 4. Animazione e Aggiornamento Display
if (myDisplay.displayAnimate()) {
switch (state) {
case 1:
getTime();
getDate();
// Qui puoi cambiare PA_PRINT con PA_SCROLL_LEFT o altro!
myDisplay.displayText(strTime, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_SCROLL_LEFT, PA_NO_EFFECT);
break;
case 2:
getHour();
myDisplay.displayText(strTime, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
break;
case 3:
getMinute();
myDisplay.displayText(strTime, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
break;
}
myDisplay.displayReset(); // Prepara il display per il prossimo ciclo
}
}