Aller au contenu principal

Périphériques série et Arduino

Les fonctions intégrées Serial* communiquent avec tout ce qui apparaît comme un port COM : un Arduino, un ESP32 ou un Raspberry Pi Pico en USB, un adaptateur USB-série, un récepteur GPS, un lecteur de codes-barres en mode série, une imprimante de tickets ou d'étiquettes, une imprimante 3D ou une commande numérique qui accepte du G-code, un instrument de laboratoire, ou un boîtier de boutons, un pavé de macros, un bouton rotatif ou un contrôleur de LED fait maison. Le périphérique envoie et reçoit des lignes de texte ; vos scripts transforment ces lignes en n'importe quelle autre chose que sait faire Input.Observer.

Quelques idées :

  • Un boîtier de boutons ou un pavé de macros. Un Arduino lit ses boutons et affiche B1, B2, ... Un moniteur série transforme chaque ligne en raccourci, en touche multimédia ou en commande de fenêtre.
  • Un bouton rotatif de volume ou de défilement. Un potentiomètre ou un encodeur rotatif envoie sa position ; le moniteur règle le volume ou fait défiler.
  • Des voyants d'état. Un geste ou un raccourci clavier envoie LED 255 0 0 à une carte qui pilote un ruban de LED, pour qu'une lumière indique que l'enregistrement est en cours ou que la compilation a échoué.
  • Des capteurs. Un minuteur demande à une carte une température ou un niveau de luminosité et l'affiche, l'écrit dans un fichier journal ou baisse la luminosité de l'écran.
  • Des lecteurs et scanners. Chaque code-barres ou étiquette RFID envoyé par le lecteur devient du texte saisi, une recherche ou une consultation dans un fichier.
  • Des machines. Envoyez des lignes de G-code à une imprimante ou à un traceur, un SerialWriteTextLine par commande.

Trouver le port​

Windows donne à chaque périphérique un nom comme COM3. Le Gestionnaire de périphériques le liste sous Ports (COM et LPT) ; l'IDE Arduino l'affiche dans son menu de cartes. Un script peut aussi les lister :

n = SerialEnumeratePorts();
if (n == 0) UtilityPrint("No COM ports. Is the board plugged in?");
for (i = 0; i < n; i = i + 1) {
UtilityPrint(SerialGetEnumeratedPortAt(i));
}

La liste est triée par numéro : COM3 vient donc avant COM10. Le numéro peut changer lorsque le périphérique est branché sur un autre port USB.

Vitesse, format de trame et fins de ligne​

  • La vitesse (baudRate) doit correspondre à celle du périphérique : le nombre indiqué dans le Serial.begin(...) d'un croquis Arduino, généralement 9600 ou 115200.
  • Le format de trame est presque toujours 8 bits de données, sans parité, un bit d'arrêt : 8, SerialParity.None, SerialStopBits.One. Écrivez les constantes : le nombre 1 seul comme argument de bits d'arrêt signifie un bit et demi d'arrêt.
  • Fins de ligne. Une ligne reçue se termine au terminator que vous indiquez, qui est retiré de la ligne. Un texte vide signifie CR LF, ce qu'envoie le Serial.println d'Arduino. Pour un périphérique qui termine ses lignes par LF seul, utilisez "\n" ; pour CR seul, utilisez "\r". SerialWriteTextLine termine ce qu'il envoie par le même terminateur, ou par CR LF lorsque l'appel ouvre lui-même le port. Avec CR LF, un croquis Arduino qui lit avec Serial.readStringUntil('\n') reçoit la ligne avec un CR final, que trim() retire ; avec "\n", il n'y a pas de CR à retirer.
  • Signaux. L'ouverture d'un port active ses signaux DTR et RTS, comme le fait l'IDE Arduino. Cela redémarre la plupart des cartes Arduino Uno et Nano, ainsi que les autres cartes dotées du même circuit de réinitialisation.

