ottimizzazione codice interruttore

Rieccomi, spiego cosa vorrei fare:
interruttore (non pulsante) collegato al pin2 con pull_up interna attivata.
Quando cambia lo stato del pin interruttore, deve cambiare lo stato del pin di uscita dove verrà collegato relè per gestire una strip led.
In caso di riavvio di arduino, si deve ripristinare lo stato precedente del pin di uscita (se i led erano accesi si devono riaccendere, se erano spenti rimangono spenti).
Ho aggiunto anche un debounce per sicurezza.
Questo è lo sketch:

#include <EEPROM.h>

int ledPin = 13;
int interruttorePin = 2;
int ledStato;
int interruttoreStato;
int lettura;
int attesaDebounce = 50;
unsigned long ultimoTempoDebounce = 0;
int ultimaLettura = LOW;


void setup(){ 
  ledStato = EEPROM.read(1);
  delay(50);  //inserito delay per dare il tempo di lettura alla eeprom
  pinMode(ledPin, OUTPUT);
  pinMode(interruttorePin, INPUT_PULLUP);
  digitalWrite(ledPin, ledStato);
  lettura = digitalRead(interruttorePin);
  interruttoreStato = digitalRead(interruttorePin);
}


void loop(){  
  lettura = digitalRead(interruttorePin);  // (int lettura = Variabile locale) leggo lo stato del pulsante
  if(lettura != ultimaLettura){            // se lo stato del pin è il contrario dell`ultima lettura
    ultimoTempoDebounce = millis();        // assegno il conteggio in millisecondi
  }

  if((millis() - ultimoTempoDebounce) > attesaDebounce){   // se il conteggio è superiore a 50 millisecondi
    if(lettura != interruttoreStato){      // se il pin2 è diverso dallo stato dell'intteruttore c'è stata variazione
      ledStato = !ledStato;                                // cambio lo stato del pin 13
      digitalWrite(ledPin, ledStato);                      // Imposto al pin13 lo stato di ledStato
      EEPROM.write(1, ledStato);                           //scrivo lo stato del led nella eeprom
    }
    interruttoreStato = lettura;                               // assegno lo stato dell'interruttore al pin2
  }

  ultimaLettura = lettura;                                 // assegno l`ultima lettura allo stato dell'interruttore
  delay(10);                                               // Ritardo 10 millis
}

Domande:

-il codice può andare bene o meglio ottimizzarlo magari utilizzando dei bool per gli stati visto che sono solo ON/OFF? Altre ottimizzazioni per snellire il tutto? (in futuro aggiungerò altri ingressi e relative uscite)

-Sto facendo dei test sfruttando il pin13 (out led) che però al riavvio esegue alcuni lampeggi (che a me non vanno bene) per poi portarsi nella condizione precedente. Il problema è relativo al pin13?
EDIT: sto testando con pin7 e non ho problemi relativi al pin13. Nessun lampeggio in accensione.

Poi dovrò affrontare il discorso del buffer circle per la eeprom.

Grazie!

Il pin 13 all'accensione lampeggia se non erro per via del bootloader che ti consente di caricare via USB i programmi, se non lo vuoi devi caricare i programmi con un programmatore ISP, se percò puoi usare anzi gli altri pin sarebbe meglio.
Uso delle variabili bool sicuramente si, non tanto per una reale esigenza di questo programma che essendo molto piccolo non da problemi di memoria ma per pulizia e forma mentis per il futuro.
Se vuoi replicare il codice per N ingressi ed uscite l'ideale sarebbe usare array (o strutture) per memorizzare i vari stati, millis, ecc. in modo da poter richiamare funzioni basate su indice dell'array per eseguire controlli, scritture in EEPROM e cambio stato del pin d'uscita, scrivi una volta usi molte :slight_smile:

Quel delay(10) il lo rimuoverei a che ti serve hai già il debounce software, anche se per ridurre il tutto all'osso e dimenticarsene per sempre ti consiglierei di passare a quello hardware di debounce e a quel punto diventa solo una digitalread e un controllo dello stato precedente, se differente salvi in eeprom e cambi l'uscita, molto meglio direi... poi vedi tu

Grazie fabpolli, gentilissimo!
Parto dal fondo, il delay(10) già rimosso!
Non ho grossi problemi di spazio quindi lascerei anche il debounce software per sicurezza.
Il pin13 posso non utilizzarlo visto che tanto lavoro con una Arduino Mega. Come da edit nel post precedente, utilizzando il pin7 al posto del 13 non ho alcun problema di lampeggio e quindi va benissimo così.
Array... qua per me si fa davvero complicata la cosa sono un babbissimo! In pratica andrò a comandare delle strip led (circa 6) ed avrò di conseguenza 6 interruttori (uno ovviamente per ogni pin) e relè (anche qua uno per ogni pin).
Correggo lo sketch con i bool ed aggiungo gli ingressi e le uscite necessarie al mio scopo ma la parte array la vedo dura.

Ancora grazie!

La domanda "il programma va bene o devo ottimizzarlo" é una domanda strana. Se un programma fa quello che il orogrammatore vuole é soluzione punto. Se il programma non fa quello che vuole il programmatore vi é ul problema, e va spiegato e risloto. Quanto a ottimizzazione si può fare. Ad esempio puoi sostituire con byte le variabili il cui massimo é 255. Eviterei bool, che occupa un byte per poter usare solo un bit. Aggiungerei 'const' a tutte le dichiarazioni di variabili il cui valore resta costante

