Aller au contenu

24 - Périphériques et IHM

Mise en situation

Un thermostat allume le chauffage quand la pièce est trop froide. Un lampadaire s’éclaire à la tombée de la nuit. Un aspirateur robot change de direction avant de toucher un mur. Dans ces trois objets, un petit ordinateur mesure quelque chose dans le monde réel, décide quoi faire, puis agit sur le monde réel.

Dans le modèle de Von Neumann, vu au chapitre 09 - Architecture , ces échanges avec l’extérieur sont le rôle des entrées-sorties. Ce chapitre présente les composants qui les réalisent, les capteurs et les actionneurs, puis montre comment écrire un programme qui les relie, et comment programmer une interface homme-machine (IHM). La fiche d’exercices correspondante est 33 - Périphériques et IHM .

Les périphériques d’entrée et de sortie

Définition. Un périphérique est un appareil relié à l’unité centrale, qui permet à l’ordinateur d’échanger des informations avec l’extérieur :

  • un périphérique d’entrée fait entrer une information dans l’ordinateur : clavier, souris, micro, caméra ;
  • un périphérique de sortie fait sortir une information de l’ordinateur : écran, imprimante, haut-parleur.

Certains périphériques font les deux. Un écran tactile affiche une image (sortie) et repère la position du doigt (entrée).

Un programme ne pilote pas directement le matériel : c’est le système d’exploitation, vu au chapitre 23 - Systèmes d’exploitation , qui gère les entrées-sorties grâce à ses pilotes. Quand un programme Python appelle input(), il demande au système le texte tapé au clavier ; quand il appelle print(), il lui demande d’afficher un texte à l’écran.

Les capteurs

Définition. Un capteur mesure une grandeur physique (température, lumière, distance, pression…) et la transforme en un signal électrique, que le système lit sous la forme d’un nombre.

Un capteur est donc un périphérique d’entrée. Quelques exemples :

Grandeur mesuréeCapteurExemple d’utilisation
TempératureThermomètre électronique (sonde)Thermostat, station météo
LumièreCapteur de luminosité (photorésistance)Éclairage public, réglage de l’écran d’un téléphone
DistanceCapteur à ultrasons ou à infrarougeRobot, aide au stationnement d’une voiture
Présence, mouvementDétecteur de mouvement infrarougeÉclairage d’un couloir, alarme
Contact, appuiBouton, interrupteur, touche de clavierClavier, sonnette, butée d’un robot
Position du doigtSurface tactileÉcran de téléphone, borne de distributeur

Le clavier et l’écran tactile sont eux aussi des capteurs : chaque touche est un petit interrupteur, et la surface tactile mesure l’endroit où le doigt la touche.

Pour le programme, une mesure n’est qu’un nombre : 21 pour 21 °C, 350 pour une luminosité de 350 sur une échelle propre au capteur, 1 ou 0 pour un bouton appuyé ou non. C’est au programmeur de savoir ce que ce nombre représente et dans quelle unité.

Les actionneurs

Définition. Un actionneur reçoit une commande du programme, sous forme de signal électrique, et la transforme en une action physique : mouvement, lumière, son, chaleur.

Un actionneur est donc un périphérique de sortie. Quelques exemples :

ActionneurAction produiteExemple d’utilisation
MoteurMouvement de rotationRoues d’un robot, ventilateur, store électrique
Lampe, diode électroluminescente (DEL)LumièreÉclairage, voyant d’un appareil
Haut-parleur, buzzerSonAlarme, signal sonore d’un four
Résistance chauffanteChaleurRadiateur électrique, bouilloire
ÉlectrovanneOuverture ou fermeture d’un passage d’eauArrosage automatique, lave-linge

L’écran est aussi un actionneur particulier : il transforme les données envoyées par le programme en lumière, point par point.

La chaîne mesure, décision, action

Un système qui réagit à son environnement fonctionne toujours en trois étapes :

  1. Mesure : le capteur mesure une grandeur physique et fournit un nombre au programme.
  2. Décision : le programme compare ce nombre à une valeur de référence et choisit une commande.
  3. Action : l’actionneur exécute la commande, ce qui modifie l’environnement.
MESUREDÉCISIONACTIONCapteurProgrammeActionneurEnvironnement : pièce, rue, sol, obstacle…mesurecommandegrandeur physiqueaction

L’action modifie la grandeur mesurée : le chauffage réchauffe la pièce, donc la température lue au tour suivant change. C’est pourquoi la chaîne se répète sans fin, tant que l’appareil est sous tension.

Le programme qui réalise la décision s’exécute sur un petit ordinateur intégré à l’objet :

  • un système embarqué est un ordinateur intégré à un appareil, qu’il commande : thermostat, lave-linge, voiture, montre ;
  • un objet connecté est un système embarqué relié à un réseau, souvent Internet : il peut envoyer ses mesures ou recevoir des ordres à distance, comme un thermostat réglable depuis un téléphone ;
  • un robot est un système embarqué qui se déplace ou manipule des objets grâce à ses actionneurs.

