Envoi et réception de données via port série

Bonjour à tous en ce début d'année 2014, au passage bonne année!

Je viens quérir votre aide dans le cadre d'un projet d'école! Bah oui je suis en informatique industrielle et l'arduino est un chouette joujou pour fabriquer des petits systèmes. :stuck_out_tongue:

Dans ce cadre donc, je construit un régulateur de pH constitué d'un arduino MEGA, d'une carte avec amplis pour la sonde de pH, un double pont en H pour mes moteurs qui actionnent des seringues pour verser de l'acide ou de la base pour réguler le pH, et d'une interface en VB pour superviser le tout et bien évidement entrer les paramètres de contrôle.

Mes ennuis commencent là! En effet, je dois envoyer une valeur depuis l'interface en VB vrs l'arduino qui servira de consigne pour la régulation. Pour celà, j'ouvre une connexion série, j'envoie la sonsigne et je demande à l'arduino de me la renvoyer pour confirmer qu'elle a été bien reçue.

Voilà le code arduino que j'utilise:

void setConsigne(){
  attenteReception();
  
  consigne = Serial.read();
      
  Serial.print(consigne);
}

void attenteReception(){
  do{
    delay(50);
  }while(Serial.available() == 0);
}

Et du coté de l'interface VB:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        SerialPort1.Open()
        SerialPort1.Write("b")
        SerialPort1.Write(7)
        Sleep(200)
        Dim Incoming As Integer = SerialPort1.ReadExisting
        Label2.Text = Incoming
        SerialPort1.Close()
    End Sub

J'envoie donc comme consigne "7" vers l'arduino, qui le met dans une variable "consigne (orginial non? ^^) et est sensé me la renvoyer, mais je reçois "55" qui est le code ASCII de cette valeur, ce qui ne m'arrange pas, j'aimerais recevoir "7" logiquement!

Merci d'avance pour votre aide!

Deux solutions :

-soit côté arduino : faire

int val = Serial.read() - '0';
  • soit côté vb, changer
SerialPort1.Encoding

Merci pour cette réponse. Mais est-ce que tu pourrais m'expliquer ce que ça change? Car utiliser quelque chose qu'on donne c'est bien, mais j'aimerais surtout comprendre pourquoi ma solution ne fonctionne pas.

EDIT: je viens de tester ta solution coté Arduino, le problème c'est que cela fonctionne avec une valeur entière, mais j'aimerais pouvoir envoyer une valeur avec jusqu'à 2 décimales et apparement cette solution ne le permet pas. :~

Désolé de ce petit up mais j'ai remodifié par la suite mon dernier message et je ne pense pas que ça a été pris en compte.

Je disais donc que j'arrive bien à retrouver mon "7", mais j'aimerais pouvoir envoyer et recevoir un nombre avec 2 décimales afin d'effectuer un réglage plus précis. J'ai testé les 2 solutions: la première fonctionne mais uniquement avec des entiers, la seconde me met une erreur dans mon code VB.

Bonjour,

Reapper:
Je disais donc que j'arrive bien à retrouver mon "7", mais j'aimerais pouvoir envoyer et recevoir un nombre avec 2 décimales afin d'effectuer un réglage plus précis. J'ai testé les 2 solutions: la première fonctionne mais uniquement avec des entiers, la seconde me met une erreur dans mon code VB.

Je pense que Serial.parseFloat() devrait t'aller :

skywodd:
Je pense que Serial.parseFloat() devrait t'aller :
Serial.parseFloat() - Arduino Reference

Je ne sais pas si tu l'as testée mais elle est extrêmement lente ... Je ne suis pas allé voir ce qu'ils ont mis derrière et j'ai pas vraiment chronométré mais je pense qu'on est pas loin de la demi seconde pour un simple écho ...

B@tto:
Je ne sais pas si tu l'as testée mais elle est extrêmement lente ... Je ne suis pas allé voir ce qu'ils ont mis derrière et j'ai pas vraiment chronométré mais je pense qu'on est pas loin de la demi seconde pour un simple écho ...

