Go Down

Topic: EEPROM programme débutant (Read 125 times) previous topic - next topic

Jean24816

Bonjour à tous,


Voici mon problème:


Code: [Select]


#include <EEPROM.h>
void setup() {
  Serial.begin(9600);
  union data {
    float f;
    int i;
  } convert;

  float f = 1.23;  // 00000001 .  00001011
  convert.f = f;

  EEPROM.write(0, highByte(convert.i)); //00000001
  EEPROM.write(1, lowByte(convert.i));  //00001011

  //----------------------------------

  byte high = EEPROM.read(0);
  byte low = EEPROM.read(1);

  convert.i = (high << 8) + low;
  f = convert.f;

  Serial.println(convert.i);
  Serial.println();
  Serial.println(f);

}

void loop() {
  // put your main code here, to run repeatedly:

}


J'ai pour résultat :

1-  convert.i  : 28836                  incorrect

2-             f   :  1.23            correct

Merci pour votre attention


JPD

hbachetti

Faire une union entre un float et un int n'a aucun sens. Un float d'autre part a une taille de 32bits.
Si tu nous parlais plutôt de ce que tu veux exactement faire ?
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

lesept

L'entier n'est pas initialisé, comment peux-tu savoir s'il est incorrect ?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

hbachetti

Il s'agit d'une union. Les deux variables membres se recouvrent (partiellement car elles n'ont pas la même taille).
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

dbrion06

"Faire une union entre un float et un int n'a aucun sens. Un float d'autre part a une taille de 32bits."

Faux: ça veut dire qu'on reserve la place la plus grande pour un float et un int , soit 4 octets.
(c'est le sosie de EQUIVALENCE en Fortran,  qui était souvent interdit, car source de désordre - même si ça faisait un sens pour un compilateur ou un lecteur très soigneux et que ça continue de faire un sens, tout en restant abominable)

https://github.com/DFRobot/DFRobot_PH/blob/master/DFRobot_PH.cpp
gère proprement, à mon sens, les écritures et lectures en EEPROM (sans avoir à se soucier de la taille, calculée par sizeof

Code: [Select]


#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}


(l'utilisateur n'a pas à se soucier de la nature de ce qu'il veut stocker, qui est forcé à un tableau d'octets)

dbrion06

(partiellement car elles n'ont pas la même taille)
Ceci a un sens pour les arduino basés sur avr (le int a 16 bits); les arduini basés sur arm ou esp ont ils des "int" de 16 bits?

Par ailleurs, si on veut écrire en EEPROM deux nombres, et les récupérer, il faut veiller à ce que le dernier ne squatte pas l'adresse de l'autre (seul le dernier écrit sera recupérable, sinon; est ce souhaitable)
Pour écrire un entier puis un réel, j'écrirais (non testé)
Code: [Select]


#include <EEPROM.h>


#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

void setup() {
  Serial.begin(115200);
  int a = 12345, aLu=-1;
  float b=56.78, bLu=-9.0;
  int addr_a=0;
  int addr_b;
  addr_b= addr_a + sizeof(a); // évite chevauchement
  EEPROM_write(addr_a, a);
  EEPROM_write(addr_b, b);
 
  EEPROM_read(addr_a, aLu);
  EEPROM_read(addr_b, b_lu);
Serial.println(aLu);
Serial.println(bLu);
}
void loop{}

kamill

#6
Oct 21, 2019, 05:26 pm Last Edit: Oct 21, 2019, 05:30 pm by kamill
Comme le dit hbachetti on de peut pas interpréter un bout d'un float comme un entier.
Il suffit de voir la structure d'un float pour se rendre compte que ça n'a aucun sens.

hbachetti

#7
Oct 21, 2019, 05:27 pm Last Edit: Oct 21, 2019, 05:27 pm by hbachetti
Dans le monde ARDUINO l'int est codé sur 2 octets, le float sur 4 octets.
Chercher à faire l'union d'un int est d'un float, deux entités radicalement différentes, ne rime à rien.

Code: [Select]

  float f;
  EEPROM.put(0, 1.23);
  EEPROM.get(0, f);
  Serial.println(f);

Cela donne bien le résultat attendu, sans gymnastique inutile.

EEPROM::put() et EEPROM::get() sont deux fonctions template qui tiennent compte du type de la variable passée en paramètre.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...


dbrion06

"Chercher à faire l'union d'un int est d'un float, deux entités radicalement différentes, ne rime à rien."


Ca rime à chercher à économiser 2 (cas des avr) ou 4 octets, avec un  risque enorme de confusion (c'était utilisé, quoique interdit, dans les années 80 pour recouvrir, disons un tableau d'entiers par un tableau de reels, en pariant qu'ils ne seraient jamais utilisés simultanément: le gain de place permettait de faire fonctionner des logiciels interessants -ils rimaient à quelque chose pour les utilisateurs qui n'étaient pas poetes!-  sur de très petits calculateurs, même pour l'époque, au prix d'enormes problèmes de maintenance).

Go Up