Communication TX/RX entre 2 arduinos & EasyVR

Bonjour,

Je suis actuellement en école d'ingénieur et mon projet est de réaliser des actions (fermeture de volet par exemple) grâce à la commande vocale par EasyVR.
J'ai donc à ma disposition 1 module EasyVR, 2 modules XBee + Shield, 2 cartes Arduino UNO R3.

J'ai plusieurs questions mais ma principale question concerne la communication entre ma carte arduino émettrice et ma carte réceptrice.

Le EasyVR est connecté sur l'émetteur.
Le TX de l'émetteur est connecté au RX du récepteur et vice-versa.

J'arrive bien à dire "Allume la led" et l'algo de l'émetteur envoie sur le port série un caractère 'A' et en face le récepteur lit la donnée et si celle-ci est 'A' alors la LED s'allume. Aucun problème jusque là.

Maintenant, mon problème est que les équipements seront connectés sur l'arduino récepteur. (11 pins digitales libres (vu que deux seront prises par le module XBee à savoir TX et RX, 6 pins analogiques (qui pourront être des sorties digitales ?)).
Mes équipements seront: 2 moteurs CC (pour volet et porte), 1 led RGB, 1 capteur de température, 1 servo moteur, 1 écran LCD.

Mon écran LCD prend 7 pins ( 6 pins de data + 1 de l'alimentation (que je veux contrôler vocalement)).
L'objectif est d'afficher la température sur l'écran. Comme j'ai un problème de nombres de pins j'aimerai mettre cet écran sur l'arduino récepteur afin d'avoir plus de pins sur le récepteur.

Je voudrai donc dire "Prend la température", l'arduino 1 (émetteur) va envoyé un caractère 'T' et si en face le récepteur lit 'T' alors il prend la température, fait les calculs pour l'obtenir en °C puis renvoie la donnée au dixième près. Ma question est celle-ci: comment renvoyé la donnée (j'imagine en faisant un Serial.write(calculCelcius(data))) mais en face comment écrire dans l'algorithme "attends de recevoir la donnée.

J'aurai d'autre questions sur les interruptions mais j'essaie d'avancer étape par étape.

Merci à vous ! Bonne journée

Sxndrome:
Comme j'ai un problème de nombres de pins j'aimerai mettre cet écran sur l'arduino récepteur afin d'avoir plus de pins sur le récepteur.

Je crois que je m'y perds avec tous ces récepteurs! :slight_smile:
Pourquoi ne pas laisser l'écran sur l'émetteur, puisqu'il n'y a que deux broches de prises, si j'ai bine compris, par TX et RX?
Autrement, opter pour un écran dont la commande utilise un nombre plus réduit de broches? En I2C ou SPI?

Concernant la communication, je serais d'avis de développer une convention de communication sommaire. Plutôt que d'attendre sans rien faire la réponse à une demande, pourquoi ne pas simplement coder la réponse, comme ça le programme émetteur sait quoi en faire? Par exemple, l'émetteur envoie T, continue à faire sa petite vie tout en surveillant s'il reçoit des données. De son coté le récepteur reçoit la commande T, fait son calcul, et réponds par exemple T25.2, ainsi l'émetteur sait à quoi correspond la donnée reçue. On peut imaginer formater les requêtes et réponses de manière à ce qu'il soit clairement établi ce qui est le début d'une requête, et ce qui en marque la fin. Par exemple en commençant chaque requête par $ ou tout autre caractère dédié, et en finissant chaque requête par un caractère EOL.
On peut également, à partir du moment où l'on établit clairement et sans ambiguïté le début et la fin de la requête, y mettre plusieurs paramètres, et ajouter par exemple un index unique pour identifier la requête. Par exemple écrire $ID234T. Et remettre l'ID dans la réponse, ainsi l'émetteur peut tracer ce qu'il a reçu ou non...

Merci pour ta réponse !

Oui je comptais bien laisser l'écran connecté à l'émetteur. Cependant, ce n'est pas un écran I2C mais un écran qui a besoin de 6 pins pour fonctionner (RS,EN,D4,D5,D6,D7). J'ai un budget assez limité mais puisque presque rien n'est connecté à l'émetteur, autre que TX et RX comme tu l'as dit, alors l'I2C ne me semble pas indispensable.

Pour la communication, si j'ai bien compris : j'envoie un caractère 'T', alors le récepteur va recevoir ce caractère et faire l'acquisition de la température ainsi que son calcul. Par la suite je ferai une sorte de:
Serial.write('$T');
Serial.write(temperature);

Ai-je bien compris ? Je viens seulement de démarrer arduino depuis ce projet donc je ne m'y connais pas dans ce domaine. Cependant, j'ai bien compris l'idée d'émettre des caractères en début de chaines pour dire d'ou provient la chaine. Par exemple toutes mes chaines qui sont des réponses du récepteur commenceront par '$', le second caractère peut préciser l'objet de la réponse comme 'T' pour température et ensuite la donnée qui nous intéresse. Pour finir on envoie un caractère de fin de réponse comme '@'

Sur le principe je comprends, mais niveau informatique je ne vois pas. Comment l'émetteur peut être à l'écoute tout le temps ? Comment va-t-il interpréter ce qu'il reçoit ?

Quelques questions subsidiaires :
Le Serial.read() prend la donnée dans le buffer mais cette donnée disparaît-elle juste après l'appel de la fonction read() ?
Les algorithmes arduino sont-ils lus de haut en bas, instructions par instructions, comme en C ? (Je suppose que oui)

J'ai aussi découvert un autre problème : lorsque je veux allumer une led vocalement, je dis ALLUME_LED et l'émetteur envoie le caractère 'A'; à la réception je fais un :

if(Serial.available()>0){
caractereRecu=Serial.read();
Serial.println(caractereRecu);

switch(caractereRecu){
case 'A':
digitalWrite(led,HIGH);
break;
}
}

Le problème est que lorsque je dis n'importe quoi, j'ai donc une erreur vu que le EasyVR n'a pas reconnu de mot connu et donc la LED s'éteint. Mais je ne vois pas pourquoi.

Merci de vos réponses.

Bonjour,

Avoir le programme de l'émetteur à l'écoute tout le temps peut se faire, avec des interruptions. Cela dit ça complexifie la chose, et je ne pense pas que ce soit nécessaire dans ton cas: si l'idée est d'accuser réception de la bonne transmission des ordres, je pense qu'il n'est pas très important que ce soit fait en une milliseconde, ou en une demi-seconde. Ca ne changera rien ni pour le bon déroulement du programme, ni pour l'expérience utilisateur.
la solution est donc assez simple: tester dans la boucle principale, comme tu sembles d'ailleurs le faire, s'il y a des données à lire ou non. Et s'il y en a, les tester.
Concernant le test des valeurs reçues, tu peux procéder comme tu le fais déjà: tester le caractère reçu, avec if() successifs, ou bien des switch/case. Par exemple, si le premier caractère est T, on s'attend à trouver une température, on pourra donc chercher une valeur.

if(Serial.available()>0){
    caractereRecu=Serial.read();
    Serial.println(caractereRecu);

    switch(caractereRecu){
        case 'A':
            digitalWrite(led,HIGH);
            break;
        case 'T':
            receivedValue = Serial.parseFloat();
            display_temperature(receivedValue);
            break;
        default:
            break;
    }
}

Voir ici une implémentation possible (je ne prétends pas détenir aucun savoir), dans la fonction _serial_parse_json(): arduino-projecteur-laser/serialIO.cpp at master · troisiemetype/arduino-projecteur-laser · GitHub
L'idée est de d'avoir de gêrer l’acquisition de données au travers de status. On commence avec un status "attente", puis on passe à un status "attente variable", puis "attente valeur", etc. Ca peut permettre de développer un suivi fin, et éventuellement une gestion des erreurs.
Un autre exemple ici, dont je me suis en partie inspiré, dans la fonction _parse_gcode_block: https://github.com/synthetos/g2/blob/edge/TinyG2/gcode_parser.cpp
Ici (pour faire simple) chaque caractère est analysé, et la fonction correspondante appelée.

Le caractère de fin peut être, tout simplement, un caractère EOL: ça tombe bien, c'est ce qu'ajoute la fonction Serial.println(). Autant l'utiliser, c'est fait pour! :wink:

Pour les diverses questions d'ordre général: Serial utilise deux buffers (tx et rx), qui sont des tableaux circulaires: ils disposent d'un pointeur de lecture et d'un pointeur d'écriture, qui sont chacun remis à zero lorsqu'ils arrivent au bout du tableau. L'utilisation de Serial.read() fait avancer le pointeur de lecture, et donc la valeur lue est en effet "perdue".
Les algorithmes sont bien lus comme en C, mais je ne connais pas les subtilités sous-jacentes.