Go Down

Topic: Conception d'un nichoir connecté ! soucis de LED IR modulé ! (Read 2920 times) previous topic - next topic

al1fch

Bonsoir

le secteur 1 comporte toutes les cellules d'adresses 0 à 4095
le secteur 2 comporte toutes les cellules d'adresses 4096 à 8191

le code proposé ci dessus n'agit donc que sur deux cellules mémoire du secteur 1 , il n'a aucune influence sur les autres secteurs de la mémoire Flash.

concernant les cellules effacées il faudrait se plonger dans le code de bas niveau (dans la mesure ou il est disponible) pour trouver le détail des mises à jour de données  en mémoire Flash seteur par secteur.

(L'extension ESP pour IDE ARduino 'sous-traite' la gestion d ela mémoire Flash adess fonctiosn fournies par ESpressif)

Faute d'avoir vu ce code de bas ou très bas niveau, ma compréhension pour l'instant est la suivante  :

quand le commit arrive :
-les 4096 cellules du secteur sont effacées (pas de détail !)
-les 4096 valeurs présentes dans un buffer (RAM) sont écrites en Flash après mise à jour du buffer  par quelques EEPROM.write(), les autres valeurs du buffer étant inchangées.
Ceci permet de réécrire ce qu'il faut réécrire et changer ce qu'il faut là ou il faut ....et ne rien perdre !!


dbrion06

A priori, je ne pense pas qu'il efface:
il lit le secteur , fait les modifs dans le buffer en RAM et le commit -specifique à ESPxxx-  force l'écriture dans l'"EEPROM": les données en dehors des adresses 1 et 2 sont dans le même état qu'avant..

en passant, excusez moi pour la bêtise de ma question:
pourquoi jouez vous avec l'"EEPROM", alors que vous pouvez utiliser les mêmes bouts de circuit comme un système de fichier  et que spiffs a fait tous les efforts possibles pour maintenir l'intégrité de ce bout de circuit? (c'est mêm dans sa raison sociale sous github , "wear levelled SPI flash file system for embedded devices "  https://github.com/pellepl/spiffs? si vous voulez stocker davantage, ou avez l'expérience de fichiers sur PC, faire tout en spiffs vous simplifiera la vie, au prix peut être d'une certaine lenteur...

al1fch

Quote
es données en dehors des adresses 1 et 2 sont dans le même état qu'avant..
de mon point  de vue cela se réalise par effacement et réécriture

en absence d'EEPROM physique,  l'EEPROM est émulée en Flash , non dans la petite Flash interne des soc ESP8266 mais dans le circuit intégré Flash SPI de 'forte capacité' indispensable en complément.

Deux contraintes :
-la technologie Flash des Flash SPI en général
-les particularités des puces utilisées en accompagnement des soc ESP8266  (W25Q32BV de Winbond la pluart du temps , notament dans les modules ESP-12)

La technologie Flash utilisée içi permet d'écrire un 0 sur un 1 mais pas un 1 sur un zéro Il faut donc effacer  pour remettre partout des  1, puis des 0 par endroits

ça ne peut se faire ni par octets, ni par pages , mais par secteurs (ou groupes de secteurs)  qui, dans le cas des puces Winbond accompagnant généralement les ESP8266 ont une  taille de 4ko

D'où  le rôle central de ce buffer dont la taille est nécessairement celle des secteurs

(ceci est intégré également à SPIFFS qui en plus assure effectivement en plus une répartition d'usure.)

N.B je n'ai pas  été dans les tréfonds  du 'framework' d'Espressif (lDF) pour étudier par le détail la gestion de bas niveau de la mémoire Flash  et vérifier que c'est 'comme je l'imagine à partir des contraintes technologiques des puces.

rer67

Bonsoir

le secteur 1 comporte toutes les cellules d'adresses 0 à 4095
le secteur 2 comporte toutes les cellules d'adresses 4096 à 8191

le code proposé ci dessus n'agit donc que sur deux cellules mémoire du secteur 1 , il n'a aucune influence sur les autres secteurs de la mémoire Flash.

concernant les cellules effacées il faudrait se plonger dans le code de bas niveau (dans la mesure ou il est disponible) pour trouver le détail des mises à jour de données  en mémoire Flash seteur par secteur.

(L'extension ESP pour IDE ARduino 'sous-traite' la gestion d ela mémoire Flash adess fonctiosn fournies par ESpressif)

Faute d'avoir vu ce code de bas ou très bas niveau, ma compréhension pour l'instant est la suivante  :

quand le commit arrive :
-les 4096 cellules du secteur sont effacées (pas de détail !)
-les 4096 valeurs présentes dans un buffer (RAM) sont écrites en Flash après mise à jour du buffer  par quelques EEPROM.write(), les autres valeurs du buffer étant inchangées.
Ceci permet de réécrire ce qu'il faut réécrire et changer ce qu'il faut là ou il faut ....et ne rien perdre !!


parfait là c'est plus clair !!

je suis en plein impression 3D des supports de DEL !

dbrion06

Seul le commit assure une écriture physique (terme emprunté aux bases de données) https://randomnerdtutorials.com/esp32-flash-memory/
write ne fait "que" mettre un flag ("dirty") à un; commit regarde si le flag est à un, dans ce cas , le remet à zero   après écriture.https://forum.arduino.cc/index.php?topic=509169.0 montrent des bouts de code de la librairie EPROM pour ESP (en passant, si j'ai stocké 3.141, que je veux écrire 2.7, puis que je change d'avis et veux écrire 3.141 -revenant à l'état initial-, le commit fera une écriture inutile; je suppose que ce cas est suffisamment rare pour être omis)

al1fch

Quote
Seul le commit assure une écriture physique
Nous sommes d'accord s'il s'agit de l'écriture physique en Flash (ici Flash imitant une EEprom)
EEPROM.write écrit physiquement en RAM

J'ai aussi regardé les librairies Arduino touchant d'une manière ou d'une autre à la mémoire Flash
Elles appellent  toujours des fonctions de bas niveau d'Espressif où se passe la cuisine que j'imagine (sur la base de qui me parait incontournable au vu des notices techniques des composants)

Un jour peut être j'irai voir ces fonctions  de bas niveau (drivers Flash-SPI dans l'IDF) et je découvrirai que ça se passe autrement ;)
En attendant au vu de la doc W25Q32BV et de la librairie Arduino j'en reste à ce qui me parait le plus plausible même si cela parait peu élégant et illogique à première vue.

dbrion06

JE reste toujours intrigué par le fait que l'on peut aussi profiter d'une librairie, spiffs, qui assure l'équilibrage de l'usure "wear levelling" au prix de temps longs et variables (j'ai joué avec les programmes de démo, qui mesurent les temps d'écriture: d'un essai à l'autre, les temps variaient beaucoup). Si l'usure de l"eeprom"flash est un problème, ou si on est paresseux (gestion de fichiers presque classiques) , c'est peut être interessant.

al1fch

Si l'usure de l'EEPROM émulée en Flash est un réel problème  à l'échelle de la durée de vie présumée de l'objet alors oui, autant profiter de SPIFFS.
A chacun de peser le pour et le contre dans les situations qu'il rencontre.
l'EEPROM dans ce fil a été proposée  comme une des solutions possibels sans négliger cette question


rer67

bonsoir,

j'ai tout de meme encore un soucis d'enregistrement dans l'eeprom ...

- je veux enregistrer dans EepromE la variable "entrée" si supérieur de 10 de la valeur de l'eepromE en mémoire
- je veux enregistrer dans EepromS la variable "sortie" si supérieur de 10 de la valeur de l'eepromS en mémoire

Au démarrage je charge les valeurs des eepromE et eepromS :

Code: [Select]
// Chargement des valeurs d'eeprom's
  EEPROM.begin(2); // 2 octets pour le int à sauver
  eepromE = EEPROM.read(1) * 256 + EEPROM.read(2);
  entree = eepromE;
  Serial.print("nombre d'entrée reprise de l'eeprom: ");
  Serial.println(entree);
 
  eepromS = EEPROM.read(4096) * 256 + EEPROM.read(4097);
  sortie = eepromS;
  Serial.print("nombre de sortie reprise de l'eeprom: ");
  Serial.println(sortie);
  delay(100);


puis dans loop :

Code: [Select]
// Sauvegarde du nombre d'entrée dans l'eeprom si " entrée +10 "
      eepromE = EEPROM.read(1) * 256 + EEPROM.read(2);
   if (eepromE + 10 == entree) {
        EEPROM.write(1, uint8_t(entree / 256));
        EEPROM.write(2, uint8_t(entree % 256));
        EEPROM.commit();
    }   
// Sauvegarde du nombre de soties dans l'eeprom si " sorties +10 "
      eepromS = EEPROM.read(4096) * 256 + EEPROM.read(4097);
   if (eepromS + 10 == sortie) {
        EEPROM.write(4096, uint8_t(sortie / 256));
        EEPROM.write(4097, uint8_t(sortie % 256));
        EEPROM.commit();
    }   


j'ai mis 1,2 et 4096,4097 pour utiliser uniformément la mémoire et eviter l'usure prématurée.

MAIS ....
la valeur de mon eproomS reste toujours à 0 !!

al1fch

Bonsoir

désolé ! :smiley-red:  j'ai été imprudent en proposant de répartir l'usure de la Flash sur plusieurs secteurs, c'était une 'fausse bonne idée" que je n'avais pas testée.

En relisant la description de la librairie EEPROM pour ESP8266 on voit qu'elle est  limitée à  un secteur unique Pas question donc avec cette librairie d'étendre l'EEPROM émulée sur plusieurs secteurs de mémoire Flash.

lien : https://arduino-esp8266.readthedocs.io/en/2.5.2/libraries.html#eeprom
Quote
EEPROM.begin(size)  : before you start reading or writing, size being the number of bytes you want to use. Size can be anywhere between 4 and 4096 bytes........... EEPROM library uses one sector of flash located just after the SPIFFS.

rer67

hello !

merci de ta réponse... c'est pas grave ! je vais essayer de corriger !

rer67

J'ai essayé de faire un enregistrement sur l'eeprom quand la tension d'alimentation disparaît sur D6.
pour cela j'ai fait une interruption :

Code: [Select]

// PInteruption coupure alim
   #define interpin D6 // D6 pour pin interuption de perte de 3V sur GPIO12

Code: [Select]
// Interuption D6
   attachInterrupt(digitalPinToInterrupt(interpin), sauvEeprom, FALLING);

Code: [Select]
// Sauv eproom's en cas de coupure d'alimentation
ICACHE_RAM_ATTR void sauvEeprom() {     // via interuption

   Serial.println("perte alim");
        EEPROM.write(1, uint8_t(entree / 256));
        EEPROM.write(2, uint8_t(entree % 256));
        EEPROM.write(3, uint8_t(sortie / 256));
        EEPROM.write(4, uint8_t(sortie % 256));
        EEPROM.commit();
}


Cependant, la fonction "sauvErprom" ne se lance pas ... et la compilation ne montre pas d'erreur ...

rer67

Bonsoir

désolé ! :smiley-red:  j'ai été imprudent en proposant de répartir l'usure de la Flash sur plusieurs secteurs, c'était une 'fausse bonne idée" que je n'avais pas testée.

En relisant la description de la librairie EEPROM pour ESP8266 on voit qu'elle est  limitée à  un secteur unique Pas question donc avec cette librairie d'étendre l'EEPROM émulée sur plusieurs secteurs de mémoire Flash.

lien : https://arduino-esp8266.readthedocs.io/en/2.5.2/libraries.html#eeprom
ça y est c'est corrigé !
Code: [Select]
// Chargement des valeurs d'eeprom's
  EEPROM.begin(8); // 2 octets pour le int à sauver
  eepromE = EEPROM.read(1) * 256 + EEPROM.read(2);
  entree = eepromE;
  Serial.print("nombre d'entrée reprise de l'eeprom: ");
  Serial.println(entree);

  eepromS = EEPROM.read(3) * 256 + EEPROM.read(4);
  sortie = eepromS;
  Serial.print("nombre de sortie reprise de l'eeprom: ");
  Serial.println(sortie);
  delay(100);


merciii

rer67

J'ai essayé de faire un enregistrement sur l'eeprom quand la tension d'alimentation disparaît sur D6.
pour cela j'ai fait une interruption :

Code: [Select]

// PInteruption coupure alim
   #define interpin D6 // D6 pour pin interuption de perte de 3V sur GPIO12

Code: [Select]
// Interuption D6
   attachInterrupt(digitalPinToInterrupt(interpin), sauvEeprom, FALLING);

Code: [Select]
// Sauv eproom's en cas de coupure d'alimentation
ICACHE_RAM_ATTR void sauvEeprom() {     // via interuption

   Serial.println("perte alim");
        EEPROM.write(1, uint8_t(entree / 256));
        EEPROM.write(2, uint8_t(entree % 256));
        EEPROM.write(3, uint8_t(sortie / 256));
        EEPROM.write(4, uint8_t(sortie % 256));
        EEPROM.commit();
}


Cependant, la fonction "sauvErprom" ne se lance pas ... et la compilation ne montre pas d'erreur ...
je me reponds :
il faut placer
Code: [Select]
// Sauv eproom's en cas de coupure d'alimentation
ICACHE_RAM_ATTR void sauvEeprom() {     // via interuption

   Serial.println("perte alim");
        EEPROM.write(1, uint8_t(entree / 256));
        EEPROM.write(2, uint8_t(entree % 256));
        EEPROM.write(3, uint8_t(sortie / 256));
        EEPROM.write(4, uint8_t(sortie % 256));
        EEPROM.commit();
}


avant le setup !

Go Up