HOWTO · Arduino

Arduino attend l'entrée

On peut configurer l'Arduino pour attendre l'entrée en utilisant la fonction Serial.available() et la fonction digitalRead().

Sur cette page

Choisissez la source d’entrée en fonction du signal : utilisez l’entrée série pour recevoir des octets envoyés par un ordinateur ou un autre appareil, digitalRead() pour lire l’état marche/arrêt d’une broche, par exemple celle d’un bouton, et analogRead() pour comparer la mesure d’un capteur à un seuil. Les sketches Arduino ci-dessous utilisent l’API Arduino standard. Les programmes de test C++ portables qui les accompagnent remplacent le matériel de la carte par des valeurs déterministes : ils permettent de compiler et de suivre la logique de traitement des entrées sans carte Arduino, mais ne testent pas le comportement électrique.

Choisir la source d’entrée : série, numérique ou analogique

Utilisez l’entrée série lorsqu’un appareil hôte envoie des caractères ou des commandes par USB ou par une liaison UART. Utilisez une broche numérique lorsque le signal a deux états. Choisissez une entrée analogique si le capteur produit une tension variable que vous devez mesurer et comparer. Sélectionnez la broche et le montage électrique adaptés à votre carte et à votre capteur ; les exemples utilisent la broche 2 pour un bouton et A0 pour un capteur analogique.

Attendre des données série avec Serial.available()

Serial.available() indique le nombre d’octets présents dans le tampon de réception. Vérifiez cette valeur avant d’appeler Serial.read() afin que le sketch ne tente pas de lire lorsqu’aucun octet n’est disponible. Cet exemple consomme puis renvoie un octet à la fois, ce qui convient à une commande constituée d’un seul caractère. Il ne reconstitue pas une ligne complète ; pour traiter une commande par ligne, accumulez les octets jusqu’au caractère de nouvelle ligne et gérez explicitement le terminateur.

Exécutez ce programme de test portable pour observer le traitement des octets. Dans un sketch Arduino, conservez setup() et loop() et remplacez le petit objet de substitution montré ici par l’objet Serial de la carte.

#include <iostream>

class SerialPort {
 public:
  void begin(int) {}
  int available() const { return next_ < 1; }
  int read() { ++next_; return 65; }
  void print(const char* text) { std::cout << text; }
  void println(int value) { std::cout << value << '\n'; }

 private:
  int next_ = 0;
};

SerialPort Serial;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    int incomingByte = Serial.read();
    Serial.print("Received byte: ");
    Serial.println(incomingByte);
  }
}

int main() {
  setup();
  loop();
}
Received byte: 65

Réglez le moniteur série ou l’appareil émetteur sur le même débit en bauds. Comme Serial.read() renvoie la valeur entière d’un octet, l’exemple affiche un rapport numérique étiqueté de l’octet : l’étiquette « Received byte: » suivie de la valeur numérique de l’octet ; convertissez la valeur en char pour afficher le caractère lui-même.

Attendre une entrée numérique avec digitalRead()

Une entrée numérique se lit sur sa broche, et non sur le port série. Pour un bouton relié entre la broche 2 et la masse, configurez INPUT_PULLUP : au repos, la lecture vaut HIGH, et lorsque le bouton est enfoncé, elle vaut LOW. La boucle ci-dessous attend d’abord l’appui, puis le relâchement. Cette attente par interrogation met en pause les autres tâches de loop() tant que l’une de ces conditions n’est pas remplie.

Ce programme de test portable fournit une séquence d’états de broche à la même logique d’attente. Dans le sketch Arduino, remplacez les fonctions de substitution par les API pinMode() et digitalRead() de la carte.

#include <iostream>

const int INPUT_PULLUP = 2;
const int HIGH = 1;
const int LOW = 0;
const int buttonPin = 2;
int pinStates[] = {HIGH, LOW, LOW, HIGH};
int stateIndex = 0;

void pinMode(int, int) {}
int digitalRead(int) { return pinStates[stateIndex++]; }

class SerialPort {
 public:
  void begin(int) {}
  void println(const char* text) { std::cout << text << '\n'; }
};

SerialPort Serial;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  while (digitalRead(buttonPin) == HIGH) {
  }

  Serial.println("Button pressed");

  while (digitalRead(buttonPin) == LOW) {
  }
}

int main() {
  setup();
  loop();
}
Button pressed

La résistance de rappel interne maintient l’entrée à un niveau défini lorsque le bouton est ouvert. Si votre circuit relie plutôt le bouton à une alimentation positive et utilise une résistance externe de rappel à la masse, utilisez INPUT et vérifiez que la lecture vaut HIGH lorsque le bouton est enfoncé. Faites correspondre la polarité du code au circuit pour éviter une entrée flottante ou une réponse inversée.

Attendre un seuil analogique avec analogRead()

analogRead() mesure la tension sur une broche analogique et renvoie une valeur numérique. Comparez cette valeur à un seuil choisi en fonction de votre capteur et de votre carte. Ce sketch signale toute mesure supérieure au seuil, y compris dès le premier passage si c’est déjà le cas. Après ce signalement, il attend qu’une mesure ultérieure soit inférieure ou égale au seuil avant de pouvoir le signaler à nouveau.

Ce programme de test portable fournit deux mesures : la première dépasse le seuil et la suivante lui est inférieure ou égale. Sur la carte, le cœur Arduino fournit A0 et analogRead() ; les broches disponibles et la plage des mesures varient selon la carte.

#include <iostream>

const int A0 = 0;
const int sensorPin = A0;
const int threshold = 500;
int readings[] = {600, 450};
int readingIndex = 0;

int analogRead(int) { return readings[readingIndex++]; }

class SerialPort {
 public:
  void begin(int) {}
  void println(const char* text) { std::cout << text << '\n'; }
};

SerialPort Serial;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);

  if (sensorValue > threshold) {
    Serial.println("Threshold exceeded");

    while (analogRead(sensorPin) > threshold) {
    }
  }
}

int main() {
  setup();
  loop();
}
Threshold exceeded

La plage numérique et la tension représentées par analogRead() dépendent de la carte. Consultez sa documentation et calibrez threshold à partir des mesures du capteur. Il s’agit d’échantillonner et de comparer à répétition, et non d’attendre des octets sur le port série.

Éviter de bloquer le reste du sketch

Une boucle while serrée vérifie sans cesse l’entrée, mais empêche le reste de loop() de s’exécuter tant que sa condition ne change pas. C’est utile si le sketch doit s’arrêter à cet endroit, mais cela retarde les autres tâches, comme la mise à jour d’un écran ou la vérification d’une autre entrée. Si le sketch doit continuer à fonctionner, vérifiez l’entrée une fois par passage et mémorisez son état au lieu d’attendre dans une boucle. Par exemple, utilisez if (Serial.available() > 0) pour traiter les octets disponibles, puis poursuivez le reste de loop().

Si le sketch semble ne plus répondre, vérifiez que la broche choisie correspond au câblage, que l’entrée numérique a un niveau défini, que l’émetteur série utilise le débit en bauds configuré et que le seuil analogique est adapté à la plage de mesure de la carte. Une attente bloquante ne se termine pas non plus tant que l’état testé n’a pas changé.