Utilisation de la mémoire SPIFFS

Bonjour, je possède un ESP8266 (NodeMcu V3) qui contrôle l’éclairage de chez moi.
Lorsqu’il reçoit une certaine variable, il allume la lampe. J’aimerais que lorsqu’il reboot ou bien après une perte d’alimentation, il récupère l’état précédent de ma lumière.
J’ai vu que c’était possible grâce à la mémoire SPIFFS. J’ai essayé de mettre une variable à 1 dans ce fichier data lorsque je dois allumer ma lampe. Et lorsque le programme démarre, il va lire dans ce fichier et réallume ou non ma lampe mais cela ne marche pas.

Un peu d’aide serait la bienvenue.
Merci

Un code sous forme d'image :confused:

Tu aurais pu mettre ton code entre balises.

sorry

une alternative à SPIFFS pour mémoriser quelque chose d'aussi simple : EEPROM émulée
syntaxe içi : Libraries — ESP8266 Arduino Core 3.0.0-39-g04c23227 documentation
voir aussi les exemples fournis pour ESP8266

je vois mal ton code en image... réédites ton message initial en plaçant le code comme il se doit sur ce forum
tel quel tu auras peu de réponses...désolé....

j'entrevois unif (state =  "ON" )qui ne fais pas du tout ce que tu espères

#include <FS.h>
int led = D8;
String state;

void setup(){
  Serial.begin(9600);
  SPIFFS.begin();
  File file = SPIFFS.open("/state.txt", "r");
  state = file.readString();
  if(state = "ON"){digitalWrite(led, HIGH);}
  if(state = "OFF"){digitalWrite(led, LOW);}
}

void loop(){
  if(RECOIT ORDRE ALLUMAGE){
    digitalWrite(led, HIGH);
    File file = SPIFFS.open("/state.txt", "w");
    file.println("ON");
    delay(50);
    file.close();
    }
    else if(RECOIT ORDRE EXTINCTION){
    digitalWrite(led, LOW);
    File file = SPIFFS.open("/state.txt", "w");
    file.println("OFF");
    delay(50);
    file.close();
}

J’ai aussi essayé avec la double égalité au lieu du simple égal mais rien n’y fait.
Je ne sais pas si les ESP ont une mémoire EEPROM mais je ne m’était pas orienté vers celle ci du fait de son nombre d’opérations limité.

le double égal s'impose, il ya un problème ailleurs

l'ESP8266 ne dispose pas d'EEPROM , elle est émulée en mémoire Flash (une mémoire qui n'est pas dans l'ESP8266 mais à côté)

Spiifs utilise également la même mémoire Flash, et du point de vue de l'usure SPIFFS a un léger avantage vu qu'il utilise une forme simple de "répartition de l'usure". (wear levelling) qui ralentit l'usure .

De là a abandonner systématiquement l'utilisation de l'EPROM émulée c'est un pas que je ne franchis pas dans mes applications.

La mémoire Flash SPI de marque Winbond qui accompagne les ESP8266 est garantie pour au moins 100 000 cycles d'écriture/effacement pour chaque secteur......on peut voir venir.....même en usage de type EPROM

Je prends donc SPIFFS quand j'ai un réel besoin de système de fichiers, EPROM quand il s'agit de mémoriser qq données de temps à autre. Je conçois qu'on voit 'mathématiquement' les choses autrement. !

A part cela pour les démarrage 'à chaud' (ceux ou l'alimentation n'a pas été coupée), pour les réveils après un deepsleep() on peut profiter d'une petite RAM (dite RTCRAM) pour conserver et retrouver des données . (pas d'usure du tout)
Seule la coupure de l'alimentation efface cette RTCRAM

Donc pour mon cas l'EEPROM émulée serait la meilleure solution ?

Donc pour mon cas l'EEPROM émulée serait la meilleure solution ?

Impossible de répondre.
ça dépend de la fréquence des écritures en EPROM et donc du temps au bout duquel vous arriverez vers 100 000 écritures Si le résultat est acceptable pour vous , alors oui
.....ça ne peut être qu'un choix personnel.

J'ai juste voulu dire de ne pas écarter par principe l'EPROM émulée en Flash pour les ESP

Je ne sais pas, en combien de temps allume-t-on la lumière 5000 fois ? :stuck_out_tongue:

?? ça dépend du nombre de personnes au domicile, du type de pièces

pour 10 allumages et 10 extinctions par jours = 20 écritures/jour ça donne 7300/an ... et 13 ans de fonctionnement pour la mémoire Flash gérée en EPROM