Trois exemples courants

Le thermostat

  • Mesure : une sonde de température mesure la température de la pièce.
  • Décision : si la température est inférieure à la consigne (la température souhaitée, par exemple 19 °C), il faut chauffer ; sinon, il ne faut pas chauffer.
  • Action : le programme allume ou éteint la résistance chauffante du radiateur.

L’éclairage automatique

  • Mesure : un capteur de luminosité mesure la lumière du jour ; dans un couloir, un détecteur de mouvement indique en plus si quelqu’un passe.
  • Décision : si la luminosité est inférieure à un seuil (et, dans le couloir, si quelqu’un est présent), il faut éclairer.
  • Action : le programme allume ou éteint les lampes.

Le robot aspirateur

  • Mesure : un capteur à ultrasons ou à infrarouge mesure la distance à l’obstacle placé devant le robot ; des capteurs de contact signalent un choc.
  • Décision : si l’obstacle est loin, le robot avance ; s’il est proche, il tourne pour l’éviter.
  • Action : le programme commande les moteurs des deux roues : même vitesse pour avancer, vitesses différentes pour tourner.
SystèmeCapteurDécisionActionneur
ThermostatSonde de températuretempérature < consigne ?Résistance chauffante
Éclairage automatiqueCapteur de luminosité, détecteur de mouvementluminosité < seuil et présence ?Lampes
Robot aspirateurCapteur de distance, capteur de contactobstacle proche ?Moteurs des roues

Programmer la chaîne en Python

Sur une carte programmable ou dans un robot, une bibliothèque fournit des fonctions qui lisent les capteurs et commandent les actionneurs. Ici, on n’a pas de matériel : on simule le capteur et l’actionneur par deux fonctions, ce qui permet d’écrire et de tester la partie la plus importante, la décision.

Le capteur, l’actionneur et la décision

Le capteur simulé renvoie une température tirée au hasard ; l’actionneur simulé affiche l’état du chauffage au lieu d’allumer un vrai radiateur.

import random


def lire_temperature():
    """Capteur simulé : renvoie la température de la pièce, en degrés Celsius."""
    return random.randint(15, 25)


def commander_chauffage(allumer):
    """Actionneur simulé : allume le chauffage si allumer vaut True, l'éteint sinon."""
    if allumer:
        print("chauffage allumé")
    else:
        print("chauffage éteint")


def decider(temperature, consigne):
    """Renvoie True s'il faut chauffer, c'est-à-dire si la pièce est plus froide que la consigne."""
    return temperature < consigne

La fonction decider ne dépend d’aucun matériel : elle reçoit des nombres et renvoie un booléen. On peut donc la tester avec des valeurs choisies, sans attendre qu’il fasse froid :

assert decider(17, 19) == True     # trop froid : on chauffe
assert decider(21, 19) == False    # assez chaud : on ne chauffe pas
assert decider(19, 19) == False    # exactement la consigne : on ne chauffe pas
print("Tous les tests passent")

La boucle de régulation

Le programme principal répète la chaîne mesure, décision, action. Ici, on se limite à cinq mesures :

consigne = 19
for i in range(5):
    temperature = lire_temperature()            # mesure
    chauffer = decider(temperature, consigne)   # décision
    print(f"Mesure {i + 1} : {temperature} °C,", end=" ")
    commander_chauffage(chauffer)               # action

Un affichage possible (les températures sont tirées au hasard) :

Mesure 1 : 17 °C, chauffage allumé
Mesure 2 : 22 °C, chauffage éteint
Mesure 3 : 19 °C, chauffage éteint
Mesure 4 : 15 °C, chauffage allumé
Mesure 5 : 24 °C, chauffage éteint

Dans un vrai thermostat, la boucle ne s’arrête jamais : on écrit while True, et le programme attend un moment, par exemple une minute, entre deux mesures.

# NE PAS EXÉCUTER : boucle sans fin, comme dans un vrai thermostat
consigne = 19
while True:
    temperature = lire_temperature()
    commander_chauffage(decider(temperature, consigne))

Remarque. Dans ce programme, chaque fonction a un seul rôle : lire_temperature pour la mesure, decider pour la décision, commander_chauffage pour l’action. Pour faire tourner le même programme sur un vrai thermostat, il suffit de réécrire les deux fonctions qui touchent au matériel ; la décision ne change pas.

L’interface homme-machine

Définition. L’interface homme-machine (IHM) est l’ensemble des moyens par lesquels un utilisateur et une machine échangent des informations : les périphériques (boutons, écran, écran tactile…) et le programme qui affiche des informations et réagit aux actions de l’utilisateur.

Le panneau d’un four (un afficheur et quelques boutons), l’écran tactile d’un distributeur de billets, la fenêtre d’une application ou une page web, étudiée au chapitre 13 - IHM Web , sont des IHM.

Le cahier des charges

