Mémoire EEPROM ESP32

Bonjour,
J'utilise un ESP32 ( ESP32-DevKitCVE avec 8 MB Flash + 8 MB PSRAM ) avec capteur BME280
J'ai pour projet de récupérer la température toutes les 5 minutes.
Pas de problème pour ça.
Une fois mes mesures prise, mon ESP32 entre en deep'sleep'mode.
J'aimerais enregistrer mes valeurs de température dans la mémoire EEPROM de mon ESP32 et par exemple récupérer toutes les mesures qu'il y a eu pendant les 2 dernières semaines.
Je n'ai jamais utiliser la mémoire EEPROM, j'ai regardé 4 - 5 vidéos et dans chaque exemples que j'ai vu il rentre des paramètres à retenir et non simplement une sauvegarde de mesure.
J'aimerais savoir si il existe des exemples similaire avec ce que je souhaite et si c'est bien dans la mémoire que dois sauvegarder mes valeurs ou dans une autre mémoire.
J'ajoute mon début de programme dans la matinée.
Vous remerciant.

Bonsoir

  1. l'ESP32 ne contient pas d'EEPROM !!
    Il est possible d'en émuler une dans la mémoire Flash SPI (8MB içi) qui accompagne tout ESP32
    Tutoriel : https://randomnerdtutorials.com/esp32-flash-memory/
    Rangement de paramètres ou autre données c'est à toi de gérer les cases mémoire de cette 'EEPROM'

  2. Il est également possible de mémoriser des données dans un système de fichiers SPIFFS, ou mieux LIttleFS qui a vocation à le remplacer depuis que SPIFFS n'est plus maintenu.
    Ce système de fichier prend également place en mémoire Flash, avec la possibilité de définir la taille de l'espace qui lui est réservé (menu Outils -> Partition Scheme)
    Voit=r les exempels dans les catégiries SPIFFS ou LIttleFS
    (par rapport à l'EEPROM' tu trouveras peut être plus pratique d'ouvrir un fichier et d'y ajouter des données.)

  3. L'ESP32 possède une petite zone de RAM particulière 16KB qui reste alimentée pendant le deep-sleep, Espressif la nomme 'RTC-RAM'. (Bien entendu la conservation de l'information dans cette petire RAM reste tributaire du maintien de l'alimentation)
    exemple d'utilisation : https://projetsdiy.fr/esp32-stocker-donnees-temporaires-memory-rtc-memory-deep-sleep/

1 Like

D'accord merci , la mémoire flash ? se souvient même en deep_sleep ?
Car mon objectif est avec avec une mesure toutes les 5 minutes, les conserver deux semaines , soit 4032 mesures.
Si c'est trop une mesure toute les 15 minutes et j'aurais donc 1344 mesures à réaliser.
Pour commencer je dois calculer le nombre d'octets que je compte stocker par mesure ( de tous mes capteurs) ?
Si vraiment l'espace de l'esp32 est trop petit, il est possible d'ajoute un module mémoire sur l'esp32 ?

Bonjour

Le forum n'est pas le seule source d'information , le web regorge d'informatiosn sur la technologie Flash
La première phrase de l'article 'Memoire Flash' de WIhkipedia répond à ta question, rapidement et en toute indépendance.....

Si la mémoire Flash n'était pas conservée hors alimentation le code serait perdu et il faudrait re-téléverser le code après chaque mise sous(tension !!
Si elle ne s'en souvenait pas pendant le deep-sleep l'ESP32 aurait un problème au réveil !!

Où va le code téléversé d'après toi ?

Oui il faut calculer le nombre total d'octets (qui peut être différent du nombre de mesures)

Il est un peu tôt pour envisager l'ajout de mémoire à un ESP32 !!

1 Like

"EEPROM" is a silly idea on the ESP32 anyway. It's a weird library with very limited functionality to give Arduino people something with a familiar name. There is no EEPROM. It doesn't exist.

Preferences is an Arduino library that uses ESP-IDF's NVS, which has wear levelling. Use that.

1 Like

Bonsoir @nona66