A mon avis l'ESP8266 ou son alimentation auront lâché avant .... éventuellement suite à une surtension sur le secteur.

Si la lampe est commandée par un petit relais sa durée de vie électrique n'est pas meilleure que 100 000 commutations.

Bonjour,

Envoie le contenu de state sur le moniteur ainsi que le nombre de caractères contenus.

Le problème ne dois pas être si compliqué.

J'ai le droit à une chaîne de caractères incompréhensible ....

on doit nécessairement lui trouver une sens !

Il n'y a pas de file.close dans le setup

J’ai un peu changé mon programme…
La valeur (LOW ou HIGH) s’affiche correctement au démmarage mais ma led reste eteinte dans tout les cas …

#include <FS.h>
int led = D1;
String fileTxt; 

void setup()
{
  Serial.begin(9600);
  SPIFFS.begin();
  pinMode(led, OUTPUT);
  File f = SPIFFS.open("/led.txt", "r");
  fileTxt = f.readString();
  Serial.println(fileTxt);
  if(fileTxt == "LOW"){
        digitalWrite(led, LOW);}
  else if(fileTxt == "HIGH"){
        digitalWrite(led, HIGH);}
  f.close(); 
      }

void loop()
{
      if (DOIT S'allumer)
      {
        File f = SPIFFS.open("/led.txt", "w");
        digitalWrite(led, HIGH);
        f.println("HIGH");
        delay(50);
        f.close();
       }
      else if (DOIT S'éteindre)
      {
        File f = SPIFFS.open("/led.txt", "w");
        digitalWrite(led, LOW);
        f.println("LOW");
        delay(50);
        f.close();
}

As-tu testé un simple blink avec cette led ? C'est peut-être un problème de connexion ou de choix de la pin

Quand je démarre l’ESP, la led reste eteinte
Je lui donne l’ordre de s’allumer → elle s’allume
Mais lorsque je reboot, il y a bien la valeur “HIGH” dans le fichier mais la led ne s’allume pas
En réalité c’est un relais qui contrôle la led, j’essaye avec une led directement

Le code que tu nous montres n'est pas celui que tu utilises, car ceci n'est pas valide :

if (DOIT S'allumer)

Donc, pas facile d'aider sans le vrai code.

As-tu vraiment besoin d'utiliser une String ? Le problème vient peut-être de ça. Essaye d'utiliser un booléen ou un byte, qui vaut 0 ou 1 au lieu de (resp.) LOW et HIGH.
Le test dans le setup sera plus simple

fileByte = f.read();
 Serial.println(fileByte);
 digitalWrite(led, fileByte);

De même dans la suite du code, si 'DOIT S'allumer' est un booléen ou un byte (0 ou 1), fais plus simple :

void loop() {
      File f = SPIFFS.open("/led.txt", "w");
      digitalWrite(led, doitsallumer);
      f.write(doitsallumer);
      delay(50);
      f.close();
}

C’est un peu plus complexe … je mets le code en entier mais ça va de suite être plus compliqué.
Infos : ce n’est pas 1 led mais 4 relais (rouge, vert, bleu, et vcc).
Je mets un relais sur le VCC à cause d’un défaut d’isolement électrique.

#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include <FS.h>
#define WIFI_SSID "****"
#define WIFI_PASS "****"
#define MQTT_SERV "io.adafruit.com"
#define MQTT_PORT 1883
#define MQTT_NAME "****"
#define MQTT_PASS "****"

String red = "R";
String green = "G";
String blue = "B";
String cyan = "C";
String magenta = "M";
String yellow = "Y";
String white = "W";
String off = "OFF";
int r = D1;
int g = D2;
int b = D3;
int VCC = D0;
String fileTxt; 

//INIT
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, MQTT_SERV, MQTT_PORT, MQTT_NAME, MQTT_PASS);
Adafruit_MQTT_Subscribe onoff = Adafruit_MQTT_Subscribe(&mqtt, MQTT_NAME "/f/RGB");

void setup()
{
  Serial.begin(9600);
  SPIFFS.begin();
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(r, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(VCC, OUTPUT);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  WiFi.mode(WIFI_STA);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");}  
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.println("OK!");
  mqtt.subscribe(&onoff);
  File f = SPIFFS.open("/rgb.txt", "r");
  fileTxt = f.readString();
  Serial.println(fileTxt);
  if(fileTxt == red){
        digitalWrite(r, HIGH);
        digitalWrite(g, LOW);
        digitalWrite(b, LOW);
        digitalWrite(VCC, HIGH);}
  else if(fileTxt == green){
        digitalWrite(r, LOW);
        digitalWrite(g, HIGH);
        digitalWrite(b, LOW);
        digitalWrite(VCC, HIGH);}
  else if(fileTxt == blue){
        digitalWrite(r, LOW);
        digitalWrite(g, LOW);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);}
  else if(fileTxt == cyan){
        digitalWrite(r, LOW);
        digitalWrite(g, HIGH);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);}
  else if(fileTxt == magenta){
        digitalWrite(r, HIGH);
        digitalWrite(g, LOW);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);}
  else if(fileTxt == yellow){
        digitalWrite(r, HIGH);
        digitalWrite(g, HIGH);
        digitalWrite(b, LOW);
        digitalWrite(VCC, HIGH);}
  else if(fileTxt == white){
        digitalWrite(r, HIGH);
        digitalWrite(g, HIGH);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);}
 else if(fileTxt == off){
        digitalWrite(r, LOW);
        digitalWrite(g, LOW);
        digitalWrite(b, LOW);
        digitalWrite(VCC, LOW);}
      f.close();
      }

