Go Down

Topic: communication I2C (Read 1 time) previous topic - next topic

Neneh

Bonjour,
j'utilise la communication I2C pour dialoguer entre ma carte UNO et MEGA.
je doit envoyé sur ma mega des variables float qui sont calculées sur ma UNO.( des position en degres)
je respecte l'exemple fournit mais ca ne marche pas! je precise que je suis un debuant ^^

  Wire.beginTransmission(4); // transmit to device #4
                Wire.write("L'azimut est");        // sends five bytes
                Wire.write(AzimutFinal);              // sends one byte 
                Wire.endTransmission();    // stop transmitting
             
               
                delay(500);

le message d'erreur est  "call of overloaded write(floa) is ambiguous"

merci d'avance pour votre aide 8) 8) 8) 8)


john_lenfr

Normal un write envoie un byte et tu lui mets un float.

Converti ta valeur avant de l'envoyer

B@tto

Salut,

L'i2c transmet des paquets de byte, donc write(float) forcement ça plante.

La solution la plus simple dans ton cas est de multiplié ton float par un multiple de 10 correspondant au nombre de virgule que tu souhaites, et de garder la partie entière, puis de faire l'inverse à l'arrivée.

Exemple : 18.65 à transmettre ==> sera envoyé 1865.

Maintenant il faut découper cet entier en byte. Si on condidère qu'un integer est suffisant, soit 2 bytes :

Code: [Select]
byte LSBbyte, MSBbyte;
LSBbyte = MonInt & 0xFF;
MSBbyte = MonInt >> 8;

Wire.beginTransmission(4);
Wire.write(MSBbyte);
Wire.write(LSBbyte);
Wire.endTransmission();  


A la reception

Code: [Select]
int MaValeur = (Wire.read()<<8) | Wire.read() ;
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Neneh


Salut,

L'i2c transmet des paquets de byte, donc write(float) forcement ça plante.

La solution la plus simple dans ton cas est de multiplié ton float par un multiple de 10 correspondant au nombre de virgule que tu souhaites, et de garder la partie entière, puis de faire l'inverse à l'arrivée.

Exemple : 18.65 à transmettre ==> sera envoyé 1865.

Maintenant il faut découper cet entier en byte. Si on condidère qu'un integer est suffisant, soit 2 bytes :

Code: [Select]
byte LSBbyte, MSBbyte;
LSBbyte = MonInt & 0xFF;
MSBbyte = MonInt >> 8;

Wire.beginTransmission(4);
Wire.write(MSBbyte);
Wire.write(LSBbyte);
Wire.endTransmission();  


A la reception

Code: [Select]
int MaValeur = (Wire.read()<<8) | Wire.read() ;


merci pourcette reponse  :) :)
je ne comprend pas la variable MonInt , je suis censé la remplacer par ma variable float? desolé pour mon faible niveau en programation :-/

koala

MonInt c'est ta variable float multiplié par 100. De cette façon tu te retrouve avec un entier que tu doit découper en deux octets, et les envoyer sur le bus I2C. A la reception, tu recolle tes deux octets pour te retrouver avec MonInt. Il ne te reste plus qu'à diviser par 100 pour retrouver ton float d'origine :)

jlbechennec

Bonjour,

Une autre solution pour transmettre un float et récupérer un float de l'autre côté est d'envoyer les octets qui composent le float. Un float occupe 4 octets. Pour accéder aux octets, on peut utiliser une union :

Code: [Select]

union floatbytes {
  float f;
  byte  b[4];
};


Une union ressemble à une struct. La différence est que tous les membres de l'union partagent la même zone mémoire.
Pour récupérer les octets d'un float il suffit d'instancier une variable de type floatbytes (l'union donc), :

Code: [Select]

floatbytes t;


d'écrire le float dedans en utilisant le membre de type float :

Code: [Select]

t.f = AzimutFinal;


et d'envoyer ses octets en accédant cette fois ci au tableau membre b

Code: [Select]

Wire.beginTransmission(4); // transmit to device #4
Wire.write("L'azimut est");
for (int i = 0; i < 4; i++) {
  Wire.write(t.b[i]);
}
Wire.endTransmission();    // stop transmitting
delay(500);


Côté réception, il suffit de faire l'inverse : récupérer les octets et les écrire dans le tableau b puis lire le membre f pour récupérer le float.

Go Up