Utilisation des entrées et sorties (I/O)

La carte dispose d'entrées analogiques et numériques. Les sorties sont exclusivement numériques. Il est néanmoins possible de simuler une sortie analogique grâce à la technique de la modulation de largeur d'impulsions (ou PWM en anglais).

Les entrées analogiques

Une tension comprise entre 0 et 5 Volt peut être appliquée sur une entrée analogique. Au delà, il faut utiliser un diviseur de tension. Pour information, cette tension est immédiatement convertie en numérique à l'aide d'un convertisseur analogique / numérique 10 bits (Les valeurs s'étendent de 0 à 1023).

La structure minimale d'un programme qui permet d'effectuer une mesure analogique sur un port (A0 à A5) est indiquée juste après :

const int analogInPin = A0; // A0 alias signifiant Analog 0 
int sensorValue = 0;
void setup() {
}
void loop() {
  sensorValue = analogRead(analogInPin);
}

Trois étapes sont indispensables :

  1. Ligne 1 : définir le port (Pin) analogique servant à la mesure en définissant une variable nommée analogInPin (valant ici A0) ;
  2. Ligne 2 : créer une variable pour stocker le résultat de la mesure (nommée sensorValue). Attention, la valeur étant transformée en numérique, le type de la variable doit être int ;
  3. Ligne 6 : la fonction analogRead retourne la valeur mesurée sur le port A0.

Remarque : le mot clé const sert à définir une variable constante, c'est à dire dont la valeur ne doit pas être changée au cours de l'exécution du programme.

Les entrées / sorties numériques

Configuré en entrée ou en sortie, le niveau électrique du port (pin) est soit haut (HIGH), correspondant à 5 volt environ, soit bas (LOW) pour 0 volt environ. Il n'y a pas d'autre possibilité, c'est un fonctionnement tout ou rien (TOR).

Entrée numérique

L'utilisation la plus classique est celle d'un interrupteur (ou bouton poussoir) (circuit ouvert OU fermé). La masse et l'alimentation 5V sont généralement prises sur la carte. Une résistance dite “Pull Up” doit être rajoutée afin de limiter le courant lorsque le circuit est fermé.

pullup

Fig.1 : schéma électrique du branchement d'un bouton poussoir avec résitance pullup

Remarque : il existe aussi un montage direct (sans résistance) en utilisant une résistance interne à la carte que nous n'abordons pas ici.

Remarque : pour certains projets, nous pouvons être amenés à compter le nombre d'appui sur le bouton poussoir : dans ce cas, attention au phénomène de rebond (non abordé ici).

const int buttonPin = 2;
void setup() {
  pinMode(buttonPin, INPUT);
}
void loop() {
  buttonState = digitalRead(buttonPin);
}
  • Ligne 1 : affectation du numéro du port à la variable buttonPin
  • Ligne 3 : le port est configuré en entrée
  • Ligne 6 : la fonction digitalRead permet de lire l'état du port (LOW ou HIGH)

Sortie numérique

L'utilisation la plus classique est celle d'une commande (diode, moteur à faible courant, servomoteur ...). diode

Fig.2 : branchement d'une diode commandée par une sortie numérique

const int ledPin =  13;      // the number of the LED pin
void setup() {
  pinMode(ledPin, OUTPUT);
}
void loop() {
    //digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin, LOW);
}
  • Ligne 1 : affectation du numéro du port à la variable ledPin
  • Ligne 3 : le port est configuré en sortie
  • Ligne 6 ou 7 : la fonction digitalWrite place le port en état bas ou haut (LOW ou HIGH). La diode sera allumée ou éteinte.

Simulation d'une sortie analogique

La carte Arduino ne permet pas d'avoir une sortie analogique, c'est à dire de fournir une tension pouvant prendre n'importe quelle valeur entre 0 et 5 volt. Il existe une alternative qui s'appelle PWM.

Le principe est d'alterner rapidement sur la sortie numérique des états hauts et bas. Les composants électriques du circuit ne réagissent pas assez rapidement aux variations et se comportent alors comme s'ils recevaient un signal moyenné (entre les états hauts et bas). En faisant varier les durées de l'état haut par rapport au bas, on peut simuler n'importe quelle valeur analogique entre 0 et 5 volt. pwm

Fig.3 : signal logique PWM

Le programme qui génère le PWM présente l'allure suivante :

void setup()
{
  pinMode(13, OUTPUT);
}
void loop()
{
  digitalWrite(13, HIGH);
  delayMicroseconds(100); // Approximately 10% duty cycle @ 1KHz
  digitalWrite(13, LOW);
  delayMicroseconds(1000 - 100);
}
  • Ligne 7 : on place la sortie à l'état haut.
  • Ligne 8 : la fonction delayMicroseconds stoppe le déroulement du programme pendant 100 ms.
  • Ligne 9 : on place la sortie à l'état bas.
  • Ligne 10 : on attend 900 ms Ce programme crée donc un état haut pendant 10% du cycle, simulant ainsi une sortie analogique de 0,1*5= 0,5 volt.

Il existe la fonction analogWrite qui permet de générer du PWM directement :

void setup()
{
  pinMode(13, OUTPUT);
}
void loop()
{
  analogWrite(13, 25);
}

Ligne 7 : la fonction analogWrite prend en deuxième argument une valeur comprise entre 0 et 255 (25 correspondant approximativement à 10%). Attention, seulement les ports qui ont un numéro précédé d'un signe ~ sur la carte sont des ports PWM (sur une Leonardo : 3, 5, 6, 9, 10, 11 et 13).

Communication entre la carte et le logiciel Arduino

La carte et le PC peuvent communiquer entre eux via le port USB. Il s'agit d'une communication série (virtualisée ici). La carte peut également communiquer par port série avec d'autres équipements. On utilise dans ce cas les ports TX (pin 1) et RX (pin 0).

Envoi de données vers le PC

Nous nous limitons à la communication entre carte et PC. Le code à mettre en oeuvre est de la forme :

void setup() {
  // open the serial port at 9600 bps:
  Serial.begin(9600);
}
void loop() {
  //Serial.print("Hello world");
  Serial.println("Hello world"); // with new line caracter
  delay(1000); // wait one second before the next message
}
  • Ligne 3 : configure le port série à une vitesse de 9600 baud, utilisation du module Serial.
  • Ligne 6 ou 7 : envoi des données sur le port série avec ou sans retour à la ligne.
  • Ligne 8 : pause jusqu'au prochain envoi!!

Depuis le logiciel, une fenêtre de communication s'ouvre en cliquant sur le bouton suivant :

serial

Fig.4 : localisation du bouton d'ouverture du terminal serie

serial2

Fig.5 : terminal série affichant les messages en provenance de la carte

Reception de données par la carte

Taper votre texte dans la zone de texte de la fenêtre puis cliquer sur “Envoyer”. Le programme doit être prévu pour la réception des données, comme indiqué dans la suite :

serial3

Fig.6 : envoi d'une donnée à la carte

Le programme permettant de gérer la réception des données :

int incomingByte = 0;   // for incoming serial data
void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}
void loop() {
        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();
                // say what you got:
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);
        }
}
  • Ligne 7 : on teste si des données sont disponibles sur le port série.
  • Ligne 9 : la méthode read() lit caractère par caractère et ne permet donc pas de récupérer immédiatement des messages à plusieurs caractères.

Les données sont reçues caractère par caractère.

Remarque : Serial.println() écrit le caractère en decimal, hexadecimal, ... mais pas en caractère ascii. Pour éviter cela, il existe la fonction char :

    Serial.println(char(incomingByte));

Pour en savoir plus sur la communication Serial.