Table des matières:

Envoyer des données numériques d'un Arduino à un autre : 16 étapes
Envoyer des données numériques d'un Arduino à un autre : 16 étapes

Vidéo: Envoyer des données numériques d'un Arduino à un autre : 16 étapes

Vidéo: Envoyer des données numériques d'un Arduino à un autre : 16 étapes
Vidéo: Sauvegarder des Données dans l'Arduino avec l'EEPROM - ARDUINO #3 2024, Juillet
Anonim
Envoyer des données numériques d'un Arduino à un autre
Envoyer des données numériques d'un Arduino à un autre

introduction

par David Palmer, CDIO Tech. à l'Université Aston.

Avez-vous déjà eu besoin d'envoyer des numéros d'un Arduino à un autre ? Ce Instructable montre comment.

Vous pouvez facilement tester son fonctionnement en tapant simplement une chaîne de chiffres à envoyer au terminal Serial Monitor, et voir les numéros revenir sur un deuxième moniteur série connecté au deuxième Arduino. Vous pouvez même utiliser une liaison Bluetooth.

Ce qu'il fait

Deux programmes Arduino (des croquis en langage Arduino) doivent être développés, l'un un programme maître pour se connecter à l'ordinateur hôte exécutant le moniteur série Arduino, l'autre pour agir en tant qu'esclave pour recevoir le message série du maître, le décoder et le renvoyer. L'esclave est éventuellement capable d'afficher les numéros avec lesquels il traite sur le moniteur série d'un deuxième IDE - juste au cas où vous voudriez l'utiliser. Cela peut aider à faire fonctionner les choses en premier lieu, et vous aider si vous décidez d'apporter des modifications aux programmes en fonction de vos propres besoins.

Équipement

  • 2 Arduino
  • 2 câbles USB
  • fils de raccordement (au besoin)
  • 1 PC/ordinateur portable chargé avec Arduino IDE (disponible en téléchargement gratuit sur le site Web Arduino.cc)

Étape 1: Configuration - Configurez d'abord votre matériel

Configuration - Configurez d'abord votre matériel
Configuration - Configurez d'abord votre matériel
Configuration - Configurez d'abord votre matériel
Configuration - Configurez d'abord votre matériel

Branchez les 2 Arduinos sur 2 ports USB de votre ordinateur.

Astuce, c'est une bonne idée de les étiqueter comme M et S (maître et esclave) afin de ne pas vous embrouiller plus tard (comme le montrent les 2 photos ici.)

Étape 2: Configuration - Configurez votre écran

Configuration - Configurez votre écran
Configuration - Configurez votre écran

La meilleure chose à faire est de configurer votre écran de sorte que vous ayez

  • l'IDE chargé avec le programme Master à gauche et
  • celui avec l'Esclave à droite.

Gardez également les moniteurs série pour Maser et Slave à gauche et à droite, comme indiqué dans la capture d'écran ici.

Étape 3: Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 1

Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 1
Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 1

Lorsque vous configurez votre Master End Serial Monitor pour envoyer deux chiffres, vous devez toujours utiliser les caractères délimiteurs de début et de fin et le caractère de séparation par virgule comme vous le voyez ici.

Vous devez maintenant connecter les 2 Arduino ensemble en série. Cela se fait avec deux fils de raccordement.

j'ai utilisé du vert et du jaune

  • Prenez le jaune en premier, cela doit se brancher sur D6 dans un Arduino et D7 dans le second
  • Ensuite l'inverse pour le fil vert, D7 sur le premier et D6 sur le second Arduino.

Alternativement, si vous avez quelque chose de disponible comme une paire de modules Bluetooth - comme les HC-05 - ceux-ci fonctionneront également pour vous donner exactement le même effet que les fils ci-dessus.

Étape 4: Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 2

Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 2
Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 2
Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 2
Configurez l'extrémité principale, puis connectez-vous ensemble - Partie 2

Nous utilisons la bibliothèque Software Serial. De plus amples informations sont disponibles avec ce lien

