Simulation d'un feu de chantier pour la circulation automobile
Fondamental : Matériel nécessaire
Pour cette activité, nous utiliserons
2 cartes micro:bit avec cables croco ou shield pour connecter des composants extérieurs (ici des LED)
4 LEDs (2 rouges et 2 oranges)
2 résistances de protection de 220Ohms
une plaquette de prototypage (breadboard) ou bien un modèle de feu imprimé en 3D.
Fondamental : Méthode alternative sans matériel supplémentaire
Si vous ne disposez que des cartes sans possibilités de raccorder des LED sur les broches d'entrée/sortie, pas de problèmes : vous pourrez réaliser cette activité en utilisant la matrice LED de la carte pour afficher l'état des feux en remplacement des LED rouges et orange.
Je donnerai pour chaque étape de l'activité les codes correspondants aux deux situations : avec et sans feux LEDs.
Version 0
Consigne
Créer une simulation de feu dans laquelle
un feu comporte 2 LEDs (orange et rouge) connectées sur les broches 0 et 1 de la carte. En l'absence de LEDs, afficher le feu sous forme d'un carré de 4 pixels en haut à droite pour rouge et en bas à droite pour orange (une valeur de pixels égale à 4 simulera une couleur différente).
le feu change toutes les 10 secondes
un compte à rebours s'affiche sur l'écran
Simulation : Utilisation du simulateur en ligne
Cette version 0 peut être réalisée sur le simulateur en ligne en utilisant les broches 5 et 6 pour simuler les 2 LED du feu ou bien en utilisant uniquement la matrice de LED.
Méthode : Le montage en cas d'utilisation des LEDs
Pour cette activité, nous utiliserons
2 LEDs (une rouge et une orange)
une résistance de protection de 220Ohms
une plaquette de prototypage (breadboard) ou bien un modèle de feu imprimé en 3D.
Complément : Indication pour la version avec LED
On pourra utiliser les fonctions ci-dessous permettant de simuler un feu rouge, un feu orange et l'affichage du temps restant
def afficheRouge():
pin1.write_digital(1)
pin0.write_digital(0)
def afficheOrange():
pin1.write_digital(0)
pin0.write_digital(1)
def afficheAttente(attente):
display.show(str(attente))
Complément : Indication pour la version sans LED
On pourra utiliser les fonctions ci-dessous permettant de simuler un feu rouge, un feu orange et l'affichage du temps restant
def afficheRouge():
for x in range(3,5):
for y in range(2):
display.set_pixel(x,y,9)
for x in range(3,5):
for y in range(3,5):
display.set_pixel(x,y,0)
def afficheOrange():
for x in range(3,5):
for y in range(2):
display.set_pixel(x,y,0)
for x in range(3,5):
for y in range(3,5):
display.set_pixel(x,y,4)
def afficheAttente(attente):
for x in range(2):
for y in range(5):
display.set_pixel(x,y, 0 if 5*x+y >= attente else 9)
Version 1 : Passage à 2 feux
Il y a deux façons d'aborder la suite de cette activité selon le niveau des élèves et la progression Python dans l'année :
on demande aux élèves de construire le projet eux même
on fournit un code opérationnel et on pose des questions aux élèves pour les faire réfléchir en mode débranché
Dans la suite de l'activité, je me placerai dans le second scénario : le code version 1 est fourni aux élèves et une démonstration leur est faite du dispositif fonctionnel d'un bout à l'autre de la salle de classe. Il est alors possible de mener la suite de cette activité en mode partiellement débranché en demandant aux élèves de répondre aux questions sur feuille puis passer à la phase de réalisation si vous avez accès à une salle info avec le matériel adéquat.
Objectif de l'activité
Dans cette partie, nous allons étudier un système de 2 feux connectés dans lequel
les feux sont en opposition !
Les 2 feux affichent le même compte à rebours
Consigne
Nous allons travailler sur les programmes suivants : étudiez la version avec LED ou sans LED selon votre configuration (la version sans LED fonctionne sur la carte seule en utilisant l'affichage de la matrice LED pour simuler les feux) puis répondez sur feuille aux questions suivantes :
Les programmes sur les 2 cartes sont-ils identiques ? Pourquoi ?
Identifiez le programme maître et le programme esclave.
Décrire le protocole de communication entre les cartes
Est-on certain de la robustesse du système ?
les feux peuvent-ils être tous les deux au rouge ? Est-ce gênant ?
les feux peuvent-ils être tous les deux au vert ? Est-ce gênant ?
quelles sont les conséquences du plantage d'un des feux ?
Simulation : Utilisation du simulateur en ligne
Ces deux programmes peuvent être simulés dans le simulateur en ligne, mais l'un après l'autre indépendamment.
Pour voir les messages envoyés par le programme maître, réglez les paramètres de l'onglet radio comme indiqué sur la capture d'écran ci-contre.
Sur le programme esclave, vous pourrez utiliser le champ Message pour simuler l'envoi d'une commande par le maître (essayez d'envoyer 3 ou VERT et observez le comportement de la carte).
Méthode : Eléments de réponse
Les deux feux peuvent être au rouge simultanément le temps que l'esclave reçoive une consigne du maître mais ce n'est pas gênant. Il n'est pas possible cependant du fait des valeurs d'initialisation de la variable feuRouge que les deux feux se retrouvent orange en même temps ce qui est plutôt rassurant.
Pour le moment le protocole de communication est simple : Il va toujours du maître vers l'esclave et utilise les mots suivants :
VERT : demande à l'esclave de passer à l'orange
ROUGE : demande à l'esclave de passer au rouge
1 à 9 : Valeur du compte à rebours
Il y a tout de même une faille si un feu est défaillant alors que l'autre laisse passer les voitures. Une absence de feu peut laisser croire aux usager que la voie est libre et ils vont rencontrer des véhicules venant en face. Le dispositif n'est donc pas très robuste.
Complément : Version 1 bis : identique à la version 1 mais le feu orange clignote !
Cette déclinaison de la version 1 n'est pas si simple à mettre en œuvre car elle requiert d'éviter d'avoir recours à la fonction sleep() qui bloque l'exécution du programme. Il faut donc envisager la gestion du temps autrement. A réserver aux élèves les plus expérimentés !
La méthode utilise une variable clignotant qui mémorise toutes les secondes la valeur de l'horloge donnée par ticks_ms(). Ensuite, le clignotement est réalisé dans la fonction afficheOrange() par le code suivant ou on utilise le temps écoulé depuis la dernière mémorisation de la valeur clignotant pour déterminer la luminosité du pixel. Le maximum de luminosité est donné à l'instant clignotant + 500ms.
# orange clignotant
couleur = max(0,4 - abs(ticks_ms()-clignotant - 500)//100)
for x in range(3,5):
for y in range(3,5):
display.set_pixel(x,y,couleur)
Voir le code complet en version LED et sans LED.
Version 2 : Le véhicule prioritaire
Consigne
Un véhicule prioritaire arrive à un feu ce qui doit le faire basculer au vert immédiatement.
Imaginer par quel(s) moyen(s) on peut interagir avec la carte pour simuler cette situation ? décrire l'interaction homme-machine.
la manière de prendre en compte l'arrivée du véhicule prioritaire est-elle identique selon le feu qui reçoit le signal ?
situation A : le véhicule prioritaire arrive au feu maître. Modifier le programme maître afin qu'un appui sur le bouton A passe le feu maître à l'orange et l'autre feu au rouge.
situation B : le véhicule prioritaire arrive à l'autre feu. Que faut-il modifier pour prendre en compte cette situation ?
Décrire les modifications apportées au protocole de communication
Remarque :
Dans ce scénario, les élèves n'ont pas à écrire plus de 4 lignes de python pour les deux dernières questions, ce qui est tout à fait abordable pour un élève de seconde en SNT, même si au final, le projet global est assez ambitieux.
Éléments de réponse
Il y a plusieurs moyens d'interagir avec la carte pour signaler la présence d'un véhicule prioritaire. Le plus simple est d'utiliser le bouton A de la carte, mais on peut imaginer d'autres scénarios :
utiliser l'accéléromètre pour détecter une secousse
communication radio avec une autre carte microbit
souffler sur la carte qui détectera une élévation soudaine de la température
approcher un aiment qui sera détecter par le magnétomètre
Pour la prise en charge de l'arrivée du véhicule prioritaire, les deux feux n'ont pas le même rôle : l'un envoie des ordres (maître) et le second obéi (esclave). Il n'y a pas pour le moment de communication de l'esclave vers le maître. Il faudra ajouter cette fonctionnalité pour permettre à un véhicule prioritaire de déclencher le feu esclave.
Concernant le protocole de communication, il n'y a pas de changements pour la situation A : en effet le maître contrôle le feu esclave et il peut choisir de le passer au rouge quand bon lui semble.
Par contre, lorsque le véhicule prioritaire arrive au feu esclave il est nécessaire de modifier le protocole de communication afin de permettre à l'esclave de faire un signalement au maître. On utilise ici le message PRIO que l'esclave envoie au maître pour lui demander le passage.
Méthode : Corrigé situation A : un appui sur le bouton A passe le feu maître à l'orange et l'autre feu au rouge.
Ici seul le code maître doit être actualisé. L'esclave n'est pas concerné par l'arrivée du véhicule prioritaire au feu maître car de toute manières, c'est le feu maître qui commande l'autre feu. Le code maître est modifié en ajoutant ces lignes au début de la boucle principale :
# Arrivee du vehicule prioritaire au feu maitre
if button_a.was_pressed():
feuRouge = False
attente = DUREE
radio.send("ROUGE")
Voir le code complet en version LED et sans LED.
Méthode : Corrigé situation B : le véhicule prioritaire arrive au feu esclave.
Ici, nous devons ajuster les deux codes afin d'établir une communication dans le sens esclave vers maître.
Code pour le feu maître. 5 lignes ont été ajoutées pour écouter les communications en provenance de l'esclave.
# Traitement des messages en provenance de l'esclave
incoming = radio.receive()
# Arrivee du vehicule priopritaire au feu esclave
if incoming == "PRIO" :
feuRouge = True
attente = DUREE
radio.send("VERT")
Code pour le feu esclave. Deux lignes ont été ajoutées pour envoyer le signal PRIO au maître. Il enverra alors l'ordre à l'esclave de passer au vert.
# Arrivee vehicule prioritaire
if button_a.was_pressed():
radio.send("PRIO")
Voir le code complet en version LED et sans LED.
Version 3 : Améliorer la robustesse du dispositif
Consigne
Quel scénario proposeriez-vous afin de renforcer la robustesse (tolérance aux pannes) du dispositif et renforcer la sécurité ?
Proposez une modification des programmes en ce sens
Méthode : Corrigé scénario A
Afin de renforcer la fiabilité du dispositif, une communication régulière peut être établie du maître vers l'esclave. Si l'esclave ne reçoit pas de nouvelles du maître, il passe au rouge et affiche une figure triste. Pour ce faire, dans le code du feu maître, 4 lignes ont été ajoutées :
# Robustesse du dispositif :
# Le maitre envoie l'etat du feu a l'esclave
# toutes les secondes
if feuRouge :
radio.send("VERT")
else:
radio.send("ROUGE")
Pour le feu esclave, voici les lignes impactées. On utilise ici la fonction ticks_ms() afin de savoir combien de millisecondes se sont écoulées depuis la dernière transmission du feu maître. Si ce temps dépasse 2 secondes, l'esclave se met en sécurité.
# Traitement des messages du maitre
incoming = radio.receive()
if incoming:
if incoming == "VERT" :
feuRouge = False
lastTransm = ticks_ms() # message recu
elif incoming == "ROUGE" :
feuRouge = True
lastTransm = ticks_ms() # message recu
elif len(incoming) ==1:
afficheAttente(int(incoming))
# Mise en securite si le maitre plante
if ticks_ms() - lastTransm > 2000 :
# Plus de deux secondes sans nouvelles du maitre
feuRouge = True
display.show(Image.SAD)
Voir le code complet en version LED et sans LED.
Méthode : Corrigé scénario B
Pour améliorer encore la fiabilité du dispositif, une communication régulière (envoi du message ALIVE) est établie de l'esclave vers le maître. Si le maître ne reçoit pas de nouvelles de son esclave, il passe au rouge et affiche une figure triste.
Voici les impacts sur le code maître de cette dernière modification :
On commence par ajouter une variable qui mémorise l'instant de la dernière transmission de l'esclave
lastTransm = ticks_ms() # derniere transmission de l'esclave
Ensuite, dans la boucle principale, on met le maître en sécurité (feu rouge et image triste) si l'esclave n'a pas donné signe de vie depuis plus de 2 secondes.
# Mise en securite si l'esclave plante
if ticks_ms() - lastTransm > 2000:
# Plus de deux secondes sans nouvelles de l'esclave
feuRouge = True
display.show(Image.SAD)
Pour le feu esclave, on ajoute ue nouvelle variable qui mémorise le dernier envoi du message ALIVE :
lastAlive = ticks_ms() # derniere transmission ALIVE de l'esclave
Ensuite, on envoie le message ALIVE toutes les deux secondes dans la boucle principale :
# L'esclave envoie un message au maitre toutes les secondes
if ticks_ms() - lastAlive > 1000:
radio.send("ALIVE")
lastAlive = ticks_ms()
Voir le code complet en version LED et sans LED.
Version finale
L'usage de la fonction sleep() n'est vraiment pas recommandable sur le feu maître car pendant qu'il est en sommeil il n'est pas à l'écoute des événements extérieurs et ne peut donc pas réagir en temps réel. La version proposée ci-dessous banni le sleep() au profit de la fonction ticks_ms() déjà rencontré. Il y a une meilleure réactivité du dispositif mais au prix d'un code légèrement plus compliqué, ce qui peut rebuter des élèves débutants en programmation.
Voir le code complet en version LED et sans LED.
Pour aller plus loin
Quelques idées afin de prolonger ce projet pour ceux qui le souhaitent
Ajouter un délai de sécurité durant lequel les 2 feux sont rouges pour laisser le temps aux véhicules engagés de libérer la voie
Réaliser la télécommande du chef de chantier qui
affiche quel feu est passant
permet de commander les 2 feux avec les boutons A et B
Ajouter un 3ème feu. Quelles modifications cela implique t-il ? Proposer un protocole de communication gérant une configuration à 3 (voire plus) feux.