INTRODUCTION |
Un capteur est un composant permettant de mesurer une grandeur physique telle que la température, l’intensité lumineuse, la pression ou des distances. Dans la plupart des cas, la valeur délivrée par le capteur est un nombre compris dans la plage des valeurs mesurées. Il existe cependant également des capteurs qui ne connaissent que deux états à la manière d’interrupteurs. On compte parmi ces derniers les capteurs tactiles, les capteurs permettant de savoir si le niveau d’un récipient est plein, etc. La grandeur physique mesurée est généralement convertie par le capteur en une tension électrique qui est ensuite évaluée par de l’électronique supplémentaire [plus...Pour que le signal puisse être traité par un ordinateur, il faut au préalable qu’il soitconverti en un signal digital à l’aide d’un convertisseur analogique-numérique (AN), en anglais ADC (Analog to Digital Converter]. La structure interne d’un capteur peut être très complexe comme c’est le cas pour les capteurs ultrasoniques, gyroscopiques ou ceux permettant de mesurer des distances au LASER. La courbe caractéristique d’un capteur décrit la relation entre la grandeur physique mesurée et les valeurs délivrées par le capteur. De nombreux capteurs ont une courbe caractéristique plus ou moins linéaire mais il est toujours nécessaire de déterminer le facteur de conversion (pente) et l’ordonnée à l’origine. Pour ce faire, on procède au calibrage du capteur grâce à une série de mesures de grandeurs connues. Le capteur ultrasonique permet de déterminer la distance à un objet en mesurant le temps nécessaire à une courte impulsion ultrasonique de voyager jusqu’à l’objet et d’être réfléchie jusqu’au capteur. Pour des distances comprises entre 30 cm et 2m, le capteur délivre des valeurs comprises entre 0 et 255 où 255 (-1 en mode simulation) est retourné lorsqu’il n’y a pas d’objet détecté à portée du capteur.
Dans la plupart des applications, le programme interroge les valeurs lues par le capteur à intervalles réguliers. On appelle ceci « faire du polling ». Les valeurs d’un capteur sont donc lues et traitées en boucle. La résolution temporelle, qui correspond au nombre de mesures par seconde, dépend du capteur, de la rapidité de l’ordinateur et de la connexion à disposition pour relier la brique et le programme. Le capteur ultrasonique n’est par exemple capable de faire que deux mesures par seconde. La valeur d’un capteur ne prenant que deux valeurs distinctes peut également être déterminée par polling. Il est cependant plus commode de concevoir les changements d’états comme des événements à traiter par programme à l’aide de fonctions de rappel déclenchées à chaque nouvelle lecture de valeur.
|
POLLING VS ÉVÉNEMENTS |
Dans de nombreuses situations, il est possible de décider si l’on préfère contrôler un capteur par polling ou par gestionnaire d’événements. Tout dépend de l‘utilisation que l’on veut en faire. On peut comparer les deux façons de procéder en connectant un moteur et un capteur tactile à la brique. Dans ce cas, une pression sur le bouton tactile devrait enclencher le moteur et une nouvelle pression devrait arrêter les moteurs. Les événements sont bien plus malins pour cette application puisqu’ils informent de la pression sur le capteur tactile au travers d’un appel de fonction. Il suffit de passer cette fonction comme paramètre nommé lors de la création du capteur tactile avec TouchSensor(). Avec le polling, il est nécessaire d’utiliser un drapeau isOff (aussi appelé fanion, flag en anglais) dans le but de ne réagir que lors des transitions du capteur d’un état à l’autre. from nxtrobot import * #from ev3robot import * def switchMotorState(): if motor.isMoving(): motor.stop() else: motor.forward() robot = LegoRobot() motor = Motor(MotorPort.A) robot.addPart(motor) ts = TouchSensor(SensorPort.S3) robot.addPart(ts) isOff = True while not robot.isEscapeHit(): if ts.isPressed() and isOff: isOff = False switchMotorState() if not ts.isPressed() and not isOff: isOff = True
En utilisant les événements : #from nxtrobot import * from ev3robot import * def onPressed(port): if motor.isMoving(): motor.stop() else: motor.forward() robot = LegoRobot() motor = Motor(MotorPort.A) robot.addPart(motor) ts = TouchSensor(SensorPort.S1, pressed = onPressed) robot.addPart(ts) while not robot.isEscapeHit(): pass robot.exit() |
MEMENTO |
Les capteurs peuvent être gérés par polling ou par les événements. Il est indispensable de bien comprendre les deux techniques différentes et d’être en mesure de choisir de manière éclairée l’une ou l’autre selon la situation. Dans le modèle de la programmation événementielle, on définit des fonctions dont le nom commence conventionnellement par la chaine de caractères « on ». Ces dernières sont appelées fonctions de rappel puisqu’elles sont automatiquement appelées par le système en réponse aux événements survenus. Il faut enregistrer les fonctions de rappel en recourant à des paramètres nommés lors de la création de l’objet gérant le capteur. |
INTERROGER UN CAPTEUR ULTRASONIQUE PAR POLLING |
Note préliminaire : Si votre kit EV3 n’est pas livré avec un capteur ultrasonique, il est possible de réaliser cette section avec le capteur infrarouge. Il est nécessaire d’interroger un capteur par polling si l’on a besoin d’un débit de mesures constant. Nous allons dans cette section permettre au robot de chercher un objet cible placé sur le sol quelque part dans la pièce, quelle que soit sa position de départ, pour le rejoindre. Pour détecter une cible, on va recourir au capteur ultrasonique qui fonctionne exactement comme un système de radar. Pour apprendre à maîtriser un capteur, il n’y a rien de mieux que de développer un petit programme de test même si celui-ci n’est d’aucune utilité par la suite. Il est pratique et recommandé d’écrire les valeurs lues par le capteur dans la console Python et sur l’écran de la brique ainsi que de les traduire sous forme de son audible qui sera d’autant plus aigu que la distance sera grande. Ceci vous permettra de vous libérer les mains et les yeux tout en suivant en temps réel l’évolution des valeurs du capteur pendant les manipulations du robot à la main. # from nxtrobot import * from ev3robot import * robot = LegoRobot() us = UltrasonicSensor(SensorPort.S1) robot.addPart(us) isAutonomous = robot.isAutonomous() while not robot.isEscapeHit(): dist = us.getDistance() print("d = ", dist) robot.drawString("d=" + str(dist), 0, 3) robot.playTone(10 * dist + 100, 50) if dist == 255: robot.playTone(10 * dist + 100, 50) if isAutonomous: Tools.delay(1000) else: Tools.delay(200) robot.exit()
from simrobot import * #from nxtrobot import * #from ev3robot import * mesh = [[50, 0], [25, 43], [-25, 43], [-50, 0], [-25, -43], [25, -43]] RobotContext.useTarget("sprites/redtarget.gif", mesh, 400, 400) def searchTarget(): global left, right found = False step = 0 while not robot.isEscapeHit(): gear.right(50) step = step + 1 dist = us.getDistance() print("d = ", dist) if dist != -1: # simulation #if dist < 80: # real if not found: found = True left = step print("Left at", left) robot.playTone(880, 500) else: if found: right = step print("Right at ", right) robot.playTone(440, 5000) break left = 0 right = 0 robot = LegoRobot() gear = Gear() robot.addPart(gear) us = UltrasonicSensor(SensorPort.S1) robot.addPart(us) us.setBeamAreaColor(makeColor("green")) us.setProximityCircleColor(makeColor("lightgray")) gear.setSpeed(5) print("Searching...") searchTarget() gear.left((right - left) * 25) # simulation #gear.left((right - left) * 100) # real print("Moving forward...") gear.forward() while not robot.isEscapeHit() and gear.isMoving(): dist = us.getDistance() print("d =", dist) robot.playTone(10 * dist + 100, 100) if dist < 40: gear.stop() print("All done") robot.exit()
|
MEMENTO |
On peut généralement déterminer la valeur d’un capteur par des interrogations répétées à intervalles réguliers (polling) par l’entremise d’une méthode « getter » telle que getValue(), getDistance(), etc. Lorsque l’on passe du mode simulation au mode réel, il est nécessaire d’ajuster certaines valeurs, en particulier les intervalles de temps. Il faut remarquer également que s’il ne détecte pas de cible, le capteur retourne -1 en mode simulation et 255 en mode réel.
|
ÉVÉNEMENTS ET SEUILS DE DÉCLENCHEMENT |
Les capteurs possèdent un seuil de déclenchement par défaut mais celui-ci peut être modifié par un appel à setTriggerLevel().
from simrobot import * #from nxtrobot import * #from ev3robot import * RobotContext.setStartPosition(250, 200) RobotContext.setStartDirection(-90) RobotContext.useBackground("sprites/circle.gif") def onDark(port, level): gear.backward(1500) gear.left(545) gear.forward() robot = LegoRobot() gear = Gear() robot.addPart(gear) ls = LightSensor(SensorPort.S3, dark = onDark) robot.addPart(ls) ls.setTriggerLevel(100) # adapt value gear.forward() while not robot.isEscapeHit(): pass robot.exit()
|
MEMENTO |
Le franchissement d’un seuil par les valeurs mesurées par le capteur peut être interprété comme un événement. On appelle cela le déclenchement (triggering). Valeurs par défaut pour les seuils de déclenchement:
On peut résumer les avantages et les désavantages du modèle événementiel par rapport au polling de la manière suivante:
|
EXERCICES |
|
MATÉRIEL SUPPLÉMENTAIRE: CAPTEURS ARDUINO |
En l’occurrence, la brique EV3 joue le rôle du maître I2C et l’Arduino celui de l’esclave. Les logiciels supplémentaires requis pour permettre cette liaison sont inclus d’office dans la distribution de TigerJython. La brique EV3 peut être opérée en mode direct (contrôle à distance) ou en mode autonome. Pour d’avantage d’informations, consulter la page http://www.aplu.ch/ev3. |