Silente non è stato chiesto "il programma non va dove sbaglio?" ma "come faccio ad ottimizzarlo?" quindi se fa quel che deve non è la soluzione punto, è una soluzione, non è detto che sia la migliore. Se come tanti si fosse accontentato non avrebbe chiesto, evidentemente il suo scopo è migliorare e apprendere, che dovrebbe essere lo scopo di tutti altrimenti non si va da nessuna parte. La storia di evitare i bool è un inesattezza in quanto tra byte e bool lo spazio occupato in memoria è il medesimo ovvero un byte ma se esistono le tipizzazioni c'è un perché, ovvero aiutare la comprensione del codice e, eventualmente ricevere segnalazioni di warning dal compilatore se qualcosa viene utilizato in modo errato e/o che potrebbe portare a funzionamenti non sicuri/predicibili.

Poi:
Perché hai interruttoreatato? Quando lo usi?
Puoi anche rimuovere ledstato e comandare il led con HIGH o LOW. Oppure, se vuoi fare un cambio di stato, puoindire direttamente

digitalWrite (pin, !digitalRead (pin));

.
Comunque ricorda che non é indispensabile (specie con semplici progetti e tanta memoria). Se vuoi farlo..meglio

Silente:
Oppure, se vuoi fare un cambio di stato, puoindire direttamente

digitalWrite (pin, !digitalRead (pin));

Funziona solo su MCU classe AVR, ad esempio su Arduino Zero non funziona, quindi a meno che non sia indispensabile risparmiare un byte di memoria è sempre consigliabile utilizzare una variabile che mantenga lo stato anziché appoggiarsi ad una funzione che è scarsamente portabile e oltretutto impiega molto tempo ad essere eseguita rispetto a assegnare/leggere il valore di una variabile

Ok. E anche oggi ne ho imparata una

khriss75:
o meglio ottimizzarlo magari utilizzando dei bool per gli stati visto che sono solo ON/OFF?

Considerando che 1/0, HIGH/LOW, true/false, sono la stessa cosa (sempre byte 1 e 0 chiamati in altri modi), il loro diverso uso serve solo per chiarezza:

  • 1/0 si usano quando si stanno trattando valori numerici.
  • HIGH/LOW si usano per indicare esplicitamente i livelli di ingresso e uscita.
  • true/false si usano per variabili a due stati il cui nome sia una domanda a cui rispondere si o no. Ad esempio 'pippo', 'stato', 'fase', non sono buoni nomi per variabili bool, mentre 'ricevuto', 'finito', 'avviato', 'abilitato', si.

Come detto i nomi che rappresentano delle costanti (come i nomi dei pin) meglio definirli const (o usare delle #define) e scriverli maiuscoli (è una convenzione).

Le variabili locali ad una funzione che non devono mantenere il valore tra una chiamata e l'altra basta dichiararle all'interno.

Quelle che devono mantenere il valore si definiscono globali all'esterno, oppure static all'interno della funzione che le usa.

Quelle condivise tra più funzioni per forza globali.

non mi è chiaro, scusa
tu vuoi che ogni volta che azioni l'interruttore il led cambi stato
se è così io lo interpeto che ogni volta che l'interruttore cambia stato anche il led cambia stato
ma questo significa che lo stato del led è sempre congruo con lo stato dell'interruttore
questo significa che arduino non "cambia" l'informazione
e quindi non ti serve ne il debounce ne lo stesso arduino
basta che l'interruttore comandi direttamente il led

khriss75:
Rieccomi, spiego cosa vorrei fare:
interruttore (non pulsante) collegato al pin2 con pull_up interna attivata.
Quando cambia lo stato del pin interruttore, deve cambiare lo stato del pin di uscita dove verrà collegato relè per gestire una strip led.
In caso di riavvio di arduino, si deve ripristinare lo stato precedente del pin di uscita (se i led erano accesi si devono riaccendere, se erano spenti rimangono spenti).
Ho aggiunto anche un debounce per sicurezza.

Allora quando l' interuttore é su ON i LED sono accesi; quando l' interuttore é OFF i LED sono spenti?

loop(){
digitalWrite(ledPin , digitalRead(interruttorePin));
}

Concordo di evitare di usare il pin13.

Ciao Uwe

Standardoil:
non mi è chiaro, scusa
tu vuoi che ogni volta che azioni l'interruttore il led cambi stato
se è così io lo interpeto che ogni volta che l'interruttore cambia stato anche il led cambia stato
ma questo significa che lo stato del led è sempre congruo con lo stato dell'interruttore
questo significa che arduino non "cambia" l'informazione
e quindi non ti serve ne il debounce ne lo stesso arduino
basta che l'interruttore comandi direttamente il led

Ringrazio nuovamente tutti quelli che mi stanno supportando (e sopportando :slight_smile: )

Esatto Standardoil, io voglio che il led cambi di stato quando cambia di stato l'interruttore.
Questo però non significa che il led deve seguire lo stato dell'interruttore, come scritto sopra, ho bisogno che in caso di riavvio di arduino, il led deve tornare allo stato prima dello spegnimento.
Supponiamo che interruttore ON --> led ON, agendo sull'interruttore il led, come dici tu, seguirà lo stato dell'interruttore.
Ci troviamo con interruttore ON e led ON, ora supponiamo che arduino viene disalimentato e cambio lo stato dell'interruttore mentre arduino è spento (interruttore OFF). Rialimento arduino e grazie alla lettura nella eeprom mi riporta nuovamente il led ON (come era prima dello spegnimento) ma l'interruttore è OFF. Ora per spegnere il led devo portare interruttore ON...
Non so se mi sono spiegato.
In aggiunta sto implementando anche i comandi via MQTT quindi potrò gestire il led tramite interruttore e via mqtt. Ecco il perché voglio gestire il cambio stato.

Grazie anche a te Uwe per la conferma del pin13