Vous pouvez le voir appelé à la ligne 7 de l'un ou l'autre des programmes. Il configure les broches numériques 7 et 6 en TX et RX (transmission et réception). C'est ainsi que les données sortiront de l'Arduino maître via le fil vert jusqu'à l'esclave et, lorsque le programme esclave du deuxième Arduino aura terminé son travail, reviendront via le fil jaune. Au bas de la même illustration (dans la fenêtre Serial Monitor), vous pouvez voir que les données que nous avons transmises ont maintenant contourné avec succès la boucle décrite ici et reviennent dans le PC sous la forme de la paire d'entiers bien séparés.

Étape 5: Aperçu des croquis / programmes - Structure du programme

Aperçu des sketches / programmes - Structure du programme
Aperçu des sketches / programmes - Structure du programme
Aperçu des sketches / programmes - Structure du programme
Aperçu des sketches / programmes - Structure du programme

Disposition Comme dans tous les croquis Arduino, il y a 3 parties de base:

  • Les déclarations
  • La mise en place
  • La boucle principale

Comme cela arrive souvent, nous avons fait usage ici d'une 4ème section qui est l'ajout de 'Fonctions'. Si vous n'êtes pas familiarisé avec l'utilisation des fonctions, vous pouvez rechercher des "fonctions Arduino" sur Google et vous trouverez des sites d'explications comme l'exemple dans ce lien: www.tutorialspoint.com/arduino/arduino_functions…..

Nous avons également utilisé des onglets pour séparer le programme en blocs plus gérables.

Les trois blocs que nous avons utilisés sont visibles en haut de chaque illustration des fenêtres IDE ci-dessus:

  • simpleRxTx0330Maître
  • commun
  • Remarques

Ce sont en fait des fichiers séparés dans le dossier du programme, comme vous pouvez le voir dans cette vue de l'Explorateur Windows des fichiers du programme Slave.