Avant de programmer une IHM, on écrit son cahier des charges : la liste de ce que l’interface doit afficher, des actions que l’utilisateur peut faire et de ce que le programme doit faire en réponse. Voici celui d’un thermostat :

  1. L’utilisateur règle la consigne entre 15 °C et 25 °C, avec un curseur. La consigne vaut 19 °C au démarrage.
  2. Un bouton « Mesurer » lit le capteur de température.
  3. L’interface affiche la dernière température mesurée.
  4. L’interface affiche l’état du chauffage : « Chauffage allumé » en rouge si la température est inférieure à la consigne, « Chauffage éteint » en bleu sinon.

La programmation événementielle

Un programme avec une interface graphique ne s’exécute pas de haut en bas puis s’arrête. Il crée la fenêtre et ses composants, associe une fonction à chaque action possible de l’utilisateur, puis attend : c’est la boucle d’événements. Un clic sur un bouton est un événement ; le programme répond en appelant la fonction associée à ce bouton. Ce style de programmation s’appelle la programmation événementielle.

Une IHM avec tkinter

Le module tkinter, fourni avec Python, permet de créer des fenêtres. La page 16 - GUI en donne d’autres exemples. Les composants (en anglais widgets) utilisés ici :

Composant ou méthodeRôle
tk.Tk()crée la fenêtre principale
tk.Label(fenetre, text="…")affiche un texte (sortie)
tk.Button(fenetre, text="…", command=f)bouton : un clic appelle la fonction f (entrée)
tk.Scale(fenetre, from_=a, to=b, orient="horizontal")curseur pour choisir un entier entre a et b (entrée)
composant.pack()place le composant dans la fenêtre, sous le précédent
curseur.get(), curseur.set(v)lit ou fixe la valeur du curseur
etiquette.configure(text="…", fg="red")change le texte ou la couleur d’un Label
etiquette.cget("text")renvoie le texte affiché par un Label
fenetre.mainloop()lance la boucle d’événements

Le programme ci-dessous répond au cahier des charges du thermostat. Il ne fonctionne pas dans le navigateur : l’exécuter dans Thonny.

import tkinter as tk
import random


def lire_temperature():
    """Capteur simulé : renvoie la température de la pièce, en degrés Celsius."""
    return random.randint(15, 25)


def mesurer():
    """Lit le capteur, compare à la consigne, puis affiche la mesure et l'état du chauffage."""
    temperature = lire_temperature()
    texte_mesure.configure(text=f"Température mesurée : {temperature} °C")
    if temperature < curseur.get():
        texte_chauffage.configure(text="Chauffage allumé", fg="red")
    else:
        texte_chauffage.configure(text="Chauffage éteint", fg="blue")


fenetre = tk.Tk()
fenetre.title("Thermostat")

# Point 1 du cahier des charges : curseur de 15 à 25, réglé sur 19 au démarrage
curseur = tk.Scale(fenetre, label="Consigne (°C)", from_=15, to=25, orient="horizontal", length=250)
curseur.set(19)
curseur.pack()

# Point 2 : le bouton appelle la fonction mesurer
bouton = tk.Button(fenetre, text="Mesurer", command=mesurer)
bouton.pack()

# Points 3 et 4 : deux textes, modifiés par la fonction mesurer
texte_mesure = tk.Label(fenetre, text="Température mesurée : aucune mesure")
texte_mesure.pack()
texte_chauffage = tk.Label(fenetre, text="Chauffage éteint", fg="blue")
texte_chauffage.pack()

fenetre.mainloop()

On retrouve la chaîne mesure, décision, action, déclenchée cette fois par l’utilisateur :

  • le clic sur « Mesurer » est un événement, qui appelle mesurer ;
  • mesurer lit le capteur (mesure), compare la température à la valeur du curseur (décision), puis modifie les deux textes (action sur l’interface).

Dans command=mesurer, on écrit le nom de la fonction sans parenthèses : on indique au bouton quelle fonction appeler plus tard, au moment du clic. Avec command=mesurer(), la fonction serait appelée une seule fois, à la création du bouton.

Que retenir ?

A minima…

  • Un périphérique d’entrée fait entrer une information dans l’ordinateur, un périphérique de sortie la fait sortir.
  • Un capteur mesure une grandeur physique et la transmet au programme sous forme de nombre ; un actionneur transforme une commande du programme en action physique.
  • Un système qui réagit à son environnement répète sans fin la chaîne mesure, décision, action.
  • Une IHM est l’ensemble des moyens par lesquels un utilisateur et une machine échangent des informations. On la conçoit à partir d’un cahier des charges.

Au mieux…

  • Identifier, dans un objet courant (thermostat, éclairage automatique, robot, objet connecté), les capteurs, les actionneurs et la décision prise par le programme.
  • Écrire en Python la décision sous forme d’une fonction qui reçoit les mesures et renvoie la commande, puis la tester avec assert.
  • Programmer avec tkinter une IHM qui répond à un cahier des charges : composants d’entrée (bouton, curseur), composants de sortie (textes), fonctions appelées lors des événements, boucle d’événements.