Trois façons de communiquer avec un périphérique​

  • Une question, une réponse. SerialWriteTextLine et SerialGetTextLine sur un port qui n'est pas ouvert l'ouvrent au baudRate de l'appel, 8-N-1, le temps de cet appel. L'argument baudRate est ignoré lorsque le port est déjà ouvert. Convient à un périphérique qui ne redémarre pas à l'ouverture de son port. Voir Poser une question à un périphérique série.

  • Un port maintenu ouvert. SerialOpenPort ouvre le port avec vos paramètres jusqu'à SerialClosePort, en recueillant chaque ligne envoyée par le périphérique pour que SerialGetTextLine la lise. La plupart des cartes Arduino Uno et Nano redémarrent chaque fois que leur port s'ouvre : ouvrez donc le port une seule fois, dans l'événement global Configuration chargée, et laissez les gestes et les raccourcis clavier y écrire. SerialOpenPort renvoie false pour un port absent, débranché ou ouvert dans un autre programme ; pour un port qu'Input.Observer a déjà ouvert, ou qu'un moniteur détient, il arrête l'action avec une erreur.

    // Load global event: open the port once, at the sketch's speed. An Uno or Nano
    // restarts every time its port opens, so a port opened per command would lose
    // the command while the board boots.
    if (!SerialOpenPort("COM4", 115200, SerialParity.None, 8, SerialStopBits.One, "")) {
    UtilityPrint("COM4 isn't available: unplugged, or open in the Arduino IDE's Serial Monitor?");
    }

    // Any gesture or hotkey: send a command line and read the board's reply.
    // (The sketch reads a line with Serial.readStringUntil('\n') and answers OK.)
    if (SerialWriteTextLine("COM4", "LED 255 0 0", 115200)) {
    reply = SerialGetTextLine("COM4", 1, 115200);
    if (reply != "OK") UtilityPrint(StringFormat("Board said: {0}", reply, ""));
    }
  • Un moniteur. SerialMonitorCreate exécute un script pour chaque ligne envoyée par le périphérique, en arrière-plan, jusqu'à SerialMonitorDelete. La ligne est ContextGetSerialTextLine(). Voir Associer les boutons d'un périphérique série à des touches multimédias et :

    // Arduino side: a potentiometer on A0, one reading per line.
    // void setup() { Serial.begin(115200); }
    // void loop() { Serial.println(analogRead(A0)); delay(50); }
    // Empty text as the terminator means CR LF, which Serial.println sends.
    SerialMonitorCreate("knob", "COM4", 115200, SerialParity.None, 8, SerialStopBits.One, "",
    "line = ContextGetSerialTextLine(); if (StringIsNumber(line, true)) MultimediaSetVolume(AudioEndpoint.Playback, StringToNumber(line, true) / 1023.0);");
remarque

Ce qu'il faut savoir sur les moniteurs.

  • Les lignes sont traitées une à la fois, dans leur ordre d'arrivée : le script de la ligne suivante démarre lorsque celui de la ligne précédente est terminé. Jusqu'à 256 lignes attendent ; au-delà, les plus anciennes sont abandonnées.
  • L'arrêt de toutes les actions arrête le script en cours pour une ligne et abandonne les lignes en attente. Le moniteur lui-même continue de fonctionner. Le Raccourci clavier Arrêter toutes les actions va plus loin : il supprime chaque moniteur et ferme son port.
  • N'importe quel script, y compris celui du moniteur, peut envoyer des données à un port surveillé avec SerialWriteTextLine : un moniteur peut donc répondre à son périphérique. SerialGetTextLine ne peut pas lire un port surveillé : chaque ligne va au moniteur.
  • Chaque nom de moniteur appartient à un seul port. SerialMonitorCreate avec le nom du moniteur de ce port remplace ce moniteur. Il arrête l'action avec une erreur lorsque le nom surveille déjà un autre port, lorsque le port est ouvert avec SerialOpenPort, ou lorsqu'un autre moniteur détient le port. Un port absent, débranché ou ouvert dans un autre programme donne false.
  • Débrancher le périphérique met fin au moniteur et inscrit une ligne dans l'onglet Système de la console. Rien ne relance le moniteur quand le périphérique revient. Exécutez de nouveau le SerialMonitorCreate (depuis un raccourci clavier, ou depuis l'événement Configuration chargée au prochain démarrage).
attention

Un seul programme à la fois peut ouvrir un port COM. Tant que le Moniteur série ou le Traceur série de l'IDE Arduino est ouvert, Input.Observer ne peut pas ouvrir le port, et tant qu'Input.Observer le maintient ouvert, l'IDE ne peut pas téléverser de croquis. Fermez le port (SerialClosePort ou SerialMonitorDelete) avant le téléversement.