Scrittura EEprom Arduino

Ciao a tutti, dopo essere andato a leggere il datasheet del ATMega328 in merito al limite delle scritture in una casella EEprom, ho pensato di aggirare il problema della eventuale continua scrittura della stessa ad ogni ciclo di loop nel modo seguente:

Per la dichiarazione delle variabili:

//Leggo il valore scritto nella EEPROM nella prima casella
  int pippo = EEPROM.read(1);
  int NumCam = pippo;
const int pippoMax = 9;                         //limite massimo valore della variabile
const int pippoMin = 0;                         //limite minimo valore della variabile

All'interno del loop:

 //scrivo il nuovo valore nella EEPROM quando il valore di pippo è cambiato, questo per non riscrivere la EEPROM continuamente
  if (pippo != NumCam)
                  {
                    EEPROM.write(1, pippo);
                                      }

Ovvero leggo la variabile pippo dalla casella 1 della EEprom, poi creo un duplicato della stessa variabile che non variero' per poterla poi confrontare con la variabile NumCam che nel frattempo potrebbe essere variata. Se cio' capita allora riscrivero' il nuovo valore di pippo nella EEprom. Desideravo sapere, il codice cosi' scritto e' corretto? Chiedo questo poiche ' effettivamenti il programma "gira" ma dopo qualche giorno alla riaccensione della Atmega328 nn ha piu' presentato nessun valore (o meglio il diaplay era a zero).

Dagli spezzoni messi, non è molto chiaro quello che fai ...

All'inizio metti in pippo (... un nome di variabile più indicativo no eh ?!?!) il valore della EEPROM ; nel loop, se ben capisco, quella che cambia è NumCam, quindi, se pippo != da NumCam, allora devi aggiornare SIA pippo con il nuovo valore, che salvarlo poi nella EEPROM ! Al momento, per quanto hai scritto, NON mi sembra che tu aggiorni pippo con il nuovo valore e quindi, ad ogni giro del loop, pippo sarà sempre != da NumCam, anche se quest'ultimo non è nuovamente cambiato ... ;)

Giusto ???

Guglielmo

Se non sei sicuro di quello che il prog fa o vuoi verificare i passaggi usa il debug

 //scrivo il nuovo valore nella EEPROM quando il valore di pippo è cambiato, questo per non riscrivere la EEPROM continuamente
  if (pippo != NumCam)
                  {
                   Serial.println("il valore pippo è cambiato  .... pippo = "+(String)pippo+ "  *** NumCam= "+(String)NumCam);//debug
                    EEPROM.write(1, pippo);
                   Serial.println("scrittura su eeprom completata");//debug
                   //eeprom.read...........scrivi 1 riga per leggere il valore scritto su eeprom
                                      }

cambia gli int in byte, su eeprom vai a scrivere dei byte non degli interi

 byte pippo = EEPROM.read(1);
  byte NumCam = pippo;
const byte pippoMax = 9;                         //limite massimo valore della variabile
const byte pippoMin = 0;                         //limite minimo valore della variabile

Ciao, e grazie intanto per la celerita' nella risposta. Cio' che mi propongo di fare e' di avere, dopo la riaccensione, lo stesso numero che avevo precedentemente selezionato prima di spegnere l'ATMega328; questo per poterlo leggere su di un display a 7 segmenti. La variabile che uso per variarne il valore e' "pippo" (mi scuso per la poca fantasia ma all'inizio del progetto si trattava poco piu' di un gioco), che puo' essere cambiata da 0 a 9. Quindi [u]solo[/u] se varia durante il loop (premendo pulsanti che fanno aumentare + e - la variabile), la condizione pippo != NumCam dovrebbe scrivermi nella EEprom... Ma non sono sicuro che la condizione sia corretta.

@Pablos, intanto grazie anche a te. Ho lanciato il serial monitor che mi fa vedere come varia "pippo" ma c'e' un modo per vedere se la riscrive nella EEprom? se si ti prego di dirmelo poiche' nn lo capisco.

vai a leggere la cella 1 sulla eeprom e stampala sul serial

byte valore = EEPROM.read(1);
Serial.println("valore eeprom = " + (String)valore);//debug

@ pablos Riletto meglio cio che mi hai scritto:

 //scrivo il nuovo valore nella EEPROM quando il valore di pippo è cambiato, questo per non riscrivere la EEPROM continuamente
  if (pippo != NumCam)
                  {
                   Serial.println("il valore pippo è cambiato  .... pippo = "+(String)pippo+ "  *** NumCam= "+(String)NumCam);//debug
                    EEPROM.write(1, pippo);
                   Serial.println("scrittura su eeprom completata");//debug
                   //eeprom.read...........scrivi 1 riga per leggere il valore scritto su eeprom
                                      }

In effetti non pensavo di poter utilizzare un "controllo serial print" all'interno del ciclo if (pippo != NumCam). Cosi so esattamente quando il programma abilita la funzione di scrittura, giusto? Poiche' leggero' sul serial monitor

Poiche' la leggero' sul monitor... grazie!

@Guglielmo, In effetti avendo io assegnato la variabile NumCam all'inizio quando si assegna il valore alle variabili, prima del setup per intenderci, Num Cam ha sempre lo stesso valore... Ho provato a fare cosi: ho eliminato l'assegnazione di NumCam nelle variabili prima del setup (si chiamano variabili globali??? e per tanto immodificabili??? Mah...) e l'ho creata all'interno del ciclo Loop (int NumCam = pippo;) , in modo che ad ogni passaggio venga prima confrontata con "pippo" e se quest'ultima e' variata modifica la cella di memoria e poi modifichi anche il valore di NumCam subito dopo... Quindi se pippo non e' variato nel secondo passaggio nel loop, dovrei trovare NumCam uguale a pippo poiche' l'ho aggiornata nel passaggio prima. Giusto?