Il y a une très bonne raison pour laquelle nous avons fait cela.

  • Au fur et à mesure que nous élaborions le programme, nous nous sommes rendu compte que la majeure partie du programme du Maître était le même que celui de l'Esclave.
  • Nous avons fini par rassembler toutes les parties communes dans un onglet, que nous avons donc nommé "commun", puis chaque fois que nous avions débogué une partie (testée et convaincue qu'elle fonctionnait correctement), nous avons simplement copié et collé l'intégralité de cet onglet. en face de Maître à Esclave, ou vice versa.
  • Les onglets de notes sont également identiques, car le design est générique.

Aucune des fonctions n'est appelée depuis la configuration, elles sont toutes appelées depuis la boucle, nous les avons donc créées après la configuration mais avant la boucle.

Étape 6: Conception descendante

C'est une bonne idée de concevoir votre croquis en commençant par une définition de ce que vous voulez faire.

Une fois que vous avez cela, vous pouvez commencer à faire faire ces choses au croquis. Généralement, s'il y a un détail que vous ne savez pas encore faire, faites-en simplement une fonction et laissez la création de la fonction à plus tard.

Cela suit la bonne philosophie de conception, enseignée dans de nombreuses universités, appelée CDIO (si vous ne connaissez pas déjà celle-ci, vous pouvez la rechercher sur Google et trouver des sites pour l'expliquer comme: https://www.cdio.org/s.) Cela dit en gros: ne commencez pas la conception avant d'avoir compris le concept. Ne commencez pas la mise en œuvre avant d'avoir compris la conception. Ne vous attendez pas à ce qu'il fonctionne avant d'avoir compris la mise en œuvre. C d'abord, puis D, I et O. À chaque étape suivante, vous itérez (revenez en arrière dans la ou les boucles), donc une fois que vous êtes satisfait de votre boucle de conception initiale, vérifiez qu'elle respecte toujours le concept et mettez à jour le C si vous en avez besoin. Et ainsi de suite, donc même lorsque vous êtes arrivé à Opérations, retournez tout en haut, et voyez à nouveau à quoi ressemble le C maintenant, puis le D et moi, et faites et vérifiez tout Avec les croquis de programmation, cela fonctionne de la même manière si vous concevez de haut en bas.

Étape 7: Concept et conception - Partie 1

Concept et conception - Partie 1
Concept et conception - Partie 1
Concept et conception - Partie 1
Concept et conception - Partie 1

Le concept ici ressemble aux exigences générales énoncées dans l'onglet « notes ».

La conception pourrait ressembler à une première version de la boucle, qui correspond à l'onglet notes et pourrait ressembler à ce que vous voyez sur cette figure

Voyez comment j'aime commencer par CTRL-C en copiant d'abord les commentaires dans la tête de la boucle, puis commencez à remplir les blancs avec des commandes qui feront ces choses.

Cela compile en fait OK comme vous pouvez le voir en bas de l'écran sur la figure. Cela va de l'étape CDIO D à I, et au fur et à mesure que nous développons le code, c'est une bonne idée de continuer à faire le tour de cette boucle D-I.

Il est maintenant temps de passer à l'étape suivante, il y a un commentaire qui dit que nous allons: //recevoir quelque chose de l'USB matériel, puis nous allons le transmettre sur le canal série logiciel. Nous écrivons ce code pour que cela se produise - les lignes 133 à 138 montrées ici en surligneur jaune

Étape 8: Concept et conception - Partie 2

Concept et conception - Partie 2
Concept et conception - Partie 2
Concept et conception - Partie 2
Concept et conception - Partie 2

Les deux premières fonctions que nous introduisons ici sont (recv() et tran() pour effectuer la réception depuis le port matériel et la transmission vers le port logiciel - les appelant donc avec les paramètres " hw " ou " sw " affichés.

En plus d'eux, nous avons ajouté un test sur une variable globale appelée newData. Il s'agit d'un indicateur que nous définirons dans la fonction " void recv(); ". Lorsqu'un message a été reçu, cette variable est signalée de false à true. Nous faisons cela pour que nous ne transmettions un message que s'il en a été reçu (drapeau ==true) à la ligne 134. Et une fois que nous avons transmis notre message, c'est « travail terminé », donc nous remettons le drapeau à faux à la ligne 137.

Encore une fois, nous pouvons vérifier la compilation (D à I), et cette fois nous avons un message d'erreur 'non déclaré' (affiché). Cela nous dit que nous n'avons pas déclaré le recv(); fonction. Nous prévoyons de le faire plus tard, donc pour l'instant, pour nous permettre d'obtenir une compilation propre, nous devons créer une fonction factice ou un espace réservé, comme indiqué ci-dessous.

Encore une fois, nous pouvons vérifier la compilation (D à I), et cette fois nous avons un autre message d'erreur 'non déclaré' pour le tran(); fonction. Cela nécessite la création d'un talon similaire. Encore une fois, nous pouvons vérifier la compilation (D à I), et cette fois nous trouverons que cela fonctionne parfaitement; Jusqu'ici, tout va bien.

Étape 9: Terminez la boucle principale: A) Réception depuis l'USB, B) Réception depuis l'Arduino esclave

Terminez la boucle principale: A) Réception depuis l'USB, B) Réception depuis l'Arduino esclave
Terminez la boucle principale: A) Réception depuis l'USB, B) Réception depuis l'Arduino esclave
Terminez la boucle principale: A) Réception depuis l'USB, B) Réception depuis l'Arduino esclave
Terminez la boucle principale: A) Réception depuis l'USB, B) Réception depuis l'Arduino esclave

Il y a un dernier élément que nous avons ajouté pour terminer cette partie qui consiste à ajouter du code de débogage.

Il existe un autre Instructable sur les croquis de débogage auquel on peut se référer pour comprendre ce que nous avons fait ici et pourquoi. Reportez-vous à l'Instructable "Comment construire et tester des croquis Arduino jusqu'à ce qu'ils fonctionnent"