void loop()
{
  MQTT_connect();
  Adafruit_MQTT_Subscribe * subscription;
  while ((subscription = mqtt.readSubscription(5000)))
  {
    if (subscription == &onoff){
      File f = SPIFFS.open("/rgb.txt", "w");
      Serial.print("onoff: ");
      Serial.println((char*) onoff.lastread);
      if (!strcmp((char*) onoff.lastread, "R"))
      {
        digitalWrite(r, HIGH);
        digitalWrite(g, LOW);
        digitalWrite(b, LOW);
        digitalWrite(VCC, HIGH);
        f.println("R");
        delay(50);
       }
      else if (!strcmp((char*) onoff.lastread, "G"))
      {
        digitalWrite(r, LOW);
        digitalWrite(g, HIGH);
        digitalWrite(b, LOW);
        digitalWrite(VCC, HIGH);
        f.println("G");
        delay(50);
       }
       else if (!strcmp((char*) onoff.lastread, "B"))
      {
        digitalWrite(r, LOW);
        digitalWrite(g, LOW);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);
        f.println("B");
        delay(50);
       }
        else if (!strcmp((char*) onoff.lastread, "C"))
      {
        digitalWrite(r, LOW);
        digitalWrite(g, HIGH);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);
        f.println("C");
        delay(50);
       }
       else if (!strcmp((char*) onoff.lastread, "M"))
      {
        digitalWrite(r, HIGH);
        digitalWrite(g, LOW);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);
        f.println("M");
        delay(50);
       }
       else if (!strcmp((char*) onoff.lastread, "Y"))
      {
        digitalWrite(r, HIGH);
        digitalWrite(g, HIGH);
        digitalWrite(b, LOW);
        digitalWrite(VCC, HIGH);
        f.println("Y");
        delay(50);
       }
      else if (!strcmp((char*) onoff.lastread, "W"))
      {
        digitalWrite(r, HIGH);
        digitalWrite(g, HIGH);
        digitalWrite(b, HIGH);
        digitalWrite(VCC, HIGH);
        f.println("W");
        delay(50);
       }
      else if (!strcmp((char*) onoff.lastread, "OFF"))
      {
        digitalWrite(r, LOW);
        digitalWrite(g, LOW);
        digitalWrite(b, LOW);
        digitalWrite(VCC, LOW);
        f.println("OFF");
        delay(50);}
        f.close();
    }
  }
}

void MQTT_connect()
{
  if (mqtt.connected() && mqtt.ping())
  {
    return;
  }

  int8_t ret;

  mqtt.disconnect();

  Serial.print("Connecting to MQTT... ");
  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0)
  {
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);
    retries--;
    if (retries == 0)
    {
      ESP.reset();
    }
  }
  Serial.println("MQTT Connected!");
}

OK, alors 4 leds, ça tient dans un byte : un bit par led, tu as de la place.
Tu codes l'état des leds comme ça par exemple :

byte etats = 0x0100;

avec un code du genre RGBV (un bit par couleur, tu vois ce que je veux dire ?)

Ensuite tu stockes cette valeur dans le fichier. Lors de la lecture, tu décodes et tu allumes les leds en fonction de la valeur

byte etatR = etats & 0x1000;
byte etatG = etats & 0x0100;
byte etatB = etats & 0x0010;
byte etatV = etats & 0x0001;
digitalWrite (r, etatR);
digitalWrite (g, etatG);
digitalWrite (b etatB);
digitalWrite (VCC, etatV);

L'idée est de se passer des String, si c'est elles qui posent le problème.