Dans les exemples suivants, nous verrons comment transmettre des informations d’un Arduino vers un autre en utilisant le protocole série (UART / RS-232 / COM PORT).
Le protocole série utilise deux broches pour l’échange des données; une broche pour la réception (RX) et une broche pour la transmission (TX)
Dans le cas d’un Arduino Uno ces broches sont D0 (RX0) et D1 (TX0).
L’Arduino Uno ne possède qu’un seul port série.
De plus, si nous utilisons la console série pour y afficher des messages alors le port série du UNO ne sera pas disponible pour le transfert d’information vers d’autres appareils.
Ce n’est pas le cas pour tous les Arduino.
Par exemple, l’Arduino Mega propose 4 ports séries (UART0-UART3).
Il est possible d’utiliser des broches digitales standards pour reproduire le comportement et les fonctions d’un port UART en utilisant la librairie SotfwareSerial. Cette librairie est disponible par défaut dans l’environnement de Arduino IDE, c-a-d, qu’il n’est pas nécessaire de l’installer.
Si nous désirons relier deux appareils ensemble qui utiliseront leur port UART pour la communication, il faut relier la broche RX du premier sur la broche TX du deuxième. Puis la broche TX du premier sur la broche RX du deuxième.
Avec l’utilisation du Grove Hat, il sera possible d’inverser les broches RX/TX dans les paramètres de configurations du port UART logiciel.
Par exemple, deux Arduino UNO reliés par un câble sur le port D4 du Hat Grove pourront être configurés de la façon suivante:
SoftwareSerial portSerieTransmetteur(4, 5); // RX, TX SoftwareSerial portSerieRecepteur(5, 4); // RX, TX
Pour le prochain laboratoire, il faut relier un Arduino Mega et un Arduino UNO en plaçant un câble entre les deux connecteurs D6.
/* Code du transmetteur - sur le MEGA Note: Relier deux Arduino via le port D6 */ #include <SoftwareSerial.h> #include "rgb_lcd.h" #include "Streaming.h" #define UART_RX 6 #define UART_TX 7 #define UART_VITESSE 9600 #define MAX_NB_ALEATOIRE 99 #define UNE_SECONDE 1000 #define LCD_DEUXIEME_LIGNE 1 #define LCD_NB_LIGNE 2 #define LCD_NB_COL 16 rgb_lcd lcd; SoftwareSerial portSerieTransmetteur(UART_RX, UART_TX); // RX, TX void setup() { Serial.begin(UART_VITESSE); // port natif utilisé pour le débogage Serial.println("Démarrage du transmetteur..."); lcd.begin(LCD_NB_COL,LCD_NB_LIGNE); lcd.print("Transmetteur"); // Initialiser le port serie 'SoftwareSerial' portSerieTransmetteur.begin(UART_VITESSE); } // setup() void loop() { // Transmettre un code à chaque seconde // générer un nombre entre 0 et MAX_NB_ALEATOIRE - 1 byte unCode = random(MAX_NB_ALEATOIRE); portSerieTransmetteur.write(unCode); Serial << "Envoi du code suivant: " << unCode << endl; lcd.setCursor(0, LCD_DEUXIEME_LIGNE); lcd << "Envoi de: " << unCode; delay(UNE_SECONDE); } // loop()
/* Code du récepteur - sur le UNO Note: Relier deux Arduino via le port D6 */ #include <SoftwareSerial.h> #include "rgb_lcd.h" #include "Streaming.h" #define UART_RX 6 #define UART_TX 7 #define UART_VITESSE 9600 #define UNE_SECONDE 1000 #define LCD_DEUXIEME_LIGNE 1 #define LCD_NB_LIGNE 2 #define LCD_NB_COL 16 rgb_lcd lcd; // Le RX du UNO doit être connecté au TX du MEGA et TX -> RX // Il faut donc inverser les signaux: SoftwareSerial portSerieRecepteur(UART_TX, UART_RX); // RX, TX void setup() { Serial.begin(UART_VITESSE); Serial.println("Démarrage du récepteur..."); lcd.begin(LCD_NB_COL,LCD_NB_LIGNE); lcd.print("Recepteur"); // Initialiser le port serie 'SoftwareSerial' portSerieRecepteur.begin(UART_VITESSE); } void loop() { byte unCode; if (portSerieRecepteur.available()) { unCode = portSerieRecepteur.read(); // afficher la valeur du byte reçu Serial << "Code recu = " << unCode << endl;; lcd.setCursor(0, LCD_DEUXIEME_LIGNE); lcd << "Code recu: " << unCode; } // si byte disponible sur le UART }
NOTE IMPORTANTE:
L’Arduino MEGA ne permet pas d’implémenter le UART, via la librairie SoftwareSerial, en mode réception sur toutes ses broches. Il faut se limiter aux broches suivantes:
Par contre, en mode transmission, il n’y a pas cette contrainte.
Il n’y pas non plus de contraintes si nous utilisons les ports natifs UART du MEGA.
De plus, sur certains Arduino, la vitesse MAXIMUM de transmission est limitée à 57600bps.
Documentation de la classe :: SoftwareSerial
Il faut modifier les vitesses de transmission/réception de l’exemple précédent à 115 200 bauds et tester le système.
Question: Est-il toujours fonctionnel?
Il faut relier les deux Arduino par leur port natif UART; 1) Mega sur Serial3 et 2) UNO sur Serial.
Note: Il ne faut plus afficher dans la console série du projet UNO, seulement sur l’écran LCD.
Question: Est-ce que le système est toujours fonctionnel? Si non, il faut expliquer pourquoi.
// Exemple d'initialisation du UART no 3 sur le MEGA: Serial3.begin(9600);
/* Code du transmetteur Version chaine de caractères Note: Relier deux Arduino via le port D6 */ #include <SoftwareSerial.h> #include "rgb_lcd.h" #include "Streaming.h" rgb_lcd lcd; const String messages[] = { "Haddock", "Tournesol", "Dupond et Dupont", "Tintin", "Milou", "Bachi-bouzouk", "Boit-sans-soif", "Brontosaure", "Calembredaine", "Cataplasme", "Clysopompe", "Cornemuse", "Cornichon", "Cyclotron" }; // Le RX du premier doit être connecté au TX du deuxième et TX -> RX #define UART_RX 6 #define UART_TX 7 #define UART_VITESSE 9600 #define MAX_NB_ALEATOIRE 14 #define UNE_SECONDE 1000 #define LCD_DEUXIEME_LIGNE 1 #define LCD_NB_LIGNE 2 #define LCD_NB_COL 16 SoftwareSerial portSerieTransmetteur(UART_RX, UART_TX); // RX, TX void setup() { Serial.begin(UART_VITESSE); // port natif utilisé pour le débogage Serial.println("Démarrage du transmetteur..."); lcd.begin(LCD_NB_COL,LCD_NB_LIGNE); lcd.print("Transmetteur"); // Initialiser le port serie 'SoftwareSerial' portSerieTransmetteur.begin(UART_VITESSE); } // setup() void loop() { // Envoyer un message aléatoire à toutes les secondes: byte unCode = random(MAX_NB_ALEATOIRE); portSerieTransmetteur.print(messages[unCode]); Serial << "Envoi du message suivant: " << messages[unCode] << endl; lcd.setCursor(0, LCD_DEUXIEME_LIGNE); lcd << "Envoi du msg: " << unCode << " "; delay(UNE_SECONDE * 2); }
/* Code du récepteur Version chaine de caractères Note: Relier deux Arduino via le port D6 */ #include <SoftwareSerial.h> #include "rgb_lcd.h" #include "Streaming.h" rgb_lcd lcd; // Le RX du UNO doit être connecté au TX du MEGA et TX -> RX // Il faut donc inverser les signaux: #define UART_RX 6 #define UART_TX 7 #define UART_VITESSE 9600 #define UNE_SECONDE 1000 #define LCD_DEUXIEME_LIGNE 1 #define LCD_NB_LIGNE 2 #define LCD_NB_COL 16 SoftwareSerial portSerieRecepteur(UART_TX, UART_RX); // RX, TX void setup() { Serial.begin(UART_VITESSE); Serial.println("Démarrage du récepteur..."); lcd.begin(LCD_NB_COL,LCD_NB_LIGNE); lcd.print("Recepteur"); // Initialiser le port serie 'SoftwareSerial' portSerieRecepteur.begin(UART_VITESSE); delay(UNE_SECONDE); } void loop() { String unMessage; static unsigned long compteurMessage = 0; if (portSerieRecepteur.available()) { unMessage = portSerieRecepteur.readString(); // afficher la valeur du byte reçu Serial << "Message recu = " << unMessage << endl; lcd.setCursor(0,0); lcd << "MSG RECUS: " << ++compteurMessage; effacerLigne2LCD(); lcd << unMessage; } // si données disponibles sur le UART } void effacerLigne2LCD(){ lcd.setCursor(0, LCD_DEUXIEME_LIGNE); for (int i = 0 ; i < LCD_NB_COL; i++){ lcd << " "; } lcd.setCursor(0, LCD_DEUXIEME_LIGNE); }
/* Fichier: code.alarme.h Auteur: Alain Boudreault Date: 2021.11.21 --------------------------------------------------------- Description: Définir un type enum à utiliser pour les différents états du système d'alarme. Note: Inclure ce fichier dans le dossier de votre projet. Puis, programmer la syntaxe suivante pour utiliser ce type: codesAlarme code; ... code = evenement_systeme_enligne; --------------------------------------------------------- M-A-J: 2022.11.11 A.B. - Ajout de 'evenement_nb_codes' --------------------------------------------------------- */ // S'assurer que ce fichier ne sera inclus qu'une seule fois lors de la compilation du projet #ifndef LES_CODES_ERREUR_H #define LES_CODES_ERREUR_H enum codesAlarme { evenement_temperature_depassee, evenement_dectection_mouvement, evenement_code_invalide, evenement_code_valide, evenement_alarme_active, evenement_alarme_inactive, evenement_systeme_enligne, evenement_nb_codes }; #endif // LES_CODES_ERREUR_H_ _
/* Simulation d'un système d'alarme UNO, qui envoie des événements à une centrale de controle (MEGA) via le protocole UART. Le UNO est connecté par son port D8 au port UART2 du MEGA. Étant donné que le UNO n'a qu'un seul port UART et qu'il est utilisé pour déboger l'application, la librairie 'SoftwareSerial' est utilisée pour simuler un port UART à partir d'une GPIO. */ #include <SoftwareSerial.h> #include "code.alarme.h" #include "rgb_lcd.h" #include "Streaming.h" rgb_lcd lcd; // Le RX du UNO doit être connecté au TX du MEGA et TX -> RX // Il faut donc inverser les signaux: SoftwareSerial mySerial(5, 4); // RX, TX codesAlarme unCodeAlarme = evenement_systeme_enligne; void setup() { Serial.begin(9600); while (!Serial) { ; // S'assurer que le port serie est pret. Ceci n'est pas requis pour un SoftwareSerial. } Serial.println("Demarrage du systeme d'alarme..."); lcd.begin(16,2); lcd.print("Master"); // Initialiser le port serie 'SoftwareSerial' mySerial.begin(9600); // Envoyer l'état du système d'alarme à la centrale (Mega) mySerial.write(unCodeAlarme); // Attention, pour envoyer un seul octet (Byte), il faut utiliser la méthode write et non pas print. delay(1000); } void loop() { unCodeAlarme = evenement_dectection_mouvement; // Envoyer un code de détection du mouvement à toutes les secondes: byte i; i = random(evenement_nb_codes); mySerial.write(i); Serial << "Envoi du code suivant: " << i << endl; delay(1000); }
/* Simulation d'un système d'alarme UNO, qui envoie des événements à une centrale de controle (MEGA) via le protocole UART. Le UNO est connecté par son port D8 au port UART2 du MEGA. Étant donné que le UNO n'a qu'un seul port UART et qu'il est utilisé pour déboger l'application, la librairie 'SoftwareSerial' est utilisée pour simuler un port UART à partir d'une GPIO. */ #include <SoftwareSerial.h> #include "code.alarme.h" #include "rgb_lcd.h" #include "Streaming.h" rgb_lcd lcd; // Le RX du UNO doit être connecté au TX du MEGA et TX -> RX // Il faut donc inverser les signaux: SoftwareSerial mySerial(5, 6); // RX, TX codesAlarme unCodeAlarme = evenement_systeme_enligne; void setup() { Serial.begin(9600); while (!Serial) { ; // S'assurer que le port serie est pret. Ceci n'est pas requis pour un SoftwareSerial. } Serial.println("Demarrage du systeme d'alarme..."); lcd.begin(16,2); lcd.print("Slave ready"); // Initialiser le port serie 'SoftwareSerial' mySerial.begin(9600); // Envoyer l'état du système d'alarme à la centrale (Mega) //mySerial.write(unCodeAlarme); // Attention, pour envoyer un seul octet (Byte), il faut utiliser la méthode write et non pas print. delay(1000); } void loop() { codesAlarme code; if (mySerial.available()) { code = mySerial.read(); // afficher la valeur du byte reçu Serial.print("\nCode = "); Serial.print(code, DEC); Serial.println(""); lcd.setCursor(0, 1); lcd << "Code recu: " << code; // Tester les événements du système d'alarme if (code == evenement_systeme_enligne) Serial.print("Systeme client en ligne !"); if (code == evenement_dectection_mouvement) Serial.print("DANGER: Il y a intrusion ...."); } }
Mettre en place un système de deux Arduino, reliés ensemble VIA le protocole UART qui s’échangent des données.
Il faut relier, correctement, deux Arduino via le protocole UART.
Chaque Arduino possède un écran LCD.
Le premier Arduino envoi vers le deuxième, un nombre aléatoire compris entre 0 et NB_CITATIONS. Le nombre aléatoire est affiché sur la ligne 1 du LCD du premier Arduino en respectant la forme suivante:
1: Citation no: nn
2:
Le deuxième Arduino reçoit le nombre aléatoire et l’utilise pour obtenir une citation dans le tableau des citations. Le nombre aléatoire est affiché sur la ligne no 2 du deuxième Arduino.
1: Arduino no 2
2: Envoi de: nn
La citation obtenue est envoyée vers le premier Arduino et affichée sur la ligne no 2 de ce dernier.
1: Citation no: nn
2: Texte de la citation
Voici le tableau des citations:
const String citations[] = { "Bachi-bouzouk", "Boit-sans-soif", "Brontosaure", "Calembredaine", "Catachrese", "Coupe-jarret", "Doryphore", "Dynamiteur", "Empoisonneur", "Hurluberlu", "Cataplasme", "Clysopompe", "Cornemuse", "Cornichon", "Cyclotron" };