Un moniteur série (UART) matériel avec Arduino

![]() |
Schéma d'une communication UART |
Dans le logiciel Arduino IDE, le "moniteur série" permet de savoir ce qu'il se passe sur la liaison série matérielle de l'Arduino. Dans le cas de l'Arduino UNO par exemple, la liaison série matérielle se trouve sur les entrées/sorties 0 (broche de réception) et 1 (broche de transmission), et elle est utilisée notamment pour l'envoie d'un programme au microcontrôleur.
Imaginons que vous êtes en train de réaliser un système électronique, mettant en jeu un microcontrôleur et une puce GSM, ou encore GPS (en effet les modules GSM et GPS utilisés dans le monde Arduino communiquent pour la plupart via liaison série UART). Si vous désirer "écouter" ce qu'il se dit sur cette liaison, il va vous falloir soit programmer le microcontrôleur pour qu'il rapporte via un autre moyen ce qu'il se dit sur la liaison série, soit vous utilisez un autre microcontrôleur ou équipement qui va "espionner" la communication.
Voilà le projet que je veux partager avec vous dans cet article : un moniteur série matériel. Il permet de visualiser facilement et rapidement les données échangées via une liaison série sans la perturber. Il est bien sur possible de régler la vitesse de la communication (en bauds) et on peut distinguer la provenance de chacun des messages (pour savoir de quel côté de la liaison série viennent-il).
Alors comment écouter sur deux lignes séries (une liaison = deux lignes, TX et RX) en même temps à l'aide d'un Arduino ? L'Arduino UNO ne possèdent qu'une seule liaison série matérielle, donc une seule broche de réception (nommée RX). On pourrait utiliser un port série logiciel (software serial) mais j'ai préféré employer la solution de facilité et simplement utiliser un microcontrôleur disposant de deux ports série matériels : le ATMega644.
Ce microcontrôleur présente d’autres intérêts par rapport au traditionnel ATMega328 équipant l'Arduino UNO :
ATMega328 | ATMega644 | |
Flash [ko] | 32 | 64 |
RAM [ko] | 32 | 64 |
ROM [ko] | 1 | 2 |
IO | 23 | 32 |
ADC | 8 | 8 |
Les trois types de mémoire ont le double de capacité et il dispose aussi d'un plus grand nombre d'entrée/sortie pour un prix "seulement" deux fois supérieur à l'ATMega328.
Ce microcontrôleur existe dans un boitier DIP facilement utilisable avec une breadboard par exemple mais j'ai préféré faire fabriquer une petite carte pour l'accueillir.
![]() |
Photo de la carte pour l'ATMEGA644 nue |
Cette simple carte accueille l'ATMEGA644 (ou l'ATMEGA1284, ces deux sont compatibles) ainsi qu'une alimentation, un circuit de Reset et un cristal à 16MHz.
![]() |
Photo de la carte pour l'ATMEGA644 assemblée |
![]() |
Photo de l'écran d'affichage |
![]() |
Photo du système |
![]() |
Schéma du double AOP LM358 configuré en deux montages suiveurs |
Il est sans doute largement possible d'améliorer le montage par exemple avec une carte SD pour enregistrer les données de communication etc... Mais ce petit montage m’a suffi pour faire fonctionner le module GSM que je souhaitais.
Voici le programme Arduino utilisé :
#include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" #define TFT_DC 3 #define TFT_CS 4 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); char inchar1; //caractère entrant char inchar2; String message1 = ""; //message entier String message2 = ""; const byte led1 = 0; const byte led2 = 2; const byte act1 = A5; const byte act2 = A7; const byte bp = A2; unsigned int ixe = 11; //position x d'écriture #include <EEPROM.h> const byte addrEE = 52; //on enregistre la vitesse de la communication dans la case 52 byte selbaudrate = 2; //on sélectionne 9600 bauds au début unsigned long baudrate = 0; void setup() { pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(act1, INPUT_PULLUP); pinMode(act2, INPUT_PULLUP); pinMode(bp, INPUT_PULLUP); fctchangebaud(); //on initialise la liaison série et l'interface graphique } void loop() { if (digitalRead(bp) == LOW) { delay(5); //anti-rebond if (selbaudrate == 7) selbaudrate = 0; else selbaudrate++; EEPROM.write(addrEE, selbaudrate); fctchangebaud(); } if(digitalRead(act1) == LOW) { while (Serial.available() && message1.length() < 53) { inchar1 = Serial.read(); message1 += inchar1; delay(10); //le temps que le prochain caractère arrive, IMPORTANT ! } message1.trim(); if (message1 != "") { digitalWrite(led1, LOW); digitalWrite(led2, HIGH); if (ixe > 230) { ixe = 11; tft.fillScreen(ILI9341_BLACK); tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE); tft.print("SERIAL MONITOR - "); tft.print(baudrate); tft.print(" bauds"); tft.drawLine(0, 9, 320, 9, ILI9341_WHITE); } tft.setCursor(1, ixe); tft.setTextColor(ILI9341_GREEN); tft.print(message1); ixe = ixe + 10; } } else while(Serial.available()) Serial.read(); //on vide quand même le buffer de l'autre serial if(digitalRead(act2) == LOW) { while (Serial1.available() && message2.length() < 53) { inchar2 = Serial1.read(); message2 += inchar2; delay(10); //le temps que le prochain caractère arrive, IMPORTANT ! } message2.trim(); if (message2 != "") { digitalWrite(led2, LOW); digitalWrite(led1, HIGH); if (ixe > 230) { ixe = 11; tft.fillScreen(ILI9341_BLACK); tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE); tft.print("SERIAL MONITOR - "); tft.print(baudrate); tft.print(" bauds"); tft.drawLine(0, 9, 320, 9, ILI9341_WHITE); } tft.setCursor(1, ixe); tft.setTextColor(ILI9341_RED); tft.print(message2); ixe = ixe + 10; } } else while(Serial1.available()) Serial1.read(); //on vide quand même le buffer de l'autre serial message1 = ""; //Vide la variable "message" message2 = ""; } void fctchangebaud() { Serial.end(); Serial1.end(); switch (selbaudrate) { case 0: baudrate = 2400; break; case 1: baudrate = 4800; break; case 2: baudrate = 9600; break; case 3: baudrate = 19200; break; case 4: baudrate = 28800; break; case 5: baudrate = 38400; break; case 6: baudrate = 57600; break; case 7: baudrate = 115200; break; } Serial.begin(baudrate); Serial1.begin(baudrate); tft.begin(); tft.setRotation(3); tft.fillScreen(ILI9341_BLACK); tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1); tft.print("SERIAL MONITOR - "); tft.print(baudrate); tft.print(" bauds"); tft.drawLine(0, 9, 320, 9, ILI9341_WHITE); ixe = 11; }
Et voici le schéma électrique complet du système (cliquez pour agrandir) :
![]() |
Schéma éléctrique du moniteur série matériel |
A bientôt !
Liens externes :
Bibliothèque Sanguino : https://github.com/Lauszus/Sanguino
Bibliothèque ILI9341 : https://github.com/adafruit/Adafruit_ILI9341
ATMega644 : http://www.atmel.com/devices/ATMEGA644.aspx
0 commentaires:
Enregistrer un commentaire