Ainsi, ces lignes de débogage [136-139 illustrées] sont ajoutées ensuite dans la boucle principale et, voilà, vous pouvez les tester à l'extrémité maître en rendant la variable de débogage true, et en compilant (I), puis si vous connectez un Arduino, vous pouvez télécharger, ouvrir le moniteur série et voir si ce qui revient dans le moniteur série est comme indiqué ici (le message "DEBUG MODE" est-il ajouté?)

Étape 10: Réception et traitement des données dans l'Arduino esclave

Réception et gestion des données dans l'Arduino esclave
Réception et gestion des données dans l'Arduino esclave
Réception et gestion des données dans l'Arduino esclave
Réception et gestion des données dans l'Arduino esclave

Réception de l'esclave Arduino

Ajoutez le code nécessaire pour le deuxième canal à la boucle principale, le récepteur série logiciel comme indiqué - lignes 149 à 155.

Pouvez-vous voir que la structure est vaguement basée sur ce que nous avons écrit ci-dessus pour le cas Master ?

Vous verrez également que nous obtenons une erreur du compilateur, une autre fonction non déclarée - cette fois parseData(); - nous devons donc créer un stub pour cela aussi, avant de pouvoir exécuter une compilation de test sans erreur.

Gestion des données dans l'Arduino esclave

Ajoutez le code de boucle principal requis pour l'Arduino s'il est configuré en tant que périphérique esclave, comme indiqué - lignes 163 à 174. Pouvez-vous voir que sa structure est très similaire à celle du premier canal ?

Et vous devriez trouver cette fois qu'il compile parfaitement.

Étape 11: écrivez la fonction de réception

Écrire la fonction de réception
Écrire la fonction de réception

La fonction Receive - void recv(char from){} - a deux tâches principales.

1 pour recevoir une chaîne de caractères du canal USB, et

2 pour en recevoir un du canal Arduino vers Arduino.

Pour le premier, nous devrons utiliser car il utilise l'UART matériel intégré de l'Arduino, et pour le second, la bibliothèque Arduino standard: le logiciel UART.

Lorsque nous commençons à ajouter du code à une fonction - pour créer une fonction qui fait quelque chose, au lieu d'un simple stub - nous devons nous rappeler de supprimer ou de commenter le stub qu'il remplace. Sinon, nous obtenons une erreur de compilation: refefintion de 'void lrec(char)'.

Essayez d'obtenir l'erreur, puis essayez l'une des méthodes suggérées ci-dessus pour vous en débarrasser.

Commencez par une fonction qui ressemble à celle que nous montrons ici des lignes 75 à 88 en jaune.

A présent, vous savez qu'en ayant du code, vous devrez essayer l'opération de compilation. Cela vous donne une erreur, comme celles que nous avons eues plus tôt, du type: nom de la fonction non déclarée dans cette portée. Nous aurons besoin au départ d'un autre stub pour nous permettre de compiler après cette erreur, alors ajoutez-en un comme avant, et assurez-vous que vous pouvez maintenant obtenir une compilation sans erreurs.

Voyons maintenant le code que nous avons écrit pour la fonction recv().

C'est assez propre, vous pouvez voir l'utilisation de la condition 'if' pour produire les deux parties de la fonction évoquée ci-dessus.

Le code à l'intérieur de la partie 'sw' et de la partie 'hw' est de la même forme, et je vais le décrire ici.

La première de la paire de lignes dans chaque cas est le début d'une boucle while. Si vous n'êtes pas familier avec while, vous pouvez le rechercher sur le site Arduino.cc/Reference pour des explications et des exemples. Ici, nous attendons "pendant" que la fonction "Serial" intégrée n'a reçu aucun caractère et parce que la variable newData a été désactivée (c'est-à-dire que la condition newData == false est vraie). Dès qu'un caractère - ou plus d'un caractère - est reçu, le while passera à la deuxième ligne de cette paire. Cela fera ensuite appel à recAstringChar(char); fonction pour gérer le caractère actuel. Cette paire de lignes alternera alors tant que (ou aussi longtemps) qu'il y aura encore des caractères à recevoir. Une fois qu'ils sont tous terminés, l'état while se termine, permettant au niveau suivant if ou else jusqu'à la fin, et à son tour autorisant le rec(char); fonction à terminer. Ainsi, un message complet a maintenant été reçu.