merci de rédiger en français sur ce forum ( et de lire les réponses déjà fournies, comme la réponse #2 :wink:)

1 Like

Bonjour,
Ducoup je viens de faire ce programme
Il fonctionne proprement mais pour optimiser ma mémoire, je pensait afficher ma température et humidité avec seulement 1 chiffre après la virgule.
j'ai donc essayé ceci comme je faisais sur mon écran TFT mais ça ne marche pas. Pourriez vous m'aider ?

Temperature = (bme.readTemperature(),1);

image

//BME280
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
unsigned long delayTime;
float Temperature;
float Humidite;
float Pression;


//ds1307
#include "RTClib.h"
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
int annee ;
int mois ;
int jour ;
int heure ;
int minute1 ;


// Libraries for SD card
#include "FS.h"
#include "SD.h"
#include <SPI.h>
// Define CS pin for the SD card module
#define SD_CS 14
// Save reading number on RTC memory
RTC_DATA_ATTR int readingID = 0;
String dataMessage;


void setup() {
  // Start serial communication for debugging purposes
  Serial.begin(115200);

  // Initialize SD card
  SD.begin(SD_CS);
  if (!SD.begin(SD_CS)) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }
  Serial.println("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("ERROR - SD card initialization failed!");
    return;    // init failed
  }

  // If the data.txt file doesn't exist
  // Create a file on the SD card and write the data labels
  File file = SD.open("/data.txt");
  if (!file) {
    Serial.println("File doens't exist");
    Serial.println("Creating file...");
    writeFile(SD, "/data.txt", " Date, Heure, Température, Humidité, Pression\r\n");
  }
  else {
    Serial.println("File already exists");
  }
  file.close();

  //BME280
  while (!Serial);   // time to get serial running
  Serial.println(F("BME280 test"));

  unsigned status;

  status = bme.begin();
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
    Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(), 16);
    Serial.print("        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
    Serial.print("   ID of 0x56-0x58 represents a BMP 280,\n");
    Serial.print("        ID of 0x60 represents a BME 280.\n");
    Serial.print("        ID of 0x61 represents a BME 680.\n");
    while (1) delay(10);
  }

  Serial.println("-- Default Test --");
  delayTime = 5000;

  Serial.println();

  //DS1307
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }

}

void loop() {
  //BME280
  //printValues();



  //SD
  getclimat();
  getdate();
  sdcard();

  //DS1307


  delay(delayTime);
}
void getclimat() {
  Temperature = ((bme.readTemperature(),1));
  Humidite = (bme.readHumidity(),1);
  Pression = (bme.readPressure() / 100.0F);
}
void getdate() {
  DateTime now = rtc.now();
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute1 = now.minute();
}
void sdcard() {
  dataMessage =  String(jour) + "/" + String(mois) + "/" + String(annee ) + "," + String(heure) + ":" + String(minute1) + ","  +   String(Temperature) + "," + String(Humidite) + "," + String(Pression) + "\r\n";
  Serial.print("Sauvegarde: ");
  Serial.println(dataMessage);
  appendFile(SD, "/data.txt", dataMessage.c_str());
}
void writeFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Writing file: %s\n", path);
  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}
// Append data to the SD card (DON'T MODIFY THIS FUNCTION)
void appendFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Ajout au fichier: %s\n", path);
  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message ajouté");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}
void printValues() {
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" °C");

  Serial.print("Pressure = ");

  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
}

Bonjour,

Temperature est un float et sa taille ne dépend pas du nombre de décimales.
Ca n'optimisera pas le moins du monde la mémoire.

Ceci Temperature = (bme.readTemperature(),1); met 1 dans Temperature.

D'accord merci
Afficher une valeur de moins utilisera moins d'octet nn ?
Ce n'est donc pas possible d'afficher seulement 1 chiffre après la virgule ?

J'ai un petit problème, j'aimerais afficher l'état de mes leds sur ma base de donnée.
Pourriez vous me conseillez j'ai essayé ceci mais ça ne fonctionne pas.
Le compilateur ne me signale pas d'erreur mais je n'ai pas l'info vert , orange, rouge dans le fichier data

 char  info;
char VERT;
char ORANGE;
char ROUGE;
        if (LED_PIN3 == HIGH ) {
          info == VERT;//vert
        }
        else if  (LED_PIN2 == HIGH) {
          info == ORANGE;//orange
        }
       else  if (LED_PIN == HIGH) {
        info ==ROUGE ;//rouge
      }

      getclimat();
      getdate();
      sdcard();

      //sommeil
      Serial.println("sommeil pour 5 minutes");
      Serial.println();
      Serial.flush();
      esp_deep_sleep_start();
    }

  }



void getclimat() {
  Temperature = (bme.readTemperature());
  Humidite = (bme.readHumidity());
}

void getdate() {
  DateTime now = rtc.now();
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute1 = now.minute();
}


void sdcard() {
  dataMessage =  String(jour) + "/" + String(mois) + "/" + String(annee ) + "," + String(heure) + ":" + String(minute1) + ","  +
                 String(Temperature) + "," + String(Humidite) + ","  + String(info) + "\r\n";
}

