Intro
Contourner un obstacle sur la ligne
Dans cette leçon tu vas apprendre à guider Eliobot le long d’une ligne, tout en contournant les obstacles sur la route.
Étape 1
Trouver une ligne à suivre
Eliobot adore les lignes noires sur un fond clair, tu pourras trouver son bonheur au dos de sa notice d’assemblage.
Si tu as perdu la notice ou que tu veux faire un parcours plus grand, tu peux utiliser du scotch d’électricien sur un sol ou une table claire. Tu en trouveras dans toutes les boutiques de bricolage, ainsi que dans notre boutique.
Étape 2
Déclaration des entrées / sorties
Nous allons commencer notre code en intégrant quelques bibliothèques. Ce sont des ensembles de codes déjà écrits nous permettant de rajouter des fonctions facilement.
La première s’appelle “board” et est spécifique à CircuitPython. C’est grâce à elle que nous allons pouvoir expliquer à notre programme comment sont connectés les éléments au microcontrôleur (le cerveau de Eliobot)
Pour l’intégrer dans notre programme on utilise la ligne suivante :
import board
Cela nous permet d’appeler les entrée / sorties de la cartes en utilisant le numéro de la broche.
board.IO10
Étape 3
Déclaration des capteurs
Pour déclarer les capteurs on va utiliser la bibliothèque « analogio » et « digitalio »
import analogio
import digitalio
Ensuite nous définissons chaque capteur.
vBatt_pin = analogio.AnalogIn(board.BATTERY)
lineCmd = digitalio.DigitalInOut(board.IO33)
lineCmd.direction = digitalio.Direction.OUTPUT
lineInput = [analogio.AnalogIn(pin) for pin in
(board.IO10, board.IO11, board.IO12, board.IO13, board.IO14)]
obstacleInput = [analogio.AnalogIn(pin) for pin in
(board.IO4, board.IO5, board.IO6, board.IO7)]
Les capteurs de ligne sont placés en ligne de 0 à 4, 0 étant tout à gauche et 4 tout à droite.
Les capteurs d’obstacles sont classés dans un tableau et sont numérotés de 0 à 3 : 0 pour la gauche, 1 pour l’avant, 2 pour la droite, et 3 pour l’arrière. Dans la fonction, nous utilisons l’indice 1 pour le capteur de devant.
Déclaration des moteurs
Pour déclarer les moteurs on va utiliser une bibliothèque qui se nomme « pwmio ».
import pwmio
Ensuite nous définissons chaque moteur, son sens et la batterie.
AIN1 = pwmio.PWMOut(board.IO36)
AIN2 = pwmio.PWMOut(board.IO38)
BIN1 = pwmio.PWMOut(board.IO35)
BIN2 = pwmio.PWMOut(board.IO37)
Pour nous faciliter la tâche on va utiliser la bibliothèque « elio ».
from elio import Motors, ObstacleSensor, LineSensor
Ensuite on définit les moteurs, capteur de lignes et capteur d’obstacle.
motors = Motors(AIN1, AIN2, BIN1, BIN2, vBatt_pin)
lineSensor = LineSensor(lineInput, lineCmd, motors)
obstacleSensor = ObstacleSensor(obstacleInput)
Étape 4
Calibrer la ligne
Pour obtenir la sensibilité avec laquelle on détecte la ligne, nous allons utiliser la fonction « calibrate_line_sensors() ».
lineSensor.calibrate_line_sensors()
Il faut poser le robot à l’horizontal en plaçant tous les capteurs sur la ligne que l’on souhaite suivre, puis démarrer Eliobot. Une fois que le robot a fait ses trois aller-retour et qu’il ne bouge plus, nous pouvons le récupérer et le reconnecter à son ordinateur.
Étape 5
Récupérer la valeur de seuil
Nous allons d’abord récupérer la valeur de seuil qui se trouve dans le fichier config.json après avoir calibré notre ligne :
On importe la bibliothèque « json »
import json
Et on récupère la valeur de seuil
with open("config.json", "r") as f:
calibration = json.load(f)
seuil = calibration["line_threshold"]
Étape 6
Suivre la ligne
Pour suivre la ligne on va récupérer le programme de la leçon précédente, je le remet ci-dessous:
if lineSensor.get_line(2) < seuil:
motors.move_forward(speed)
elif lineSensor.get_line(0) < seuil:
motors.motor_stop()
motors.spin_right_wheel_forward(speed)
time.sleep(0.1)
elif lineSensor.get_line(4) < seuil:
motors.motor_stop()
motors.spin_left_wheel_forward(speed)
elif lineSensor.get_line(1) < seuil:
motors.motor_stop()
motors.spin_right_wheel_forward(speed)
elif lineSensor.get_line(3) < seuil:
motors.motor_stop()
motors.spin_left_wheel_forward(speed)
time.sleep(0.1)
else:
motors.motor_stop()
Pour contourner un obstacle il faut rajouter une condition, si on voit un obstacle devant alors on fait une petite déviation de notre route.
while True:
if obstacleSensor.get_obstacle(1):
motors.turn_one_step("left", 90)
motors.move_one_step("forward")
motors.turn_one_step("right", 90)
motors.move_one_step("forward")
motors.turn_one_step("right", 90)
motors.move_one_step("forward")
motors.turn_one_step("left", 90)
else:
if lineSensor.get_line(2) < seuil:
motors.move_forward(speed)
elif lineSensor.get_line(0) < seuil:
motors.motor_stop()
motors.spin_right_wheel_forward(speed)
time.sleep(0.1)
elif lineSensor.get_line(4) < seuil:
motors.motor_stop()
motors.spin_left_wheel_forward(speed)
elif lineSensor.get_line(1) < seuil:
motors.motor_stop()
motors.spin_right_wheel_forward(speed)
elif lineSensor.get_line(3) < seuil:
motors.motor_stop()
motors.spin_left_wheel_forward(speed)
time.sleep(0.1)
else:
motors.motor_stop()
Si un obstacle est détecté, on exécute une série de mouvements pour contourner l’obstacle :
- Tourner à gauche : on tourne de 90 degrés à gauche.
- Avancer : Ensuite, il fait un pas en avant.
- Tourner à droite : on tourne de 90 degrés à droite pour se repositionner parallèlement à l’obstacle.
- Avancer à nouveau : Il avance une fois de plus pour passer devant l’obstacle.
- Tourner à nouveau à droite : on effectue un autre virage à droite de 90 degrés.
- Avancer : Il avance encore une fois pour revenir sur la ligne.
- Tourner à gauche : Finalement, il tourne à gauche pour rectifier son orientation et revenir dans sa trajectoire d’origine.
Ces mouvements permettent d’effectuer une manœuvre en « U » autour de l’obstacle, en revenant à sa trajectoire initiale après l’avoir contourné.
Étape 7
Programme final
Voici le programme final que l’on va pouvoir exécuter ▶️ :
from elio import Motors, ObstacleSensor, LineSensor
import board
import time
import analogio
import digitalio
import pwmio
import json
vBatt_pin = analogio.AnalogIn(board.BATTERY)
AIN1 = pwmio.PWMOut(board.IO36)
AIN2 = pwmio.PWMOut(board.IO38)
BIN1 = pwmio.PWMOut(board.IO35)
BIN2 = pwmio.PWMOut(board.IO37)
lineCmd = digitalio.DigitalInOut(board.IO33)
lineCmd.direction = digitalio.Direction.OUTPUT
lineInput = [analogio.AnalogIn(pin) for pin in
(board.IO10, board.IO11, board.IO12, board.IO13, board.IO14)]
obstacleInput = [analogio.AnalogIn(pin) for pin in
(board.IO4, board.IO5, board.IO6, board.IO7)]
with open("config.json", "r") as f:
calibration = json.load(f)
seuil = calibration["line_threshold"]
motors = Motors(AIN1, AIN2, BIN1, BIN2, vBatt_pin)
lineSensor = LineSensor(lineInput, lineCmd, motors)
obstacleSensor = ObstacleSensor(obstacleInput)
while True:
if obstacleSensor.get_obstacle(1):
motors.turn_one_step("left", 90)
motors.move_one_step("forward")
motors.turn_one_step("right", 90)
motors.move_one_step("forward")
motors.turn_one_step("right", 90)
motors.move_one_step("forward")
motors.turn_one_step("left", 90)
else:
if lineSensor.get_line(2) < seuil:
motors.move_forward(speed)
elif lineSensor.get_line(0) < seuil:
motors.motor_stop()
motors.spin_right_wheel_forward(speed)
time.sleep(0.1)
elif lineSensor.get_line(4) < seuil:
motors.motor_stop()
motors.spin_left_wheel_forward(speed)
elif lineSensor.get_line(1) < seuil:
motors.motor_stop()
motors.spin_right_wheel_forward(speed)
elif lineSensor.get_line(3) < seuil:
motors.motor_stop()
motors.spin_left_wheel_forward(speed)
time.sleep(0.1)
else:
motors.motor_stop()
Bravo !
Et voila, ton programme est fini ! Il ne te reste plus qu’à le Téléverser pour admirer le résultat