Étape 12: Écrire la sous-fonction Recevoir - Partie 1

Écrire la sous-fonction Recevoir - Partie 1
Écrire la sous-fonction Recevoir - Partie 1
Écrire la sous-fonction Recevoir - Partie 1
Écrire la sous-fonction Recevoir - Partie 1

Nous devons maintenant écrire la fonction appelée recAstringChar(char);. Vous voyez à partir du commentaire de la ligne 50 ici en haut, que son travail consiste à mettre à jour deux tampons avec des copies du message série entrant. [Il s'est avéré que pendant que j'essayais de faire fonctionner tout cela, une chose que j'ai apprise était que j'avais besoin de deux tampons différents - ou du moins c'était le moyen le plus simple de contourner certains problèmes, donc cela a évolué en un besoin de 2 tampons, donc Je viens de les faire.] J'ai appelé un tampon: receiveData, et l'autre: receiveChars.

Les buffers sont des variables globales, ils sont donc déclarés au niveau du module, voir lignes 9 et 10 de l'onglet commun. Il y a d'autres variables déclarées à l'intérieur de cette fonction qui ont donc une portée locale - montrée aux lignes 51-54 ici. Ce n'est pas l'endroit pour expliquer les différences entre les globals et les locaux, mais il y a plus d'informations à ce sujet dans https://www.arduino.cc/glossary/en/ sous Local et Global.

Vous pouvez également tout savoir sur les types de données et les modificateurs de type: static, boolean, byte, const, char dans https://www.arduino.cc/reference/en/#variables, montré ici.

Le flux de programme principal dans cette fonction est contrôlé par le if à la ligne 56 ici, et son else correspondant à la ligne 74. Cela traite de deux scénarios

a) [à partir de la ligne 74] lorsque le message reçu commence. Cela se produit lorsque le startMarker est repéré - cela a été défini comme le caractère ' < ', c'est pourquoi chaque fois que nous testons l'esquisse, nous commençons toujours notre chaîne par ce caractère. Si nous ne le faisons pas, rien ne sera traité comme étant reçu, tout sera ignoré comme si nous tapions des bêtises à l'invite du clavier « Serial Monitor ».

b) [lignes 56 à 73] qui reçoit tous les autres caractères, quels qu'ils soient, mais ils ne traitent les caractères qu'après un début valide (un '>' a été reçu comme en a) ci-dessus.)

Dans ces lignes (de 74 à 78) nous mettons ce reçu < dans l'un des tampons (receivedData[0]) mais pas dans l'autre. Nous ajustons le pointeur de tampon (variable: char ndx) pour pointer vers la prochaine position de tampon de réserve (receivedData[1]) en utilisant la commande post-incrémentation (++) dans la ligne ndx++;, et nous définissons l'indicateur en cours sur true.

Le déroulement du programme dans cette partie de la fonction est contrôlé par le if à la ligne 57 ici, et son else correspondant à la ligne 65. Cela traite de deux scénarios

a) [à partir de la ligne 65] lorsque le message reçu est terminé. Cela se produit lorsque le endMarker est repéré - défini comme >, c'est pourquoi chaque fois que nous testons notre esquisse, nous terminons toujours notre chaîne par ce caractère. L'une des choses qui se passe lorsque le caractère de fin est reçu est que l'indicateur global (techniquement variable) newData est défini sur vrai juste au moment où la fonction se termine, de sorte que la fonction qui a appelé notre sous-fonction (la fonction appelante: recv(char);) peut « savoir » que de nouvelles données valides ont été reçues complètes.

