Memorizzare un valore nella EEPROM di Arduino

Arduino possiede una memoria di tipo EEPROM (Electrically Erasable Programmable Read-Only Memory), questa memoria è cancellabile elettricamente e quindi è possibile utilizzarla tramite lo stesso Arduino per salvare dei dati che ci interessano.

Il bello di questa memoria è che, anche togliendo tensione al circuito, il dato resta memorizzato.
Successivamente, dando nuovamente alimentazione, posso leggere i valori precedentemente salvati.
Grazie a questa memoria, ad esempio, è possibile memorizzare dati di temperatura catturati con un sensore in momenti differenti e poi rileggerli tutti insieme quando lo desidero.

In Arduino Uno la EEPROM è di 1KB, che sono 1024 Byte, possiamo quindi memorizzare 1024 numeri con valori compresi tra 0 e 255.

Ho realizzato un piccolo progetto per fare le prime prove sulla EEPROM, funziona così (scusate x la musica XD):


Entriamo più nel dettaglio della realizzazione:



Sul display viene letto il valore memorizzato nello spazio "1" della EEPROM.
Grazie a 2 pulsanti, incremento e decremento questo valore.
Raggiunto il valore desiderato premo il terzo pulsante, così facendo memorizzo il dato nella memoria e lo sostituisco al dato precedentemente memorizzato.
Per aiutarmi a capire l'avvenuta pressione del pulsante, comparirà un "S" sul display.
Ora, spegnendo e riaccendendo l'Arduino, verrà visualizzato l'ultimo dato salvato.

Questo è il circuito da realizzare:





Ecco lo sketch da caricare:

  1. #include <LiquidCrystal.h>
  2. #include <EEPROM.h>
  3. LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // connessione display (pin)
  4. const int salva = 8;
  5. const int su = 10;
  6. const int giu = 9;
  7. byte datoeeprom;
  8. int statosu = 0;
  9. int statogiu = 0;
  10. int statosalva = 0;
  11. void setup() {
  12. pinMode(salva, INPUT);
  13. pinMode(su, INPUT);
  14. pinMode(giu, INPUT);
  15. digitalWrite(8, HIGH);
  16. digitalWrite(9, HIGH);
  17. digitalWrite(10, HIGH);
  18. lcd.begin(16, 2);
  19. datoeeprom = EEPROM.read(1); //leggi il dato salvato nella eeprom nello slot 1
  20. }
  21. void loop() {
  22. lcd.print ("val");
  23. statosu = digitalRead (su);
  24. if( statosu == LOW)
  25. {datoeeprom++;} //incrementa il valore alla pressione del pulsante "su"
  26. statogiu = digitalRead (giu);
  27. if( statogiu == LOW)
  28. {datoeeprom--;} //decrementa il valore alla pressione del pulsante "giu"
  29. statosalva = digitalRead (salva);
  30. if( statosalva == LOW)
  31. {EEPROM.write(1, datoeeprom); //salva il dato nello slot 1 della eeprom
  32. lcd.setCursor(0, 1);
  33. lcd.print("S");}
  34. lcd.setCursor(13, 0);
  35. lcd.print(datoeeprom);
  36. delay(200);
  37. lcd.clear();
  38. }

Ciao a tutti!


Segui Daniele Alberti su Google+