Non ho idea di come funzioni la libreria EEPROM di arduino, in avrlibc ci sono due funzioni, una scrive il valore effettivamente senza alcuna condizione, la seconda aggiorna i valore, cioè se è necessario scrive diversamente la scrittura vera non avviene.

void eeprom_update_byte (uint8_t *p, uint8_t __value) http://www.nongnu.org/avr-libc/user-manual/groupavr__eeprom.html#ga63aee2719099e8435e8584d4b3e51991

void eeprom_write_byte (uint8_t *p, uint8_t __value) http://www.nongnu.org/avr-libc/user-manual/groupavr__eeprom.html#ga682e0b2ca0badd47e1e30e61617e1361

ciao.

AndreaBaroni: ... ho eliminato l'assegnazione di NumCam nelle variabili prima del setup (si chiamano variabili globali??? e per tanto immodificabili??? Mah...) e l'ho creata all'interno del ciclo Loop (int NumCam = pippo;) , in modo che ad ogni passaggio venga prima confrontata con "pippo" e se quest'ultima e' variata modifica la cella di memoria e poi modifichi anche il valore di NumCam subito dopo... ...

L'assegnazione iniziale la potevi lasciare, va bene. L'importante è che ne loop, quando pippo cambia, poi tu ti memorizzi il nuovo valore, assegnandolo, se ho ben capito, a NumCam ...

... qui il tuo loop potrebbe contenere :

  //scrivo il nuovo valore nella EEPROM quando il valore di pippo è cambiato, questo per non riscrivere la EEPROM continuamente
  if (pippo != NumCam) {
     NumCam = pippo;
     EEPROM.write(1, pippo);
  }

... tutto qui ;)

Guglielmo

@Mauro: la EEPROM.write di Arduino richiama la funzione eeprom_write_byte di Avr-gcc per cui scrive sempre, non controlla se il valore è identico a quello già memorizzato. In effetti, sarebbe una segnalazione da fare per cambiare la libreria di sistema ;)

Grazie a Guglielmo che mi ha messo sulla retta via e a Pablos per la dritta dell’uso del serial monitor per controllare meglio la scrittura sulla EEprom!
Il problema dovrebbe essere risolto!
Sto cercando di costruire una segnalazione per telecamere, in modo che quando sono On Air si accenda una segnalazione con i led pilotate in PWM (in modo da poter variare la luminosita’ per evitare di dar fastidio a presentatori o alla scena) ed avere anche il numero della telecamera ben in vista, potendo spegnere il display col numero per ogni eventualita’.
Per contenere gli eventuali costi e per non utilizzare una scheda Arduino sprecandola ho provveduto a montare l’ATMega 328 su di un circuito stampato da me realizzato.
Vi posto una foto del prototipo ancora privo di led luminosi ma ora, grazie a voi, perfettamente funzionante.

Tally.JPG

leo72: @Mauro: la EEPROM.write di Arduino richiama la funzione eeprom_write_byte di Avr-gcc per cui scrive sempre, non controlla se il valore è identico a quello già memorizzato. In effetti, sarebbe una segnalazione da fare per cambiare la libreria di sistema ;)

Qualcuno si è scritto una libreria più intelligente che include anche la funzione di cui si sta parlando ;) ... la trovate qui : http://thijs.elenbaas.net/2012/07/extended-eeprom-library-for-arduino/

Guglielmo

Sì, la conoscevo. Tra l'altro quella lib permette anche di leggere/scrivere dati diversi dai singoli byte come float, int e long.

A parte questo, sarebbe carino se la libreria EEPROM dell'Arduino implementasse quel piccolo trucco salva-scritture ;)

Ora provvedo alla segnalazione su Github :stuck_out_tongue_closed_eyes:

Fatto ;)

Dato che sono solo agli inizi avrei un'altro quesito da sottoporvi: Se volessi integrare un blink del led nel mio listato in maniera da vedere che l'ATMega "vive" come dovrei fare? Forse scioccamente ho copiato/incollato il file di test denominato Blink ma quello che accade è che dopo aver acceso e spento il led con una tempostica di mezzo secondo, devo poi aspettare lo svolgimento del resto del loop. E' corretto cio che mi sembra di aver notato? Non è quindi possibile far eseguire più thread contemporaneamente?

Se volessi integrare un blink del led nel mio listato in maniera da vedere che l'ATMega "vive" come dovrei fare?

puoi usare http://arduino.cc/en/Tutorial/BlinkWithoutDelay nel loop() per fare lampeggiare un led senza "rallentare" il loop

ciao

AndreaBaroni: Non è quindi possibile far eseguire più thread contemporaneamente?

Esistono un paio di alternative "semplici": Looper, un semplice scheduler basato su millis, oppure leOS, uno scheduler un pochino più raffinato (ma sempre user-friendly ;) ) basato su un timer oppure sul watchdog.

Si era parlato del problema della EEPROM in un altro topic dove si era discusso sulla possibilità di ruotare le scritture in automatico sulle varie celle e della dimensione dei tipi di dati per calcolare il numero massimo di caselle disponibili.
C’erano anche delle soluzioni interessanti.
Se ritrovo il link lo posto.

Questo è un argomento che ciclicamente ricompare sul forum. :grin: