Lettura / scrittura EEPROM

Salve ragazzi,

non riesco a risolvere un problemino che sembrerebbe banale.

Con lo sketch che segue provo ad attivare un timer su pressione di un pulsante (UNO-ON).
Alla successiva pressione di un secondo pulsante (DUE-OFF) inserisce il dato dei secondi trascorsi nella EEPROM
Il problema è che ho necessità di avere una somma di tali secondi, invece alla successiva pressione del pulsante ON (Avvio Timer) scopro che non tiene conto del dato presente nella variabile Secondi_Read.

Grazie dell'aiuto

Vi abbraccio

//Scrivo e leggo su EEPROM i secondi di un timer
 
#include <EEPROM.h>

#define UNO 7  
#define DUE 8


int c1 = 0; 
unsigned long Timer;
unsigned long Secondi;
unsigned long Secondi_Read;

bool onetime1 = true; // Eseguo solo una volta ONTIMER
bool onetime2 = true; // Eseguo solo una volta OFFTIMER

void setup() {
 
  Serial.begin(9600);
  
 
   pinMode(UNO, INPUT_PULLUP);
   pinMode(DUE, INPUT_PULLUP);

}
 
void loop() {

  if (digitalRead(UNO) == LOW){ 
        delay(40);
        if (digitalRead(UNO) == LOW){Serial.println("---- UNO---- "); ONTIMER();} 
  }
  if (digitalRead(DUE) == LOW){ 
        delay(40);
        if (digitalRead(DUE) == LOW){Serial.println("---- DUE---- "); OFFTIMER();} 
  }
             
} //Chiude Loop 



void ONTIMER()
// Parte Timer
{
  if (onetime1) {
  Timer = millis();
  onetime2 = true;
  onetime1 = false;


  //Leggo valore Secondi_Read in EEPROM 
  long aa=EEPROM.read(c1);

  long Secondi_Read=aa;
  
   Serial.println("---- ON---- ");
   Serial.print("Secondi_Read: ");
   Serial.println(Secondi_Read);
   Serial.println("----------------------------------- ");

  
  }
}

void OFFTIMER()
// Ferma Timer
{
   if (onetime2) {
    Secondi=Secondi_Read+((millis()-Timer)/1000UL); 
    onetime1 = true;
    onetime2 = false;

 
//SCRIVE SU EEPROM QUANDO IL TIMER VA OFF 
 
    long a = Secondi;
   
    EEPROM.write(c1, a);
 
  Serial.println("---- OFF---- ");

  Serial.print("Secondi: ");
  Serial.println(Secondi);

  Serial.print("Secondi_Read: ");
  Serial.println(Secondi_Read);
  Serial.println("----------------------------------- ");

     
  }
}

Dove hai letto che puoi leggere/scrivere un "long" con le EEPROM.read()/EEPROM.write() ? ? ? :o :o :o

Guglielmo

Sì Guglielmo è vero... mi sono rimaste le long perchè in realtà il programma è molto più complesso.

Ecco riportato tutto ad int.... il problema persiste! Ogni volta riporta a zero Secondi_Read e non capisco perchè!

//Scrivo e leggo su EEPROM i secondi di un timer
 
#include <EEPROM.h>

#define UNO 7  
#define DUE 8


int c1 = 0; 
int Timer;
int Secondi;
int Secondi_Read;

bool onetime1 = true; // Eseguo solo una volta ONTIMER
bool onetime2 = true; // Sommo Totale_in_Minuti in void OFFTIMER

void setup() {
 
  Serial.begin(9600);
  
 
   pinMode(UNO, INPUT_PULLUP);
   pinMode(DUE, INPUT_PULLUP);

}
 
void loop() {

  if (digitalRead(UNO) == LOW){ 
        delay(40);
        if (digitalRead(UNO) == LOW){Serial.println("---- UNO---- "); ONTIMER();} 
  }
  if (digitalRead(DUE) == LOW){ 
        delay(40);
        if (digitalRead(DUE) == LOW){Serial.println("---- DUE---- "); OFFTIMER();} 
  }
             
} //Chiude Loop 



void ONTIMER()
// Parte Timer
{
  if (onetime1) {
  Timer = millis();
  onetime2 = true;
  onetime1 = false;


  //Leggo valore Secondi_Read in EEPROM 
  int aa=EEPROM.read(c1);

  int Secondi_Read=aa;
  
   Serial.println("---- ON---- ");
   Serial.print("Secondi_Read: ");
   Serial.println(Secondi_Read);
   Serial.println("----------------------------------- ");

  
  }
}

void OFFTIMER()
// Ferma Timer
{
   if (onetime2) {
    Secondi=Secondi_Read+((millis()-Timer)/1000UL); 
    onetime1 = true;
    onetime2 = false;

 
//SCRIVE SU EEPROM QUANDO IL TIMER VA OFF 
 
    int a = Secondi;
   
    EEPROM.write(c1, a);
 
  Serial.println("---- OFF---- ");

  Serial.print("Secondi: ");
  Serial.println(Secondi);

  Serial.print("Secondi_Read: ");
  Serial.println(Secondi_Read);
  Serial.println("----------------------------------- ");

     
  }
}

E io ripeto ... dove hai letto che puoi leggere/scrivere un "int" con le EEPROM.read()/EEPROM.write() ? ? ? :o :o :o

Guglielmo

P.S.: Ma almeno, lo sforzo di andare a studiarti il reference, lo vuoi fare ? ? ? >:(

Cazziate a parte, ho sempre scritto int su EEPROM

Ecco il reference example of Write:

/*
 * EEPROM Write
 *
 * Stores values read from analog input 0 into the EEPROM.
 * These values will stay in the EEPROM when the board is
 * turned off and may be retrieved later by another sketch.
 */

#include <EEPROM.h>

/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int addr = 0;

void setup() {
  /** Empty setup. **/
}

void loop() {
  /***
    Need to divide by 4 because analog inputs range from
    0 to 1023 and each byte of the EEPROM can only hold a
    value from 0 to 255.
  ***/

  int val = analogRead(0) / 4;

  /***
    Write the value to the appropriate byte of the EEPROM.
    these values will remain there when the board is
    turned off.
  ***/

  EEPROM.write(addr, val);

  /***
    Advance to the next address, when at the end restart at the beginning.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/
  addr = addr + 1;
  if (addr == EEPROM.length()) {
    addr = 0;
  }

  /***
    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
    EEPROM address is also doable by a bitwise and of the length - 1.

    ++addr &= EEPROM.length() - 1;
  ***/


  delay(100);
}

Ciao! write e read, scrivono e leggono un byte valori da 0 a 255.
In caso di dati diversi dal byte devi usare i metodi put e get.

Link

Zamundo:
Cazziate a parte, ho sempre scritto int su EEPROM

Non diciamo sciocchezze ... EEPROM.read() ed EEPROM.write() leggono/scrivono solo BYTE ed è chiaramente documentato nel reference.

Quel tuo pezzo di codice ti funziona perché ... analogRead() da un valore massimo a 10 bit che, guarda caso, diviso per 4 (ovvero >> 2) da un valore a 8 bit ... e c'è pure scritto nei commenti ... se tu li leggessi !!! >:(

Guglielmo

Ok Ok ragazzi,

innanzitutto quello non è "un mio pezzo di codice" ma il Reference ufficiale della EEPROM Write.
Eccco il link:

In secondo luogo, non stiamo risolvendo il problema.

Immaginiamo di NON voler scrivere un dato maggiore di 255. (Possiamo usare tranquillamente il byte e vi riposto il programma col byte)

Vi va di aiutarmi a capire perchè perde il dato Secondi_Read ?

Vi abbraccio

PS Guglielmo perchè reagisci sempre in modo "nervoso" ? Dai che con l'estate urge vacanza :slight_smile:

//Scrivo e leggo su EEPROM i secondi di un timer
 
#include <EEPROM.h>

#define UNO 7  
#define DUE 8


int c1 = 0; 
byte Timer;
byte Secondi;
byte Secondi_Read;

bool onetime1 = true; // Eseguo solo una volta ONTIMER
bool onetime2 = true; // Sommo Totale_in_Minuti in void OFFTIMER

void setup() {
 
  Serial.begin(9600);
  
 
   pinMode(UNO, INPUT_PULLUP);
   pinMode(DUE, INPUT_PULLUP);

}
 
void loop() {

  if (digitalRead(UNO) == LOW){ 
        delay(40);
        if (digitalRead(UNO) == LOW){Serial.println("---- UNO---- "); ONTIMER();} 
  }
  if (digitalRead(DUE) == LOW){ 
        delay(40);
        if (digitalRead(DUE) == LOW){Serial.println("---- DUE---- "); OFFTIMER();} 
  }
             
} //Chiude Loop 



void ONTIMER()
// Parte Timer
{
  if (onetime1) {
  Timer = millis();
  onetime2 = true;
  onetime1 = false;


  //Leggo valore Secondi_Read in EEPROM 
  byte aa=EEPROM.read(c1);

  byte Secondi_Read=aa;
  
   Serial.println("---- ON---- ");
   Serial.print("Secondi_Read: ");
   Serial.println(Secondi_Read);
   Serial.println("----------------------------------- ");

  
  }
}

void OFFTIMER()
// Ferma Timer
{
   if (onetime2) {
    Secondi=Secondi_Read+((millis()-Timer)/1000UL); 
    onetime1 = true;
    onetime2 = false;

 
//SCRIVE SU EEPROM QUANDO IL TIMER VA OFF 
 
    byte a = Secondi;
   
    EEPROM.write(c1, a);
 
  Serial.println("---- OFF---- ");

  Serial.print("Secondi: ");
  Serial.println(Secondi);

  Serial.print("Secondi_Read: ");
  Serial.println(Secondi_Read);
  Serial.println("----------------------------------- ");

     
  }
}

Zamundo:
PS Guglielmo perchè reagisci sempre in modo "nervoso" ? Dai che con l'estate urge vacanza :slight_smile:

... perché ti conosco personalmente, so che lavori su Arduino da anni, che hai parecchia esperienza e ... NON ammetto che una persona come te, che ha sviluppato tutto quello che ha sviluppato, faccia ancora degli errori simili, anzi ... mi fa veramente incxxxare >:( >:( >:(

Guglielmo

oltre al reference c'è anche un post praticamente simile che ha anche gia la soluzione bella e pronta qui

in quel caso si trattava di scrivere/leggere manualmente un "float"(4 Byte ) su una memoria esterna ma il concetto rimane praticamente quello

inoltre, se usi un ATmega328p e dichiari "int c1" questa puo contenere al max 32676 sec = 9 ore circa

stesso discorso per timer(che andra in overflow anche prima...)

Gentile MixMax,

ho letto con attenzione il topic che mi hai consigliato, ma purtroppo non c'entra veramente nulla con quello di cui stiamo parlando.

Non ha nessuna importanza l'eventuale overflow.

Ho specificato di concentraci sul problema:

Pur immaginando che i secondi NON siano MAI più di 255, il problema è l'inspiegabile reset del valore di Secondi_Read

Qualcuno ha qualche idea?

Abbracci a tutti... anche a Guglielmo... guarda che in questi giorni sono ad un tiro di schioppo da te !! :slight_smile:

... oltre a non leggere i reference, continui a fare SEMPRE gli stessi sbagli ... variabili "locali" con lo stesso nome di variabili "globali" ... e si che ti era già stato spiegato il problema ... :smiling_imp: :smiling_imp: :smiling_imp:

Guglielmo

Va bene, chiedo venia.

Avevo detto nel primo post che il problema avrebbe potuto essere una banalità!

Ovviamente si risolve dichiarando le variabili globali.

Stavolta lo shampoo transalpino è meritato!

Abbracci svizzeri :grinning: