Bonjour J-M-L
Est-ce possible si l'on envoie une structure?
Cordialement
jpbbricole
Bonjour J-M-L
Est-ce possible si l'on envoie une structure?
Cordialement
jpbbricole
Bien évidemment. Voir mon post #49.
Un protocole peut blinder l'affaire :
Il faut des caractères de début et fin de paquet :
Si la taille des données reçues (elle doit être égale à sizeof (struct)) n'est pas la bonne : poubelle.
Possibilité d'ajout d'un caractère d'acquittement ACK ou de non acquittement NACK renvoyé par le récepteur. Si NACK reçu par l'émetteur -> répétition.
Possibilité d'ajout d'un caractère de N° de paquet pour s'assurer que le récepteur ne reçoit pas deux fois le même.
Possibilité d'ajout d'un checksum, ou mieux (CRC) si l'on veut garantir l'intégrité des données
Cela peut aller loin.
Tout dépend de l'importance des données.
Comme apparemment il s'agit d'un système de test pour une carte (je suppose), la réception d'un paquet erroné pourrait amener à conclure que la carte testée est KO alors qu'elle est OK.
Il y a aussi le "silence ligne" utilisé comme séparateur.
Un "silence ligne" est détecté si aucun octet n'est reçu pendant "un certain temps".
Tant qu'il n' a pas détecté un silence, le récepteur poubellise tout ce qu'il reçoit.
On peut aussi mettre à ligne à l'état BREAK entre chaque trame envoyée.
Mais c'est un peu plus compliqué.
Bonsoir
Bien sûr tout peut arriver, l’écriture série n’est pas un mode de transport garanti avec confirmation d’intégrité totale du message. Chaque octet est émis indépendamment avec une dose d’asynchrone en fonction de ce que fait l’arduino et la disponibilité des interruptions pour émettre l’octet suivant.
De plus vous ne savez pas non plus comment ça se passe au niveau réception, si le code est un peu lent et la structure un peu importante vous risquez de remplir le buffer de réception et donc de perdre des octets.
C’est pour cela qu’il est conseillé de mettre en place un protocole dés que le message envoyé fait une plus d’un octet.
J'ai fait des recherches sur internet et bricolé quelques lignes de code que je présente ci-dessous. J'utilise une union et envoie les octets par paquet mais je n'obtient rien sur le moniteur. Le problème provient probablement de mon if...
union {
uint8_t bytes[4];
float d_value;
} bytefloat;
float send_buffer[12]; // Nombre tottal d'octet à envoyer sur l'IHM
float Voltage1 = 3.325; // Première niveau de tnsion
bytefloat.d_value = Voltage1;
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
// Conversion et envoie de la valeur de tension en octet
if (!SerialUSB.write ((uint8_t*) &Voltage1, 4)) {
while (1);
}
float Voltage2 = 2.125; // deuxième niveau de tnsion
bytefloat.d_value = Voltage; 2
send_buffer[4] = bytefloat.bytes[0]; // Envoie du premier octet
send_buffer[5] = bytefloat.bytes[1]; // Envoie du deuxième octet
send_buffer[6] = bytefloat.bytes[2]; // Envoie du troisième octet
send_buffer[7] = bytefloat.bytes[3]; // Envoie du quatrième octet
if (!SerialUSB.write ((uint8_t*) &Voltage2, 4)) {
while (1);
}
float Voltage3 = 0.525; // trosème niveau de tnsion
bytefloat.d_value = Voltage3;
send_buffer[8] = bytefloat.bytes[0]; // Envoie du premier octet
send_buffer[9] = bytefloat.bytes[1]; // Envoie du deuxième octet
send_buffer[10] = bytefloat.bytes[2]; // Envoie du troisième octet
send_buffer[11] = bytefloat.bytes[3]; // Envoie du quatrième octet
if (!SerialUSB.write ((uint8_t*) &Voltage3, 4)) {
while (1);
}
Sans informations supplémentaire je ne vois même pas l'intérêt d'aller plus loin.
D'autre part certaines questions n'ont pas eu de réponse.
Enfin, avoir une idée de la finalité du projet aiderait certainement à proposer une solution adaptée.
A la réponse 2 on vous a déjà dit que l’union n’était pas une façon correcte d’accéder aux octets en C++… on dirait que la boucle est bouclée…
Le récepteur est codé en delphi pascal et une vitesse de 250 000b/s pourrait être utilisée.
Faites un protocole simple de transfert en ASCII.
Du coup je ne sais pas comment faire pour que tous les floats soient transmis correctement. J'ai bien pris en compte l'idée de mettre en place un protocole mais je sèche à trouver comment faire cela ![]()
Ca fait 72 messages qu'on tourne en rond.
Envoies les mesures sous formes ascii avec un format simple du genre
S5.24;6.41;5.22;4.99;5.00;6.54\n
comme ça tu pourras les voir sur ton terminal pour les tests et mises au point.
Tu communiques le format à celui qui doit les recevoir et il pourra les exploiter sans problème, sans avoir à se poser la question du codage interne des variables sur l'arduino.
Commencez par un truc tout simple
Serial.write(‘<‘); // marqueur de début
Serial.print(valeur1); // donnee
Serial.write(‘,‘); // separateur
Serial.print(valeur2);
Serial.write(‘,‘); // separateur
Serial.print(valeur3);
Serial.write(‘,‘); // separateur
Serial.print(valeur4);
Serial.write(‘>’); // marqueur de fin
(Tapé sur mon tel les write doivent utiliser des simple quote)
Ok merci pour cet exemple.
J'ai une question: c'est quoi l'intérêt de mettre les séparateurs et les marqueurs avec le write ? alors que les données sont imprimées ? ![]()
Bonjour victorelec
Voilà un petit exemple, sur Arduino Mega, entre leur port Serial1 à 115 200
Côtè émetteur
struct donneesMesureesDef
{float voltageA; float voltageB; float voltageC;};
donneesMesureesDef donneesAtransmettre;
unsigned long loopTime = 500; // Toutes lkes 500 milliSecondes
unsigned long loopTimeR = millis();
void setup()
{
Serial.begin(115200);
Serial1.begin(115200);
donneesAtransmettre.voltageA = 12.55;
donneesAtransmettre.voltageB = 2.03;
donneesAtransmettre.voltageC = 3750.20;
}
void loop()
{
if (millis()-loopTimeR >= loopTime)
{
Serial1.write((byte *)&donneesAtransmettre, sizeof donneesAtransmettre);
donneesAtransmettre.voltageA += 0.25;
donneesAtransmettre.voltageB += 1.1;
donneesAtransmettre.voltageC += 110.02;
loopTimeR = millis();
}
}
Côtè récepteur
struct donneesMesureesDef
{float voltageA; float voltageB; float voltageC;};
donneesMesureesDef donneesAtransmettre;
bool nouvellesDonnes = false;
void setup()
{
Serial.begin(115200);
Serial1.begin(115200);
}
void loop()
{
if (Serial1.available())
{
Serial1.readBytes((byte*)&donneesAtransmettre, sizeof donneesAtransmettre);
nouvellesDonnes = true;
}
if (nouvellesDonnes)
{
Serial.println("\n");
Serial.print(donneesAtransmettre.voltageA); Serial.print("\t");
Serial.print(donneesAtransmettre.voltageB); Serial.print("\t");
Serial.print(donneesAtransmettre.voltageC); Serial.print("\t");
nouvellesDonnes = false;
}
}
Côté émetteur, les 3 valeurs float sont incrémentées à chaque émission, pour voire les "mouvements" au récepteur.
Cordialement
jpbbricole
write est utilisé pour envoyer un seul caractère.
Serial.write(',') fait la même chose que Serial.print(",") mais prend moins de ressources.
Merci beaucoup pour votre exemple de code !
Je dois décider avec le récepteur s'il peut accepter les données en ASCII, ça sera plus simple et plus compréhensible pour moi ![]()
Si l'on commence à proposer des solutions ultra-différentes (ASCII ou structure binaire) on ne va pas s'en sortir.
D'après ce que je vois dans le code #67 victorelec ne maîtrise absolument pas les notions de base (structures, unions, etc.).
Pour ma part je retiendrais la proposition de J-M-L en #74, très simple à appréhender.
D'autre part le récepteur est codé en DELPHI.
Pour une question d'interopérabilité une transmission ASCII + séparateurs est préférable.
OK merci beaucoup !
Bonjour hbachetti
Et pourquoi pas !!!
Cette proposition va tout à fait dans l'esprit du sujet.
Le but d'un forum est d'exposer des idées et il n'y a pas que les protagonistes qui lisent ce fil, donc ça peut servir à d'autres.
Cordialement
jpbbricole