Je suis en train de communiquer d'un raspberry vers un arduino mega en USB et je me suis rendu compte que les infos transmises initialement n'était pas correctement assimilées par le code arduino (données de 0 à 65535 coté raspberry, mais arduino relit de -32766 à 32768 environ) ==> chose qui ne me convient pas.
J'ai cependant réussi à contourner cette problématique en adaptant le code, mais je n'arrive à correctement affecter la valeur envoyée à une variable de l'arduino.
le code est le suivant (il permet bien de récupérer les données => visible dans le moniteur) :
void loop() {
if (Serial.available() )
{
int datalength = Serial.readBytes(buf, BUFFER_SIZE);
{
for(int i = 0; i < datalength; i++)
{
Serial.print(buf[i]);
}
}
}
}
J'avais eu l'idée de mettre un : variable = Serial.print(buf[i]) mais ça casse le réassemblage de la donnée.
Comment je peux faire pour qu'a la fin de la boucle for, je puisse affecter le contenu du tableau à une variable ?
Bonjour, pour commencer variable = Serial.print(buf[i]) signifie que tu veux affecter à la variable "variable" la valeur de retour de la fonction d'affichage, qui je crois est "void" (aucun retour).
Je suppose que ce n'est pas le code que tu donne qui affiche une valeur sur 16bits.
Le soucis que tu rencontre est que la valeur "binaire" est assigné au mauvais type "int" au lieu d'un " Unsigned int"
Il pourrait y avoir une autre cause au problème.
Tu codes sur 2 plateformes différentes et le type int est plateforme dépendant.
Si tu veux échanger des données entre 2 plateformes différentes et avoir le contrôle sur le type de celles-ci, il faut :
soit échanger les valeurs en texte avec des printf(), et faire la conversion avec atoi() à la réception
soit échanger les valeurs en binaire avec des write(). Dans ce cas pour maitriser le format des données utiliser des types non ambigus, uint16_t par exemple pour passer des entiers non signés sur 16 bits.
Il faut aussi définir un minimum de protocole pour savoir retrouver les données afin de reconstruire les nombres correctement.
Bonjour, merci pour vos réponses.
Typiquement coté raspberry, j'envoie les datas via :
#code python
val = 592100 # une valeur comprise entre 0 et 65535
ser.write(str(val).encode('utf-8')+b'\n')
coté arduino, j'utilise le code du premier poste et il reçoit bien la valeur envoyée, mais chiffre par chiffre. Ce qui est normal, mais j'aimerai concaténer les valeurs reçues afin d'affecter la valeur envoyée (dans l'exemple 592100) à la variable.
Je vais essayer avec strcat...
Si tu lit caractère par caractère coté Arduino, c'est que le problème vient de ta sérialisation du coté python.
Désolé, avec ton code, je ne vois d'où peut venir le problème.
Peut être que si tu affiche exactement ce que tu envois et tu reçois ?
#!/usr/bin/env python
#executer avec python3
import epics
import time
import serial
if __name__ == '__main__':
ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)
while True:
val = 59210
print ("rpi =",val)
ser.write(str(val).encode('utf-8')+b'\n')
time.sleep(0.5)
line = ser.readline().decode('utf-8')
print (line)
ici le code arduino :
unsigned char prescaler = 0b00001101; // variable d'ajustement du prescaler en fonction de la valeur de frequence
int valeur = 65535; // frequenceInt
int prescal = 0;
const int BUFFER_SIZE = 50;
char buf[BUFFER_SIZE];
char val[5];
void setup () {
delay(10000);
Serial.begin(115200);
}
// =================
// Boucle principale
// =================
void loop ()
{
if (Serial.available()) // ici on regarde si qqechose vient de l USB
{
int rlen = Serial.readBytes(buf, BUFFER_SIZE);
for(int i = 0; i < rlen; i++)
{
Serial.println(buf[i]);
}
}
}
Essaies de lire ton port série avec Serial.readStringUntil('\n'); ainsi:
unsigned char prescaler = 0b00001101; // variable d'ajustement du prescaler en fonction de la valeur de frequence
int valeur = 65535; // frequenceInt
int prescal = 0;
const int BUFFER_SIZE = 50;
char buf[BUFFER_SIZE];
char val[5];
void setup () {
delay(10000);
Serial.begin(115200);
}
// =================
// Boucle principale
// =================
void loop ()
{
if (Serial.available()) // ici on regarde si qqechose vient de l USB
{
String chiffreRecuSerie = Serial.readStringUntil('\n');
chiffreRecuSerie.trim(); // Ecentuellement pour nettoyer la réception
long chiffreRecu = chiffreRecuSerie.toInt();
}
}
Pour debugger, il serait plus intéressant d'afficher "str(val).encode('utf-8')+b'\n'"
En tous cas ton output me semble correspondre à tes attentes
tu envoi 59210 et tu reçois bien 5 9 2 1 0 + un caractère, peut être le \n, mais je n'ai pas l'impression.
void loop ()
{
if (Serial.available()) // ici on regarde si qqechose vient de l USB
{
String chiffrerec = Serial.readStringUntil('\n');
chiffrerec.trim();
long chiffre = chiffrerec.toInt();
Serial.println(chiffre);
}
}
cela me retourne la même chose qu'avec le précédent code, c'est à dire :
La question est vague.
Soit tu veux concaténer 5, 9, 2, etc. dans une chaîne, et ça c'est déjà fait.
Soit tu veux les transformer en valeur numérique, et je t'ai donné plusieurs solutions.
Tout d'abord ce n'est pas le moniteur, c'est le terminal dans lequel tu as lancé PYTHON
Ton problème se situe côté PYTHON.
ser.readline() attend une chaîne terminée par '\n', mais là je ne vois pas de prime abord pourquoi print() affiche un seul caractère à la fois.
String chiffreRecuSerie = Serial.readStringUntil('\n');
chiffreRecuSerie.trim(); // Ecentuellement pour nettoyer la réception
long chiffreRecu = chiffreRecuSerie.toInt();
chiffreRecuSerie.toInt(); retourne, en réalité, une variable de type long.