pronoob94:
Vedo che non hai fatto commenti riguardo a come io ho imostato il tutto, nel senso che per gestire l'ora non vado a modificare l'ora attuale (perche non mi riesce) ma creo un altro orario (chiamato setting) nella quale incremento e decremento i valori delle costanti legate alle ore, minuti e secondi
Il primo motivo del non commento era l'ora/stanchezza
Poi anche io nella mia sveglia comodino per la regolazione ho usato variabili di appoggio, da scrivere nell'RTC solo in caso di effettiva modifica e conferma. Il codice che ho usato (solo il case della regolazione) è questo, ci sono un po' di assunzioni da fare, la prima è che i valori letti dall'RTC in un altro punto sono conservati in una struttura 'now', che solo alla fine viene aggiornata con i valori modificati e trascritta sull'RTC con la funzione 'setHour'. Ce ne sarebbero anche tante altre ('gmillis' che contiene il valore di 'millis' al ciclo di programma attuale, 't' che è una variabile tempo a 16 bit in grado di conteggiare fino a 65 secondi, 'onUp' 'onDn' 'onClic' 'onLpress' che valgono 1 per un ciclo in seguito alle azioni su un encoder, corrispondenti alle pressioni di equivalenti pulsanti ecc).
uint8_t primo = (fase != fasePrec);
if (primo) { fasePrec = fase; t = gmillis; }
uint16_t elapsed = (uint16_t)gmillis - t;
switch (fase)
{
case REGORA: // REGOLAZIONE ORA-MINUTI
if (primo)
{
s = 0; // 0 regola ora, 1 regola minuti
modify = 0; // 1 se modificato un valore
modHour = now.hour; // variabili modifica temporanee
modMinute = now.minute;
displayModHour(s, modHour, modMinute);
}
if (elapsed > 60000) { fase = PRINCIPALE; break; } // timeout 60s
else if (onClic) { beepClic(); t = gmillis; }
else if (onUp) { beepUp(); t = gmillis; }
else if (onDn) { beepDn(); t = gmillis; }
else if (onLpress) { beepLpress(); fase = PRINCIPALE; break; }
if (onUp)
{
if (0 == s) { modHour = (modHour + 1) % 24; }
else if (1 == s) { modMinute = (modMinute + 1) % 60; }
}
else if (onDn)
{
if (0 == s) { modHour = (modHour > 0) ? modHour-1 : 23; }
else if (1 == s) { modMinute = (modMinute > 0) ? modMinute-1 : 59; }
}
if (onUp || onDn) { modify = 1; displayModHour(s, modHour, modMinute); }
if (onClic && 0 == s) // passa a regolazione minuti
{
s = 1;
displayModHour(s, modHour, modMinute);
}
else if (onClic && 1 == s) // fine regolazione
{
fase = PRINCIPALE;
if (modify) { now.hour = modHour; now.minute = modMinute; setHour(); }
}
break;
}
La struttura now:
struct {
uint8_t hour = 0;
uint8_t minute = 0;
uint8_t second = 0;
uint8_t w_day = 1; // 1 = lunedi`
uint8_t m_day = 1;
uint8_t month = 1;
uint8_t year = 0;
} now;
Le funzioni per i beep:
void beepClic(void) { tone(SPEAKER, 500, 60); }
void beepLpress(void) { tone(SPEAKER, 1000, 60); }
void beepUp(void) { tone(SPEAKER, 3000, 10); }
void beepDn(void) { tone(SPEAKER, 2000, 10); }
La 'displayModHour' che non lampeggia ma "sottolinea" il campo in modifica con un carattere disegnato ad hoc:
void displayModHour(uint8_t s, uint8_t hour, uint8_t minute)
{
lcd.clear();
lcd.setCursor(0, 0);
char z[9];
sprintf(z, "%2d:%02d", hour, minute);
lcd.print(z);
if (0 == s) { lcd.setCursor(0, 1); lcdindicat(2); }
else if (1 == s) { lcd.setCursor(3, 1); lcdindicat(2); }
}
void lcdindicat(uint8_t n)
{
for (uint8_t i = 0 ; i < n ; i++) { lcd.write((uint8_t)2); }
}
La 'setHour' che non usa librerie RTC ma accede direttamente:
void setHour(void)
{
Wire.beginTransmission(0x68); // indirizzo RTC su bus i2c
Wire.write(0); // punta al registro 0
Wire.write(0); // azzera secondi RTC
Wire.write(binBCD(now.minute)); // imposta minuti RTC
Wire.write(binBCD(now.hour)); // imposta ore RTC
Wire.endTransmission();
}
uint8_t binBCD(uint8_t n) { return ((n / 10) << 4) | (n % 10); }