J'ai testé pas mal de fois parseInt(), mais parseFloat() j'ai du l'utilisé qu'une fois (les float c'est le maaaaallll :grin:)
Si ça marche c'est le principal non :stuck_out_tongue:

skywodd:
Si ça marche c'est le principal non :stuck_out_tongue:

Oula, est-ce bien Skywodd que je lis ??!! :stuck_out_tongue:

B@tto:
Oula, est-ce bien Skywodd que je lis ??!! :stuck_out_tongue:

Oui oui, mais avec la fatigue je fini par trouver certaines fonctions bien trop pratique (comme parseInt) pour me plaindre :grin:

Salut à vous deux! Désolé de pas avoir donné de nouvelles, j'étais en période d'examens et le projet a été relégué à plus tard. Néanmoins j'ai suivi avec attention ce que vous disiez. J'ai voulu tester le parseFloat et parseInt mais j'ai une erreur de compilation, je suppose donc qu'il me manque une librairie. J'ai donc cherché et compris que parseFloat fait partie de la classe Stream, mais impossible de trouver comment l'utiliser.

Pour info la communication fonctionne maintenant parfaitement de l'arduino vers le PC, par contre du PC vers l'arduino ça bugue toujours: quand j'envois 7 de puis l'interface vers l'arduino, et que l'arduino me renvoie cette valeur vers le PC je reçois le code ACSII. Ca ne vient pas de la communication arduino > PC puisqu'une donnée codée en dur dans le programme arduino est transmise correctement, le problème est donc bien à la réception PC > arduino.

Pas besoin de librairie pour parseint ou parseFloat, mais d'une version de l'IDE à jour :wink:

Bon on va remettre les choses à plat : visiblement tu ne fais pas la différence entre encodage binaire et encodage ASCII. Côté Arduino : si tu fais Serial.write(), tu envois la donnée en binaire, c'est à dire que par exemple si tu envois 16, il enverra un seul byte qui sera 00010000. Maintenant si tu utilises Serial.print(16), deux bytes seront envoyés correspondant au code ASCII des caractères, soit ici 49 (='1') et 54 (='6'). Donc si tu veux faire communiqué deux systèmes, il faut parler la "même langue".

Côté VB.NET (je fais de mémoire) tout dépend ce que tu écris : SerialPort1.write("7") enverra 7 encodé en ASCII et Serial.write(7) enverra 7 en binaire.

Ensuite je n'avais pas remarqué mais un port soit resté ouvert, on ne fait pas des Serial.open() et des Serial.close() à chaque commande, sinon c'est vite le foutoir et tu ne peux pas profité des évènements qui y sont liées, notamment .DataReceived

B@tto:
Ensuite je n'avais pas remarqué mais un port soit resté ouvert, on ne fait pas des Serial.open() et des Serial.close() à chaque commande, sinon c'est vite le foutoir et tu ne peux pas profité des évènements qui y sont liées, notamment .DataReceived

Sans compter lors du Serial.open() tu risques de faire un reset arduino en ouvrant le port série.

B@tto:
Pas besoin de librairie pour parseint ou parseFloat, mais d'une version de l'IDE à jour :wink:

Mon IDE est à jour en principe, c'est la version 1.0.5.

B@tto:
Bon on va remettre les choses à plat : visiblement tu ne fais pas la différence entre encodage binaire et encodage ASCII. Côté Arduino : si tu fais Serial.write(), tu envois la donnée en binaire, c'est à dire que par exemple si tu envois 16, il enverra un seul byte qui sera 00010000. Maintenant si tu utilises Serial.print(16), deux bytes seront envoyés correspondant au code ASCII des caractères, soit ici 49 (='1') et 54 (='6'). Donc si tu veux faire communiqué deux systèmes, il faut parler la "même langue".

Je connais un peut le système merci. ^^
Par contre ce que tu dis sur le print est faux ou alors j'ai encore mal compris car j'utilise pour la connexion ce code sur l'arduino:

void connexion(){
  Serial.write('g');
  delay(50);
  Serial.print(consigne); 
  delay(50);
  Serial.print(erreur);
}

La consigne (7.15 par exemple) et l'erreur (0.20 par exemple) sont des float que je reçois parfaitement en clair sur l'interface en VB, j'utilise par contre le write pour les caractères et la réception fonctionne.

B@tto:
Côté VB.NET (je fais de mémoire) tout dépend ce que tu écris : SerialPort1.write("7") enverra 7 encodé en ASCII et Serial.write(7) enverra 7 en binaire.

J'ai essayé mais Serial.write n'existe pas en VB. J'utilise ce genre de code:

SerialPort1.Write(pH / 100)

pH étant un décimal.

B@tto:
Ensuite je n'avais pas remarqué mais un port soit resté ouvert, on ne fait pas des Serial.open() et des Serial.close() à chaque commande, sinon c'est vite le foutoir et tu ne peux pas profité des évènements qui y sont liées, notamment .DataReceived

Bonne remarque ça, je vais changer ça de suite.

Reapper:

B@tto:
Pas besoin de librairie pour parseint ou parseFloat, mais d'une version de l'IDE à jour :wink:

Mon IDE est à jour en principe, c'est la version 1.0.5.

Tu es sûr de l'utiliser comme il faut alors ? Serial.parseInt() - Arduino Reference

Reapper:
Je connais un peut le système merci. ^^
Par contre ce que tu dis sur le print est faux ou alors j'ai encore mal compris car j'utilise pour la connexion ce code sur l'arduino:

void connexion(){

Serial.write('g');
 delay(50);
 Serial.print(consigne);
 delay(50);
 Serial.print(erreur);
}




La consigne (7.15 par exemple) et l'erreur (0.20 par exemple) sont des float que je reçois parfaitement en clair sur l'interface en VB, j'utilise par contre le write pour les caractères et la réception fonctionne.

Oui visiblement tu n'as pas tout compris ^^ : les remarques pour l'émission sont valables pour la réception. Par défaut VB reçois en ASCII. En écrivant Serial.write('g') c'est exactement comme si tu avais écris Serial.print(103). VB "lisant" en ASCII à la réception il va refaire la correspondance, donc te donner le caractère g. Et forcement si tu print() une variable elle va bien être parfaitement interprétée par VB puisque encodée en ASCII.

Reapper:
J'ai essayé mais Serial.write n'existe pas en VB. J'utilise ce genre de code:

SerialPort1.Write(pH / 100)

pH étant un décimal.

C'est pas ça n'existe pas, il suffit juste de convertir ce que tu envois :wink:

Essaye : SerialPort1.Write(CStr(pH / 100))

Bon ben je dois être un peu con alors, parce que décidement j'y arrive pas. Voici un exemple de 2 codes sensés communiquer:

VB

Private Sub btnConsigne_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConsigne.Click
        SerialPort1.Write("c")
        Dim pH As Decimal
        pH = Convert.ToDecimal(txtConsigne.Text)
        SerialPort1.Write(pH * 100)
        pH = receptionDecimal()
        Label2.Text = pH
        ProgressBar1.Value = pH
End Sub

Arduino

void setConsigne(){
  consigne = Serial.parseInt() / 100;
  Serial.print(consigne);
}

Donc le code VB envoit "c" qui permet de rentrer dans un switch du code arduino qui redirige vers le setConsigne, cette partie fonctionne. Là normalement je récupère une valeur dans une textBox, que je converti en décimal (et que je multiplie par 100 histoire d'avoir un Int) et que j'envoie à sur le port série.

Coté arduino maintenant je récupère en principe un Int que je divise par 100 pour retrouver ma virgule. Je renvoie cette valeur vers le PC pour confirmation.

Là je reçois la donnée via la fonction:

Function receptionDecimal()
        Sleep(50)
        Dim Incoming As Decimal = 99
        Incoming = SerialPort1.ReadExisting
        Return Incoming
End Function

Qui me renvoit un décimal.

  consigne = Serial.parseInt() / 100;

Carton rouge!!!

Serial.parseInt retourne un int
100 constante int

résultat consigne n'a plus de décimales. Pas d'bol......

  consigne = (float)Serial.parseInt() / 100.0;

Reapper:
Bon ben je dois être un peu con alors, parce que décidement j'y arrive pas. Voici un exemple de 2 codes sensés communiquer:

VB

Private Sub btnConsigne_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConsigne.Click

SerialPort1.Write("c")
        Dim pH As Decimal
        pH = Convert.ToDecimal(txtConsigne.Text)
        SerialPort1.Write(pH * 100)
        pH = receptionDecimal()
        Label2.Text = pH
        ProgressBar1.Value = pH
End Sub




Arduino


void setConsigne(){
  consigne = Serial.parseInt() / 100;
  Serial.print(consigne);
}

Bah disons que si tu fais pas ce que jte conseille je vois pas comment ça pourrait changer ... En plus de la remarque de fdufnews