Bien sur que si, mais ça n'utilisera pas moins de mémoire.
Tu confonds affichage et stockage de la valeur.

Avec un ESP32, le plus simple pour afficher une valeur formattée est d'utiliser sprintf
https://www.cplusplus.com/reference/cstdio/sprintf/

int sprintf ( char * str, const char * format, ... );
Write formatted data to string
Composes a string with the same text that would be printed if format was used on printf, but instead of being printed, the content is stored as a C string in the buffer pointed by str.

par exemple :

char texte[12];
float x = 3.1415926537;
sprintf(texte,"pi = %5.2f",x);

Si je ne me suis pas trompé, ça écrit dans la variable texte "pi = 3.14"

Bonjour,
je ne comprend pas trop, ce que je souhaite faire c'est lorsque ma led, verte , orange , rouge est allumée, j'envoie l'info sur ma carte SD.
C'est possible de faire un truc du genre ?

char test ( ici je dois mettre quoi ? )
if 
test= Vert 
else if 
test = orange 
else if 
test = rouge

pour ensuite quand je souhaite afficher test, ça m'affiche vert , orange ou rouge ?
Pour le moment ça m'affiche que la dernière lettre dans mon programme, t pour vert , e pour orange et rouge

J'ai réussi :slight_smile:
mon code :

String test
if 
test ="VERT"
else if
test= " ORANGE"
else if 
test= "ROUGE"

Bonjour,
Ducoup maintenant que j'ai réussi la solution la plus simple ( enregistrer mes données sur une micro SD) .
J'aimerais essayer de faire la même chose mais sur ma mémoire flash.
Cependant , je trouve ça étrange que personne n'a essayé de le faire .
Sur la carte SD, il y a plein de tutos et aucun sur la mémoire flash pour la sauvegarde de donnée .

???

Pour sauvegarder des données en mémoire Flash comme tu souhaites le faire j'ai cité 3 méthodes dans ma réponse #2 (EEPROM émulée, SPIFFS et LittleFs)

Pour chacune d'elles on trouve librairies + exemples .... et tutoriels

Oui je suis d'accord, mais pour mon niveau je trouve le tuto pas assez développé.
C'est pour cela que je cherchais un tuto qui stockait de la température par exemple pour qu'ensuite je puisse l'adapter à mes besoins.
J'ai une petite question.
Lorsque je sauvegarde les données sur la mémoire interne, et que je souhaite les récupérer comment cela se passe(j'ai vu pour la mémoire RTC mais pour la première solution ? ).Car avec ma carte SD je l'enlève et je la branche à l'ordinateur puis j'ouvre mon fichier texte.
j'ai essayé la mémoire rtc :
Il fonctionne :
stock mes 5 valeurs
les affiches dans la console
les effaces
puis recommence

Si je veux sortir mes 5 valeurs sur un fichier texte, c'est possible ?

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C

RTC_DATA_ATTR int recordCounter = 0;

typedef struct {
  float Temp;
  float Pressure;
} bmp280Records;

#define maxRecords 5 // Nombre max enregistrements 
#define sleepTime  1 // Every 10-mins of sleep 10 x 60-secs

RTC_DATA_ATTR bmp280Records Records[maxRecords];




void setup() {
  Serial.begin(115200);


    while(!Serial);    // time to get serial running
    Serial.println(F("BME280 test"));

    unsigned status;
   status = bme.begin();  

  if ( status ) {
    Serial.println("Record new values");
    Records[recordCounter].Temp     = bme.readTemperature();       // Units °C
    Records[recordCounter].Pressure = bme.readPressure() / 100.0F; // Units hPa
    recordCounter++;
    if ( recordCounter == 1 ) {
      Serial.println(String(recordCounter) + " record is stored in RTC memory");
    } else {
      Serial.println(String(recordCounter) + " records are stored in RTC memory");
    }
    

    if (recordCounter >= maxRecords) {
      for (int i = 0; i < maxRecords; i++){
        // Display records in CSV format to the serial port
        Serial.println(String(i)+","+String(Records[i].Temp)+","+String(Records[i].Pressure));
      }
      recordCounter = 0;
    }  
  } else {
    // Verifier la connexion I2C du BMP190 / BME280
    Serial.println("Sorry but BMP180 did not respond !");
  }
  
  // Reveil regulierement le processeur de l ESP32 pour faire une nouvelle mesure
  esp_sleep_enable_timer_wakeup(sleepTime * 1000000);
  
  esp_deep_sleep_start();
}

void loop() {
}

Je n'ai toujours pas trouvé la solution , personne n'a de solution pour la mémoire ?
J'envoie 70 octets par mesure.