//Libreria per la gestione di NeoPixel
#include <Adafruit_NeoPixel.h>
#include <RTClib.h>
#include <SPI.h>
// Definizioni
//Pulsante On/Off
#define BTN_ON_OFF_PIN 7
//Pulsante per aumentare la luminosità
#define BTN_DIM_UP_PIN 3
//Pulsante per diminuire la luminosità
#define BTN_DIM_DOWN_PIN 4
//Pulsante per cambiare colore
#define BTN_COLOR_CHANGE_PIN 5
//Pulsante stato
#define BTN_STATE 6
//Pin Dati per NeoPixel
#define HOUR0_PIN 2
#define HOUR1_PIN 8
#define MIN0_PIN 9
#define MIN1_PIN 10
#define SEPARATOR_PIN 11
//Numero di LED della striscia
#define NUMPIXELS 28
#define SEPARATOR_PIXELS 2
//Fotoresistenza
#define PHOTORESISTOR_PIN A3
//Mappatura LED
#define ZERO (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 24, 25, 26, 27}
#define ONE (int[]){4, 5, 6, 7, 8, 9, 10, 11}
#define TWO (int[]){0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 14, 15, 20, 21, 22, 23,24, 25, 26, 27}
#define THREE (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 21, 22, 23}
#define FOUR (int[]){4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23}
#define FIVE (int[]){0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}
#define SIX (int[]){0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}
#define SEVEN (int[]){4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
#define EIGHT (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}
#define NINE (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}
//Istanzio oggetto NeoPixel
Adafruit_NeoPixel hour0 = Adafruit_NeoPixel(NUMPIXELS, HOUR0_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel hour1 = Adafruit_NeoPixel(NUMPIXELS, HOUR1_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel minute0 = Adafruit_NeoPixel(NUMPIXELS, MIN0_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel minute1 = Adafruit_NeoPixel(NUMPIXELS, MIN1_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel separator = Adafruit_NeoPixel(SEPARATOR_PIXELS, SEPARATOR_PIN, NEO_GRB + NEO_KHZ800);
//Definizione colori. I valori dei colori sono calcolati tenendo conton della luminosità
//La luminosità puà essere impostata su 5 valori, lo step fra l'uno e l'altro
//è pari a 51, partendo da 51 fino a 255, parto dalla metà che è pari a 153
//Valori validi per prima accensione dopo inseriento spina
#define WHITE hour0.Color(153, 153, 153) //Il colore rappresentato come unit32_t è 10066329
#define WARM_WHITE hour0.Color(153, 153, 138) //Il colore rappresentato come unit32_t è 10066314
#define RED hour0.Color(153, 0, 0) //Il colore rappresentato come unit32_t è 10027008
#define GREEN hour0.Color(0, 153, 0) //Il colore rappresentato come unit32_t è 39168
#define YELLOW hour0.Color(153, 153, 0) //Il colore rappresentato come unit32_t è 10066176
#define BLUE hour0.Color(0, 76, 153) //Il colore rappresentato come unit32_t è 19609
#define EMPTY hour0.Color(0, 0, 0)
// Stato del pulsante state
int state_ButtonState = 0;
// Ultimo stato del pulsante state
int state_LastButtonState = 0;
// State variable
static uint8_t state = 1;
//Variabile timer per pressione lunga
unsigned long t_pulsante = 0;
//Step di variazione della luminosità
unsigned int step = 51;
//Variabile di appoggio con il valore attuale dello step di luminosità
//per prima accensione dopo inserimento spina
unsigned int lum_corrente = 153;
//Variabile di buffer con il valore di luminosità attivo
//allo spegnimento della lampada
unsigned int buffer_luminosita = 0;
//Colore di partenza solo per prima accensione dopo inserimento spina
uint32_t colore = WHITE;
//Variabile di buffer con il colore attivo allo spegnimento della lampada
//Colori bufferColore = EMPTY;
uint32_t bufferColore = EMPTY;
//Ritardo per la funzione anti rimbalzo
int debounceDelay = 50;
//Variabile di verifica striscia On o Off
bool on = false;
//Variabili che contengono l'ora ed i minuti, vengono aggiornati dal modulo RTC
String ora = "00";
String minuti = "00";
//Create RTC_DS3231 instance
RTC_DS3231 rtc;
//Date & time variable
DateTime dateTime;
//Variables to store time characters to be printed
char strTime[7] = " ";
String timeLine = String();
//Variabile controllo passaggio minuti
int lastMinute = -1;
//Variabile controllo passaggio secondi
int lastSecond = -1;
//Variabile booleana che indica se i separatori sono accesi o spenti
bool SwitchedOn = false;
void setup()
{
hour0.begin();
hour1.begin();
minute0.begin();
minute1.begin();
separator.begin();
Serial.begin(9600);
//start I2C communication
if (!rtc.begin()) {
Serial.println("Impossibile trovare il modulo RTC");
Serial.flush();
while(1) delay(10);
}
//Da eliminare
//rtc.adjust(DateTime(2025, 3, 23, 20, 30, 0));
//getTime();
//set initial Date-Time
if (rtc.lostPower()) {
Serial.println("Imposto l'ora....");
// 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(2025, 3, 23, 20, 50, 0));
//rtc.adjust(strTime);
}
else Serial.println("Il modulo Rtc è in esecuzione....");
pinMode(BTN_STATE, INPUT);
Serial.println(luxmeter());
}
void loop()
{
/*On_Off();
getTime();
Dim_up();
Dim_down();
Change_color();*/
setState();
switch (state)
{
case 1:
getTime();
Show();
break;
case 2:
Dim_up();
Dim_down();
//getHour();
break;
case 3:
Change_color();
//getMinute();
break;
default:
break;
}
}
//========================== Funzioni =================================
//Funzione di gestione el tasto On/Off
void On_Off()
{
//Se premo il pulsante On/Off e la striscia è spenta
if (debounce(BTN_ON_OFF_PIN)==HIGH && !on) {
//Memorizzo il valore millis
t_pulsante = millis();
//Verifico se il pulsante On/Off rimane premuto
while(debounce(BTN_ON_OFF_PIN)==HIGH){
//Se rimane premuto per il tempo prefissato
if (millis() - t_pulsante >=1000) {
//Controllo che il buffer colore non sia vuoto,
//se non lo è, accendo i LED con quel valore
if (bufferColore != EMPTY) {
ShowHour(ora, bufferColore);
ShowMinute(minuti, bufferColore);
//Assegno il flag di striscia accesa
on = true;
} else {
//Assegno il colore tutti i LED della striscia
bufferColore = colore;
colore = bufferColore;
ShowHour(ora, bufferColore);
ShowMinute(minuti, bufferColore);
//Assegno il flag di striscia accesa
on = true;
}
}
}
}
//Se, invece, premo il pulsante On/Off e la striscia è accesa
else if (debounce(BTN_ON_OFF_PIN)==HIGH && on) {
//Salvo il valore di luminosità attivo
buffer_luminosita = lum_corrente;
//Salvo il colore attivo
bufferColore = colore;
//Spengo la striscia
Clear_LED();
//Assegno il flag di striscia spenta
on = false;
}
}
//Funzione che mostra l'orario
void Show() {
//Controllo che il buffer colore non sia vuoto,
//se non lo è, accendo i LED con quel valore
if (colore != EMPTY) {
ShowHour(ora, colore);
ShowMinute(minuti, colore);
} /*else {
//Assegno il colore tutti i LED della striscia
bufferColore = colore;
colore = bufferColore;
ShowHour(ora, bufferColore);
ShowMinute(minuti, bufferColore);
}*/
}
//Funzione di spegnimento della striscia
void Clear_LED() {
//Assegno il colore tutti i LED della striscia
for(int i = 0; i < NUMPIXELS; i++){
hour0.setPixelColor(i, EMPTY);
hour1.setPixelColor(i, EMPTY);
minute0.setPixelColor(i, EMPTY);
minute1.setPixelColor(i, EMPTY);
//Spengo la striscia (assegnando colore 0,0,0 si spegne la striscia)
hour0.show();
hour1.show();
minute0.show();
minute1.show();
}
}
void setState() {
state_ButtonState = digitalRead(BTN_STATE);
if(state_ButtonState != state_LastButtonState) {
if(state_ButtonState == HIGH) {
if(state == 4){
state = 1;
} else {
state = state + 1;
}
Serial.println(state);
}
// Delay per evitare il bouncing
delay(300);
}
state_LastButtonState = state_ButtonState;
}
//Funzione per aumentare la luminosità
void Dim_up() {
//Alla pressione del pulsante per aumentare la luminosità
if (debounce(BTN_DIM_UP_PIN)==HIGH) {
//Controllo che il valore di una delle tre variabili non sia
//già al massimo (le altre due seguono di pari passo)
if (lum_corrente < 255) {
//Salvo il valore di luminosità corrente
lum_corrente = lum_corrente + step;
switch (colore) {
//Se il colore è WHITE
case 10066329:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, lum_corrente, lum_corrente));
ShowMinute(minuti, hour0.Color(lum_corrente, lum_corrente, lum_corrente));
break;
//Se il colore è WARM_WHITE
case 10066314:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, lum_corrente, lum_corrente - 31));
ShowMinute(minuti, hour0.Color(lum_corrente, lum_corrente, lum_corrente - 31));
break;
//Se il colore è RED
case 10027008:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, 0, 0));
ShowMinute(minuti, hour0.Color(lum_corrente, 0, 0));
break;
//Se il colore è GREEN
case 39168:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(0, lum_corrente, 0));
ShowMinute(minuti, hour0.Color(0, lum_corrente, 0));
break;
//Se il colore è YELLOW
case 10066176:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, lum_corrente, 0));
ShowMinute(minuti, hour0.Color(lum_corrente, lum_corrente, 0));
break;
}
}
}
}
//Funzione per diminuire la luminosità
void Dim_down() {
//Alla pressione del pulsante per aumentare la luminosità
if (debounce(BTN_DIM_DOWN_PIN)==HIGH) {
//Controllo che il valore di una delle tre variabili non sia
//già al massimo (le altre due seguono di pari passo)
if (lum_corrente > 51) {
//Salvo il valore di luminosità corrente
lum_corrente = lum_corrente - step;
switch (colore) {
//Se il colore è WHITE
case 10066329:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, lum_corrente, lum_corrente));
ShowMinute(minuti, hour0.Color(lum_corrente, lum_corrente, lum_corrente));
break;
//Se il colore è WARM_WHITE
case 10066314:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, lum_corrente, lum_corrente - 31));
ShowMinute(minuti, hour0.Color(lum_corrente, lum_corrente, lum_corrente - 31));
break;
//Se il colore è RED
case 10027008:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, 0, 0));
ShowMinute(minuti, hour0.Color(lum_corrente, 0, 0));
break;
//Se il colore è GREEN
case 39168:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(0, lum_corrente, 0));
ShowMinute(minuti, hour0.Color(0, lum_corrente, 0));
break;
//Se il colore è YELLOW
case 10066176:
//Assegno ai LED i nuovi valori
ShowHour(ora, hour0.Color(lum_corrente, lum_corrente, 0));
ShowMinute(minuti, hour0.Color(lum_corrente, lum_corrente, 0));
break;
}
}
}
}
//Funzione per il cambio colore
void Change_color() {
//Alla pressione del pulsante per cambiare colore
if (debounce(BTN_COLOR_CHANGE_PIN)==HIGH) {
switch (colore) {
//Se il colore è WHITE
case 10066329:
colore = WARM_WHITE;
ShowHour(ora, colore);
ShowMinute(minuti, colore);
break;
//Se il colore è WARM_WHITE
case 10066314:
colore = RED;
ShowHour(ora, colore);
ShowMinute(minuti, colore);
break;
//Se il colore è RED
case 10027008:
colore = GREEN;
ShowHour(ora, colore);
ShowMinute(minuti, colore);
break;
//Se il colore è GREEN
case 39168:
colore = YELLOW;
ShowHour(ora, colore);
ShowMinute(minuti, colore);
break;
//Se il colore è YELLOW
case 10066176:
colore = BLUE;
ShowHour(ora, colore);
ShowMinute(minuti, colore);
break;
//Se il colore è BLUE
case 19609:
colore = WHITE;
ShowHour(ora, colore);
ShowMinute(minuti, colore);
break;
}
}
}
//Funzione antirimbalzo
boolean debounce(int pin) {
boolean state;
boolean previousState;
previousState = digitalRead(pin);
for(int counter=0; counter < debounceDelay; counter++) {
delay(1);
state = digitalRead(pin);
if( state != previousState) {
counter = 0;
previousState = state; }
}
return state;
}