J'essaie d'envoyer des variables float sous forme d'octet mais je rencontre des soucis lors de la compilation de mon code dont une partie est donnée ci-dessous. Dans ma condition if, quand je mets tout simplement Serial.write (Voltage), la compilation marche mais ce n'est pas la bonne façon de faire car ma variable Voltage est un float (4 octets) et non un simple octet. Je voudrais que ça marche avec les 4 octets mais il affiche des erreurs que je ne parviens pas à résoudre.
Si quelqu'un pourrait m'aider ça serait top
union {
uint8_t bytes[4];
float d_value;
} bytefloat;
float send_buffer[36]; // Nombre tottal d'octet à envoyer
bytefloat.d_value = Voltage;
send_buffer[0] = bytefloat.bytes[0]; // Envoie du premier octet
send_buffer[1] = bytefloat.bytes[1]; // Envoie du deuxième octet
send_buffer[2] = bytefloat.bytes[2]; // Envoie du troisième octet
send_buffer[3] = bytefloat.bytes[3]; // Envoie du quatrième octet
if (!Serial.write (Voltage,4)) {
while (1); // Attendre que l'envoie de donnée soit fini
}
Merci @J-M-L pour votre réponse. J'utilise du C et ,non du C++. Est ce que c'est pareil ?
Pour votre remarque importante, je pensais que cette ligne de code pourrait permettre à l'arduino d'attendre que l'envoie du premier float soit fini avant d'envoyer le suivant. Comment puis-je faire cela alors ?
Merci d'avance !
Est ce que vous voulais dire aussi que je n'ai plus besoin de ces commandes du coup ?
bytefloat.d_value = Voltage;
send_buffer[0] = bytefloat.bytes[0]; // Envoie du premier octet
send_buffer[1] = bytefloat.bytes[1]; // Envoie du deuxième octet
send_buffer[2] = bytefloat.bytes[2]; // Envoie du troisième octet
send_buffer[3] = bytefloat.bytes[3]; // Envoie du quatrième octet
Vos deux lignes de code font quoi concrètement ?
float v = 123.456;
Serial.write((uint8_t*) &v, sizeof v);
ça me semble très simple par rapport à ce que j'ai proposé. J'aimerais en savoir un peu plus si possible
va envoyer les 4 octets d'un coup pour vous, vous n'avez pas besoin de l'union.
&vc'est l'adresse en mémoire du nombre décimal, un pointeur vers le premier octet. Comme on pointe vers un nombre de type float, ce pointeur est de type (float*) mais la fonction write ne gère pas ce type de pointeur. Le C ou C++ vous laisse transformer ce pointeur vers un type de pointeur d'octets, et donc c'est pour cela que je mets (uint8_t*) devant pour le convertir en pointeur vers un octet, comme attendu par la fonction write(). Ensuite je dis combien d'octets envoyer, l'opérateur sizeofsert exactement à cela (ici combien d'octets sont nécessaires pour représenter la variable v)
ça me semble très simple par rapport à ce que j'ai proposé
Il faut aussi se poser la question du récepteur.
S'il s'agit d'un autre logiciel en C sur PC ou ARDUINO ou autre, pas de problème. La norme IEEE-754 impose le format (23 bits pour la mantisse, 8 bits pour l'exposant, 1 bit pour le signe).
S'il s'agit d'un logiciel codé dans un autre langage, cela risque d'être problématique.
Exemple : PYTHON où les floats sont codés sur 64bits.
La norme IEEE-754 impose également le format des nombres flottants sur 64 bits (52 bits pour la mantisse, 11 bits pour l'exposant, 1 bit pour le signe).
Si la vitesse de transmission n'est pas un critère essentiel, pourquoi ne pas envoyer ce nombre sous forme ASCII ? Serial.print(123.456);
Ne pas oublier non plus qu'en cas de ratage d'un octet, le récepteur risque de se désynchroniser, et attendre longtemps un quatrième octet qui n'arrive pas. Serial.println(123.456, 3);
Serial.println() ajoutera un caractère fin de ligne que le récepteur pourra facilement interpréter comme terminateur.
Voir par exemple Serial.readBytesUntil() : si le récepteur est un ARDUINO, ou ESP.
A mon avis il faut bannir atof() et atoi() et plutôt recommander utiliser strtod() et strtol() en utilisant le pointeur. ça permet de savoir si la fonction a retourné 0 parce que le nombre était bien 0 plutôt que parce que la chaîne fournie ne contenait pas un nombre décodable.
exemple de code:
char d1[] = "123.456ABCD";
char d2[] = "ABCD";
void setup() {
Serial.begin(115200);
char* ptr;
double x;
x = atof(d1);
Serial.print("atof(d1) = ");
Serial.println(x, 10);
x = strtod(d1, &ptr);
if (ptr == d1) Serial.println("d1 Erreur de contenu");
else {
Serial.print("strtod(d1) = ");
Serial.println(x, 10);
if (*ptr != '\0') {
Serial.print("Il y a avait du texte après le scan ");
Serial.println(ptr);
}
}
Serial.println();
x = atof(d2);
Serial.print("atof(d2) = ");
Serial.println(x, 10);
x = strtod(d2, &ptr);
if (ptr == d2) Serial.println("d2 Erreur de contenu");
else {
Serial.print("strtod(d2) = ");
Serial.println(x, 10);
if (*ptr != '\0') {
Serial.print("Il y a avait du texte après le scan ");
Serial.println(ptr);
}
}
}
void loop() {}
Comme il s'agit d'une tension, la surcharge occasionnée par l'envoi en ASCII devrait être faible.
"12.36" -> 6 octets en comptant le terminateur
Ensuite le temps de conversion côté récepteur ne devrait pas être excessif, sans commune mesure avec le temps de conversion ADC côté émetteur.