6 commenti:

  1. Mi sto appassionando perchè comincio a capire qualche cosa, grazie a te Daniele!!!!!!!!!!

    RispondiElimina
  2. Salve Daniele ho un quesito da porti, ma se dovrei memorizzare valori superiori a 255?? Come potrei fare? GRAZIE in anticipo!!

    RispondiElimina
    Risposte
    1. Ciao Samuele, se non ti serve particolare precisione puoi salvare tutti i valori che ti servono dividendoli prima per 10 (ad esempio per 1000 salvi 100).
      In alternativa puoi convertire il valore in binario e spezzarlo su 2 byte, poi puoi ricomporlo con il comando "shiftando" i bit. (La seconda opzione è leggermente più macchinosa).
      Spero di essere stato utile, ciao!

      Elimina
  3. Ciao Daniele,
    Io dovrei aumentare/diminuire un setpoint di un PID tramite due pulsanti, e visualizzare il valore su LCD I2C.
    Nel mio progtto mi sono avanzati solo due pin digitali, quindi vorrei fare in modo che la variabile sia scritta in eeprom, non so, dopo un dato tempo.

    Mi potresti aiutare?
    Grazie.
    Filippo

    RispondiElimina
    Risposte
    1. Ciao Filippo,
      potresti usare la funzione Millis per capire che "un dato tempo" sia trascorso.
      Trovi un esempio qui:
      http://www.danielealberti.it/2013/06/blink-con-millis-anziche-delay.html

      Elimina
    2. Grazie Daniele.
      Ho rifatto il circuito, e i 3 pulsanti ci stanno...
      Ma ho una domanda:

      Ho integrato (vedi sotto) al mio sketch il tuo. Ma ora come faccio a modificare la mia variabile (setpoint) entro i valori di temperatura 0-100?

      /*
      Il programma misura la temperatura tramite sensori DS18B20 per regolare la rotazione dei due ventole da PC a 12V 0,25A,
      per controllare la temperatura della birra in fermentazione usando un terzo DS18B20 con funzione PID
      L'uscita del PID pilota un circuito H-bridge per le celle di Peltier
      */

      #include
      #include // libreria di gestione del display lcd Grove I2C
      #include // dichiarazione di utilizzo della libreria DallasTemperature
      #include
      #include

      /* Definizioni globali */

      // Il terminale data del sensore è connesso alla porta 4 di Arduino
      #define ONE_WIRE_BUS 4

      // Imposta la comunicazione oneWire per comunicare
      // con un dispositivo compatibile
      OneWire oneWire(ONE_WIRE_BUS);


      // Passaggio oneWire reference alla Dallas Temperature.
      DallasTemperature sensor(&oneWire);

      double Setpoint, Input, Output;

      int SNS_A = A0; // Legge corrente
      int LPWM = 9; // H-bridge leg 1 ->LPWM
      int enL = 8; // H-bridge enable pin 1 -> L_EN
      int RPWM = 6; // H-bridge leg 2 ->RPWM
      int enR = 7; // H-bridge enable pin 2 -> R_EN


      //Inizializzazione del PID, impostazione a DIRECT (frigo), e dell'LCD
      PID myPID(&Input, &Output, &Setpoint,2,5,1, REVERSE);
      rgb_lcd lcd ;

      // Pulsanti

      const int salva = 2;
      const int su = 12;
      const int giu = 13;

      byte datoeeprom;
      int statosu = 0;
      int statogiu = 0;
      int statosalva = 0;



      void setup()
      {
      Setpoint = 18; //definizione del set point
      Serial.begin(9600);
      Serial.println("Temperatura PIDout Corrente\n");
      lcd.begin(16, 2);
      digitalWrite(4, HIGH); // turn on pull-up resistor

      // Pulsanti
      pinMode(salva, INPUT);
      pinMode(su, INPUT);
      pinMode(giu, INPUT);
      digitalWrite(2, HIGH);
      digitalWrite(12, HIGH);
      digitalWrite(13, HIGH);
      datoeeprom = EEPROM.read(1); //leggi il dato salvato nella eeprom nello slot 1



      //turn the PID on
      myPID.SetMode(AUTOMATIC);

      // Start up the OneWire library
      sensor.begin();


      // Configurazione PIN direzione e freno H-bridge
      pinMode(LPWM, OUTPUT);
      pinMode(RPWM, OUTPUT);
      pinMode(enL, OUTPUT);
      pinMode(enR, OUTPUT);
      digitalWrite(enL, HIGH);
      digitalWrite(enR, HIGH);

      }

      void loop() {
      sensor.requestTemperatures();
      // inizio loop PID
      double temp = sensor.getTempCByIndex(0); // legge il valore della temperatura e la memorizza nella var. temp.

      Input = temp; //temperatura passata in ingresso a PID
      myPID.Compute();

      digitalWrite(LPWM, LOW);
      digitalWrite(RPWM,Output); //PWM con segnale in uscita pari a uscita PID

      Serial.print( temp); // invia i valori al' LCD
      Serial.print("\t");
      Serial.print((Output/255*100));
      Serial.print("\t");
      Serial.print(digitalRead(SNS_A));
      Serial.print("\n");

      lcd.setCursor(3,0);
      lcd.print("Temp:");
      lcd.print(sensor.getTempCByIndex(0));


      lcd.setCursor(3,1);
      lcd.print("S.P.:");
      lcd.print(Setpoint);

      // fine loop PID

      // Loop per pulsanti
      statosu = digitalRead (su);
      if( statosu == LOW)
      {datoeeprom++;} //incrementa il valore alla pressione del pulsante "su"

      statogiu = digitalRead (giu);
      if( statogiu == LOW)
      {datoeeprom--;} //decrementa il valore alla pressione del pulsante "giu"

      statosalva = digitalRead (salva);
      if( statosalva == LOW)
      EEPROM.write(1, datoeeprom); //salva il dato nello slot 1 della eeprom

      }

      Elimina

Lascia un commento qui sotto, ti risponderò il prima possibile!