Radiosveglia con matrice led dotmatrix

Ciao a tutti.
In questo periodo ho nuovamente un po' di tempo per dedicarmi ad Arduino.
Vorrei riuscire a concretizzare un'idea di quasi 2 anni fa.

Questo era il topic originale: https://forum.arduino.cc/t/creare-passo-a-passo-radiosveglia-con-dot-matrix/693927

I problemi sono rimasti gli stessi, ma credo sia meglio affrontare un problema per volta.
La parte radio FM e temperatura, devo ancora studiarla e inserirla nel programma completo.
Nella parte di data/ora e sveglia è quasi completa, ma non riesco a venire a capo per la gestione del posponi.

Se necessario copio le parti che interessano qui dal topic originale.
Grazie per l'aiuto.

Credo che lo sia

Questo è il programma che sono riuscito a mettere assieme, prendendo spunto online e modificandolo per le mie necessità.
Manca la parte della Radio FM e rilevamento temperatura che devo ancora implementare, ma un passo per volta. :slightly_smiling_face:
Ho usato uno schermo oled per comodità, a tempo debito dovrò convertirlo tutto per visualizzarlo su Dot Matrix.

Ora il mio problema, non sono capace a far funzionare il posponi come vorrei.
La sveglia ha 4 pulsanti, quando suona la sveglia, premendone uno qualsiasi, vorrei posporre tutto per 5 minuti e via così finchè non disattivo l'allarme.
Per disattivare l'allarme vorrei premere un pulsante specifico per tot secondi, così da evitare pressioni involontarie.

Grazie per l'aiuto. :ok_hand:
PS. Non ci sono problemi per qualunque modifica e miglioramento in generale al codice, ogni consiglio è ben accetto

// Includo le librerie per RTC, OLED
#include <Wire.h>
#include "RTClib.h"
#include <U8x8lib.h>

// Assegno i nomi allo schermo OLED, RTC, BMP280 e RadioFM
U8X8_SSD1306_128X64_ALT0_HW_I2C oled;
RTC_DS1307 rtc;

// Definisco i PIN per pulsanti e cicalino
#define pulsante1 4   // Pulsante radio e diminuisci valore
#define pulsante2 5   // Pulsante sveglia e aumenta valore
#define pulsante3 3   // Pulsante OK e volume -
#define pulsante4 2   // Pulsante dataora e volume +
#define cicalino 6

// Imposto lo stato dei pulsanti a 0 e giorni per RTC
int stato = 0;
char str[3];
char settimana[7][4] = {"dom", "lun", "mar", "mer", "gio", "ven", "sab"};
DateTime now;

// Imposto variabili per la sveglia
int alarmh, alarmm;
int alarms = 0; // Messo a 0, così non imposto i secondi della sveglia, quando scatta il minuto suona
bool ALARM = false;
unsigned long t_pulsanteoff = 0;

void setup() {
  Wire.begin();
  Serial.begin(9600);

  // Imposto i PIN, per i pulsanti e per il buzzer
  pinMode(pulsante1, INPUT);
  pinMode(pulsante2, INPUT);
  pinMode(pulsante3, INPUT);
  pinMode(pulsante4, INPUT);
  pinMode(cicalino, OUTPUT);

  // Inizializzo lo schermo OLED e imposto il font
  oled.begin();
  oled.setFont(u8x8_font_5x7_f);

  // Inizializzo RTC e imposto data e ora
  if (! rtc.begin()) {
    Serial.println("Errore RTC");
    abort();
  }
  if (! rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop() {
  // Nel loop gira nei vari stati della radiosveglia
  switch (stato) {
    case 0:
      dataora();
      break;
    case 1:
      impostaOra();
      break;
    case 2:
      impostaMinuti();
      break;
    case 3:
      impostaSecondi();
      break;
    case 4:
      impostaGiorno();
      break;
    case 5:
      impostaMese();
      break;
    case 6:
      impostaAnno();
      break;
    case 10:
      accendiSveglia();
      break;
    case 11:
      impostaOraSveglia();
      break;
    case 12:
      impostaMinutiSveglia();
      break;
    case 20:
      allarmeSveglia();
      break;
    case 21:
      posponiSveglia();
      break;
    case 30:
      radioFM();
      break;
    case 40:
      meteo();
      break;
  }
}

bool FIRST = true;
unsigned long t1, dt;
int ch, cm, cs;

// stato 0 - Schermata principale dove visualizzo data/ora e se sveglia attiva
void dataora() {
  if (FIRST) {
    oled.clear();
    t1 = millis();
    FIRST = false;
  }

  // Assegno i nomi ch, cm, cs per visualizzare l'RTC
  dt = millis() - t1;
  if (dt > 500) {
    now = rtc.now();
    ch = now.hour();
    cm = now.minute();
    cs = now.second();

    oled.setCursor(0, 0);

    // Visualizzo ora, minuti e secondi sul display
    sprintf(str, "%02d", ch);
    oled.print(str);
    oled.print(":");
    sprintf(str, "%02d", cm);
    oled.print(str);
    oled.print(":");
    sprintf(str, "%02d", cs);
    oled.print(str);

    // Se la sveglia è accesa scrivo ON, se spenta visualizzo la data corrente
    oled.setCursor(0, 1);
    if (ALARM) {
      oled.print("ON");
    } else {
      oled.print(settimana[now.dayOfTheWeek()]);
      oled.print(" ");
      oled.print(now.day(), DEC);
      oled.print('/');
      oled.print(now.month(), DEC);
      oled.print('/');
      oled.print(now.year(), DEC);
    }

    // Se ora, minuti e secondi sono uguali a quelli impostati per la sveglia, vai allo stato 20 - allarmeSveglia();
    if ( (ch == alarmh) && (cm == alarmm) && (cs == alarms)) {
      stato = 20;
      FIRST = true;
    }
    t1 = millis();
  }

  // Se premi pulsante4, vai allo stato 1 - impostaOra();
  if (digitalRead(pulsante4)) {
    stato = 1;
    delay(200);
    FIRST = true;
  }

  // Se premi pulsante2, vai allo stato 10 - accendiSveglia();
  if (digitalRead(pulsante2)) {
    stato = 10;
    delay(200);
    FIRST = true;
  }

  // Se premi pulsante1, vai allo stato 30 - radioFM();
  if (digitalRead(pulsante1)) {
    stato = 30;
    delay(200);
    FIRST = true;
  }

  // Se premi pulsante3, vado allo stato 40 - meteo();
  if (digitalRead(pulsante3)) {
    stato = 40;
    delay(200);
    FIRST = true;
  }

  // Se premo il pulsante2 per 5 secondi, cambio lo stato della sveglia per spegnerla.
  if (digitalRead(pulsante2) == HIGH) {
    t_pulsanteoff = millis();
  }
  else  {
    if ((millis() - t_pulsanteoff) >= 5000)
    {
      ALARM = !ALARM;
      delay(200);
    }
  }
}

// Imposto la variabile seth a 0, nel void impostaOra() assegno alla variabile l'ora
int seth = 0;

// stato 1 - Qui imposto l'ora
void impostaOra() {       // Recupero l'ora dal RTC e viene assegnata a seth
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    seth = now.hour();
    FIRST = false;
  }
  // Visualizzo a schermo che viene modificata l'ora, minuti e secondi sono tratteggiati
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , seth);
  oled.print(str);
  oled.print(" : -- : --");

  // Se premi pulsante2, aumento le ore, arrivato a 24, riparte da 0
  if (digitalRead(pulsante2)) {
    seth++;
    if (seth >= 24) seth = 0;
    delay(200);
  }

  // Se premi il pulsante1, diminuisco le ore, arrivato a 0, torna a 23
  if (digitalRead(pulsante1)) {
    seth--;
    if (seth < 0) seth = 23;
    delay(200);
  }

  // Se premo il pulsante3, salvo l'ora impostata nel RTC e vado nello stato 02 - void impostaMinuti();
  if (digitalRead(pulsante3)) {
    rtc.adjust(DateTime(now.year(), now.month(), now.day(), seth, now.minute(), now.second()));
    stato = 02;
    FIRST = true;
    delay(200);
  }
}

// Imposto la variabile setm a 0, nel void impostaMinuti() assegno alla variabile i minuti
int setm = 0;

// stato 2 - Qui imposto i minuti
void impostaMinuti() {
  // Recupero i minuti dal RTC e li assegno alla variabile setm
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    setm = now.minute();
    FIRST = false;
  }
  // Visualizzo a schermo che vengono modificati i minuti, ora e secondi sono tratteggiati
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , setm);
  oled.print("-- : ");
  oled.print(str);
  oled.print(" : --");

  // Se premi il pulsante2, aumento i minuti, arrivato a 60 riparto da 0
  if (digitalRead(pulsante2)) {
    setm++;
    if (setm >= 60) setm = 0;
    delay(200);
  }

  // Se premi il pulsante1, diminuisco i minuti, arrivato a 0 riparto da 59
  if (digitalRead(pulsante1)) {
    setm--;
    if (setm < 0) setm = 59;
    delay(200);
  }

  // Se premi il pulsante3, salvo i minuti impostati nel RTC e vado allo stato 3 - impostaSecondi()
  if (digitalRead(pulsante3)) {
    rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), setm, now.second()));
    stato = 03;
    FIRST = true;
    delay(200);
  }
}
// Imposto la variabile sets a 0, nel void impostaSecondi() assegno alla variabile i secondi
int sets = 0;

// stato 3 - Qui imposto i secondi
void impostaSecondi() {
  // Recupero i secondi dal RTC e li assegno alla variabile sets
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    sets = now.second();
    FIRST = false;
  }
  // Visualizzo a schermo che vengono modificati i secondi, ora e minuti sono tratteggiati
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , sets);
  oled.print("-- : -- : ");
  oled.print(str);

  // Se premi il pulsante2, aumento i secondi, se arrivano a 60, riparte da zero
  if (digitalRead(pulsante2)) {
    sets++;
    if (sets >= 60) sets = 0;
    delay(200);
  }

  // Se premi il pulsante1, diminuisco i secondi, se arrivano a 0, riparte da 59
  if (digitalRead(pulsante1)) {
    sets--;
    if (sets < 0) sets = 59;
    delay(200);
  }

  // Se premo il pulsante3, salvo i secondi impostati nel RTC e vado allo stato 4 - impostaGiorno()
  if (digitalRead(pulsante3)) {
    rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), sets));
    stato = 4;
    FIRST = true;
    delay(200);
  }
}

// Imposto la variabile setg a 0, nel void impostaGiorno() assegno alla variabile il giorno
int setg = 0;

// stato 4 - Qui imposto il giorno della data
void impostaGiorno() {
  // Recupero il giorno dal RTC e assegno alla variabile setg
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    setg = now.day();
    FIRST = false;
  }
  // Visualizzo a schermo che viene modificato il giorno, mese e anno sono tratteggiati
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , setg);
  oled.print(str);
  oled.print("/--/----");

  // Se premo il pulsante2, aumento i giorni, se arrivano a 31, riparte da 1
  if (digitalRead(pulsante2)) {
    setg++;
    if (setg > 31) setg = 1;
    delay(200);
  }

  // Se premo il pulsante1, diminuisco i giorni, se arriva a 1, riparte da 31
  if (digitalRead(pulsante1)) {
    setg--;
    if (setg < 1) setg = 31;
    delay(200);
  }

  // Se premo il pulsante3, salvo il giorno impostato nel RTC e vado allo stato 5 - impostaMese()
  if (digitalRead(pulsante3)) {
    rtc.adjust(DateTime(now.year(), now.month(), setg, now.hour(), now.minute(), now.second()));
    stato = 5;
    FIRST = true;
    delay(200);
  }
}

// Imposto la variabile setmese 0, nel void impostaMese() assegno alla variabile il mese
int setmese = 0;

// stato 5 - Qui imposto il mese della data
void impostaMese() {
  // Recupero il mese dal RTC e assegno alla variabile setmese
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    setmese = now.month();
    FIRST = false;
  }
  // Visualizzo a schermo che viene modificato il mese, giorno e anno sono tratteggiati
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , setmese);
  oled.print("--/");
  oled.print(str);
  oled.print("/----");

  // Se premo il pulsante2, aumento i mesi, se arrivano a 12, riparte da 1
  if (digitalRead(pulsante2)) {
    setmese++;
    if (setmese > 12) setmese = 1;
    delay(200);
  }

  // Se premo il pulsante1, diminuisco i mesi, se arriva a 1, riparte da 12
  if (digitalRead(pulsante1)) {
    setmese--;
    if (setmese < 1) setmese = 12;
    delay(200);
  }

  // Se premo il pulsante3, salvo il mese impostato nel RTC e vado allo stato 6 - impostaAnno()
  if (digitalRead(pulsante3)) {
    rtc.adjust(DateTime(now.year(), setmese, now.day(), now.hour(), now.minute(), now.second()));
    stato = 6;
    FIRST = true;
    delay(200);
  }
}

// Imposto la variabile setanno = 2021, nel caso perdo data/ora non devo scorrere tutti i millenni
int setanno = 2021;

// stato 6 - Qui imposto l'anno della data
void impostaAnno() {
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    FIRST = false;
  }
  // Visualizzo a schermo che viene modificato l'anno, giorno e mese sono tratteggiati
  oled.setCursor(0, 0);
  oled.print("--/--/ ");
  oled.print(setanno);

  // Se premo il pulsante2, aumento l'anno
  if (digitalRead(pulsante2)) {
    setanno++;
    delay(200);
  }

  // Se premo il pulsante1, diminuisco l'anno
  if (digitalRead(pulsante1)) {
    setanno--;
    delay(200);
  }

  // Se premo il pulsante3, salvo l'anno impostato nel RTC e vado allo stato 0 - DataOra()
  if (digitalRead(pulsante3)) {
    rtc.adjust(DateTime(setanno, now.month(), now.day(), now.hour(), now.minute(), now.second()));
    stato = 0;
    FIRST = true;
    delay(200);
  }
}

// stato 10 - Qui attivo la sveglia
void accendiSveglia() {
  if (FIRST) {
    oled.clear();
    oled.setCursor(0, 0);
    oled.print("Sveglia: ");
    FIRST = false;
  }
  // In base allo stato di ALARM, scrivo se la sveglia è attiva o spenta
  oled.setCursor(10, 0);
  if (ALARM) {
    oled.print("ON ");
  }
  else {
    oled.print("OFF");
  }
  // Se premo pulsante1 o pulsante2, cambio lo stato attuale della sveglia
  if (digitalRead(pulsante1) || digitalRead(pulsante2)) {
    ALARM = !ALARM;
    delay(200);
  }
  // Premendo il pulsante3, confermo lo stato della sveglia
  // Se spenta vado alla schermata principale - stato 0, se accesa vado allo stato 11 - impostaOraSveglia()
  if (digitalRead(pulsante3)) {
    if (!ALARM) stato = 0;
    else stato = 11;
    FIRST = true;
    delay(300);
  }
}

// stato 11 - Qui imposto alla variabile alarmh l'ora corrente
void impostaOraSveglia() {
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    alarmh = now.hour();
    FIRST = false;
  }
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , alarmh);
  oled.print(str);
  oled.print(" : -- : -- A");

  // Se premo il pulsante2, aumento le ore per la sveglia
  if (digitalRead(pulsante2)) {
    alarmh++;
    if (alarmh >= 24) alarmh = 0;
    delay(200);
  }

  // Se premo il pulsante1, diminuisco le ore per la sveglia
  if (digitalRead(pulsante1)) {
    alarmh--;
    if (alarmh < 0) alarmh = 23;
    delay(200);
  }

  // Se premo il pulsante3, confermo l'ora impostata e vado allo stato 12 - impostaMinutiSveglia()
  if (digitalRead(pulsante3)) {
    stato = 12;
    FIRST = true;
    delay(200);
  }
}

// stato 12 - Qui imposto i minuti della sveglia
void impostaMinutiSveglia() {
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    alarmm = now.minute();
    FIRST = false;
  }
  oled.setCursor(0, 0);
  sprintf(str, "%02d" , alarmm);
  oled.print("-- : ");
  oled.print(str);
  oled.print(" : -- A");

  // Se premo il pulsante2, aumento i minuti della sveglia
  if (digitalRead(pulsante2)) {
    alarmm++;
    if (alarmm >= 60) alarmm = 0;
    delay(200);
  }

  // Se premo il pulsante1, diminuisco i minuti della sveglia
  if (digitalRead(pulsante1)) {
    alarmm--;
    if (alarmm < 0) alarmm = 59;
    delay(200);
  }

  // Se premo il pulsante3, salvo i minuti e torno alla schermata principale, stato 0 - dataora()
  if (digitalRead(pulsante3)) {
    stato = 0;
    FIRST = true;
    delay(200);
  }
}

// stato 20 - Si attiva quando, la data impostata per la sveglia è uguale a quella del RTC
void allarmeSveglia() {
  if (FIRST) {
    oled.clear();
    oled.setCursor(0, 0);
    oled.print("SVEGLIA!!");
    FIRST = false;
  }

  tone(6, 440, 100);
  delay(100);

  // Se premo uno qualsiasi dei 4 pulsanti, vado nello stato snooze
  if (digitalRead(pulsante1) || digitalRead(pulsante2) || digitalRead(pulsante3) || digitalRead(pulsante4)) {
    stato = 21;
    FIRST = true;
    delay(300);
  }
}

// Creo variabili per il posponi
int posponim1 = 0;
int posponim2 = 0;

// Attivo il posponi per 5 minuti, se premo il tasto 4 per 5 secondi disattivo la sveglia
void posponiSveglia() {
  noTone(6);
  if (FIRST) {
    oled.clear();
    now = rtc.now();
    posponim1 = now.minute();
    posponim2 = posponim1 + 1;
    alarmm = posponim2;
    stato = 0;
    FIRST = true;
    delay(200);
  }
}

// Stato 30 - Qui gestisco la radio FM
void radioFM() {
  Serial.print("funzione radio fm");
}

// Stato 40 - Qui gestisco per il meteo/temperatura
void meteo() {
  Serial.print("funzione meteo");
}

Ciao a tutti, tralasciando la parte di posponi, stavo cercando di progredire sulla parte di visualizzazione della matrice a led.
Ho evidenti difficoltà perchè quando riesco si illumina solo 1 quadrato o comunque al contrario.

A differenza del display oled o LCD, non riesco nemmeno a scrivere una parola
Sapete darmi una mano su come gestirla?

Grazie