b) [lignes 57 à 64] qui reçoit tous les autres caractères, quels qu'ils soient. Il les range simplement soigneusement en rangées dans les deux tampons.

Étape 13: Écrire la sous-fonction Recevoir - Partie 2

Écrire la sous-fonction Recevoir - Partie 2
Écrire la sous-fonction Recevoir - Partie 2
Écrire la sous-fonction Recevoir - Partie 2
Écrire la sous-fonction Recevoir - Partie 2

Il peut être utile de donner un exemple de ce à quoi ressemblent les 2 tampons lorsqu'ils ont été remplis. Si nous devions saisir enter, les tampons auraient les caractères affichés:

Alors maintenant, vous pouvez voir que nous avons un tampon qui contient exactement les mêmes caractères que ceux que nous avons saisis pour la première fois, et un tampon qui n'a que les deux valeurs et une virgule de séparation. Maintenant que nous avons un code qui peut recevoir les caractères que nous tapons sur le clavier Serial Monitor, nous pouvons passer de la phase CDIO I à O, en tapant quelques chaînes et en voyant ce qui se passe. Téléchargez le code sur le maître Arduino, ouvrez le moniteur série et essayez de saisir quelque chose de valide, comme entrer. Recevez-vous un écho sur l'écran Serial Monitor comme celui illustré ici ?

Étape 14: écrivez les fonctions de transmission et d'analyse

Écrire les fonctions de transmission et d'analyse
Écrire les fonctions de transmission et d'analyse
Écrire les fonctions de transmission et d'analyse
Écrire les fonctions de transmission et d'analyse

D'abord pour la transmission

Alors maintenant que nous avons reçu une chaîne, nous pouvons écrire la fonction de transmission: tran(char); pour remplacer son talon. Cela nous permettra d'envoyer une chaîne du maître à l'esclave Arduino, Assurez-vous donc que les deux appareils sont branchés et connectés ensemble pour tester cette nouvelle fonctionnalité.

Entrez cette fonction comme indiqué ici dans les lignes 117 à 133. Comme vous le reconnaîtrez, elle comporte deux parties, une pour transmettre au canal USB (hardware UART) et une pour transmettre à l'autre Arduino (logiciel UART.) Cela devrait compiler une erreur -gratuit, et vous pouvez immédiatement télécharger le croquis et voir ce qui se passe. Cette fois, j'enverrai. Obtenez-vous le résultat affiché?

La capture d'écran est intéressante car la chaîne reçue… devrait avoir l'air correcte comme avant, et la chaîne transmise… devrait maintenant avoir l'air correcte. Notez cependant que la conversion Integer n'a pas fonctionné. Il y a encore un peu de code à ajouter pour que cela fonctionne.

Étape 15: écrivez les fonctions de transmission et d'analyse

Écrire les fonctions de transmission et d'analyse
Écrire les fonctions de transmission et d'analyse
Écrire les fonctions de transmission et d'analyse
Écrire les fonctions de transmission et d'analyse

Ensuite pour le Parse

Il s'agit d'un morceau de code qui analyse la chaîne reçue pour extraire les chaînes partielles numériques et les convertit en valeurs entières. C'est le vide parseData(); fonction de la boucle principale

Remplacez le stub d'analyse par le code affiché aux lignes 98 à 113. Téléchargez-le et voyons si le problème que nous avions avec les 2 valeurs entières est maintenant résolu. Essayons.

Oui, cela fonctionne, comme indiqué, les nombres entiers trouvés sont 49 et 98.

Étape 16: Finale

Final!
Final!

Ces données ont fait le tour de la boucle du PC via le maître via l'esclave et retour via le maître à nouveau vers le PC. Avec la version finale de Common téléchargée aux extrémités maître et esclave, et avec le mode de débogage désactivé maintenant, nous pouvons voir les données correctement reçues aux deux extrémités, comme indiqué ici.

Conseillé: