Oh non !
Tu t’es perdue en pleine mer après que ton bateau ait coulé,
il faut absolument que tu puisses détecter les bateaux aux alentours. En plus, tu n’as plus qu’un micro:bit
et un ordinateur avec juste assez de batterie pour t’en sortir.
Info
Le but de ce TP est de créer un système de balises grâce aux cartes micro:bit.
Ces balises vont permettre de se détecter entre elles, et ainsi de savoir si d’autres naufragés,
ou encore des bateaux de sauvetage sont aux alentours.
Pour cela, il va falloir utiliser une balise centrale qui sera chargée de détecter
les autres naufragés lorsque ceux-ci entreront dans sa zone de détection.
Ce TP va te permettre de comprendre le fonctionnement du module
radio de la carte micro:bit.
Voila une petite mise en scène de la situation :
Utilisation
Suite au naufrage du navire, tu as perdu les autres membres de l’équipage.
Il faut donc qu’ils puissent te détecter également.
Info
Ici, tu vas créer une balise qui va te permettre à la fois de
détecter les autres naufragés ainsi que les bateaux aux alentours.
Ainsi, la carte micro:bit peut agir à la fois comme une balise
réceptrice (aussi appelée serveur ou balise centrale), et comme une
balise émettrice (aussi appelée client).
La balise réceptrice agit comme un phare permettant aux clients de savoir
s’ils sont à côté de celle-ci.
La balise émettrice est donc une carte micro:bit qui va tenter de détecter la balise
centrale.
Voici un schema simplifié des interactions entre les deux balises, que nous allons réaliser lors de ce TP.
Attention, si le récepteur est trop loin, le signal va se perdre dans l’eau !
Commençons !
Mise en place
Tout d’abord, télécharge le squelette du TP via le bouton Code à compléter,
en haut de la page, puis ouvre ce fichier dans ton éditeur de texte préféré.
Explication du squelette
Avant tout, il faut importer les bons modules pour pouvoir utiliser la
radio sur la carte micro:bit.
Voici le code du squelette :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import radio
from microbit import*# L'image à afficher pour l'émetteur.image_emetteur = Image(
"99900:""00090:""99009:""00909:""90909:")
# La variable pour savoir si la carte est émettrice.est_emetteur =True# La puissance minimum requise pour détecter un autre naufragé.puissance_minimum =-60
Voici le motif de image_emetteur. Il s’agit d’une image de 5x5 pixels,
ce qui est la définition d’affichage d’une carte micro:bit.
Ensuite, il faut configurer le module radio et l’activer.
1
2
3
4
5
6
7
# configuration du module radio# le paramètre channel correspond au canal sur lequel le module radio doit# écouter et recevoir des informations.radio.config(channel=42)
# activation du module radioradio.on()
Info
Il existe beaucoup de paramètres pour configurer la radio que nous
n’explorerons pas ici, mais n’hésite pas à regarder plus en profondeur la
documentation
du module si cela t’intéresse.
Finalement, pour permettre aux autres naufragés de te recevoir à
n’importe quel moment, il faut ajouter une boucle qui se répète indéfiniment.
1
2
3
4
5
6
7
whileTrue:
# TODO : remplir le code ici# Cette instruction permet au code de marquer une pause de 100 millisecondes# entre chaque itération de la boucle pour réduire la puissance nécessaire# pour faire fonctionner la carte. sleep(100)
Info
L’instruction sleep(100) marque une pause de 100 millisecondes entre chaque
tour de boucle pour éviter à la carte d’avoir à exécuter trop d’instructions à
la suite.
Changer le mode de la balise
Nous voulons utiliser la balise dans plusieurs modes.
Un mode est un moyen pour une même carte d’utiliser plusieurs codes
différents en fonction du contexte dans lequel elle se trouve.
Nous devons effectivement recevoir les appels des autres naufragés et
être capable de leur envoyer des messages aussi.
Il faut que la balise puisse savoir si elle doit émettre ou recevoir.
À toi de jouer !
Rajoute des instructions de code dans la boucle, qui vont permettre à la balise de changer de mode lorsque le bouton A
est pressé.
Pour rappel, le mode de la balise est représenté par la variable
est_emetteur.
Info
Tu peux utiliser la fonction was_pressed de button_a qui
t’indique si le bouton a été appuyé depuis la dernière fois que cette fonction
a été appelée.
Le module radio
Le mode émetteur
Le mode émetteur permet à la balise d’émettre des messages à intervalles
réguliers. Ils seront reçus par les récepteurs afin que des sauveteurs puissent
te retrouver en pleine mer.
Info
La fonction send(message) du module radio permet d’envoyer un
message via la radio du micro:bit.
Voici un exemple d’utilisation de la fonction radio.send :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from microbit import*import radio
# Configuration de la radio.radio.config(channel=42)
# Allumage de la radio.radio.on()
# Envoie un message lorsque la carte démarre.radio.send("Demarrage")
whileTrue:
# Envoie un message a chaque fois que le bouton A est appuyé.if button_a.was_pressed():
radio.send("appui")
sleep(100)
À toi de jouer !
Écris un code dans la boucle infinie, qui, lorsque la balise est en mode
émetteur, envoie le message SOS à toutes les balises réceptrices.
Note: Par défaut, lorsqu’un message est envoyé, il est envoyé à toutes les
cartes micro:bit qui écoutent.
Le mode récepteur
Grâce à la première partie du TP, ta balise peut maintenant envoyer des
messages mais ne peut pas recevoir d’informations d’une autre balise.
Il serait vraiment mieux si tu pouvais retrouver les autres naufragés.
Info
Le module radio ne permet pas de connaître la distance parcourue par un message
reçu. Il va donc falloir utiliser la puissance du signal reçu pour
estimer la distance.
La puissance d’un signal s’exprime en décibels (de symbole dB),
comme le son !
Plus la source d’émission du signal est loin, moins la puissance en décibels
sera importante.
Info
La fonction receive_full() du module radio permet, entre autres, de savoir
avec quelle force le message a été reçu.
Cette fonction renvoie un tuple, ou None si aucun message n’est reçu.
Le None est une valeur propre à Python qui signifie qu’il n’y a rien.
En d’autres termes cela veut dire qu’il s’agit d’une valeur vide. Dans notre
cas, si la fonction receive_full renvoie None, alors aucun message n’a
été reçu.
Ce tuple contient :
Le contenu du message
La puissance du signal (c’est-à-dire la force avec laquelle le message
a été reçu) de -255 (le plus faible) à 0 (le plus fort).
Le moment auquel le message a été reçu.
Rappel : Un tuple en Python est un groupement de valeurs permettant à
une fonction de renvoyer plusieurs informations.
Il est possible d’extraire les valeurs contenues dans ce tuple :
Appuie sur le bouton Run pour exécuter le code python ci-dessous
Le résultat :
Voici un exemple de l’utilisation de la méthode receive_full :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
recu = radio.receive_full()
# si aucun message n'a été reçu, il ne faut rien faire.# dans ce cas, le message reçu serait None.if recu isnotNone:
# le premier élément du tuple est le contenu du message# Ici SOS par exemple. message = recu[0]
# le deuxième élément est la puissance du signal. puissance = recu[1]
# Affiche le message reçu par la balise client (émetteur). display.scroll(message)
# Affiche la puissance du signal. display.scroll(str(puissance))
À toi de jouer !
Écris la partie récepteur de la balise.
Clique ici pour avoir de l'aide !
Aide : Le code peut suivre cette procédure, écrite en pseudo-code :
1
2
3
4
5
6
7
8
9
10
11
12
si la balise est réceptrice, alors
message_reçu <- radio.receive_full()
si message_reçu est None, alors
On ne capte pas de balise aux alentours.
sinon,
message, puissance, temps <- message_reçu
si puissance > puissance_minimum, alors
# Une balise proche et d'autres naufragés sont détectés
Affiche l'image Image.HAPPY
sinon,
# La puissance n'est pas suffisante, aucune balise n'est proche.
Affiche l'image Image.SAD
Bravo ! Tu sais maintenant si des naufragés sont proches, et tu peux
envoyer des messages aux secours.
Cette première partie du TP t’as permis de mieux comprendre l’utilisation du
module radio. Dans la prochaine partie, tu vas pouvoir utiliser ce module radio
pour faire évoluer ta balise.
Aller plus loin
Maintenant que tu as un système de balises fonctionel, il serait intéressant de
pouvoir connaître le nombre de naufragés repérés. Pour cela, il faut que la
balise centrale garde un compte de toutes les balises qui lui ont envoyé un
message.
Établissement du protocole
Pour être sûr que l’émetteur et le récepteur se comprennent, il faut établir ce
que l’on appelle un protocole.
Info
Un protocole est une liste de règles précises qui doivent être respectées afin
de s’assurer que toutes les personnes utilisant ce protocole se comprennent.
En d’autres termes, il s’agit du langage que nous souhaitons utiliser.
Puisqu’il s’agit d’un langage, tu es libre d’utiliser ce que tu veux comme
convention pour permettre aux cartes de communiquer entre elles.
Par exemple, on peut dire que lorsque la balise centrale (le récepteur) reçoit
la chaîne de caractères SOS, alors un client a commencé à établir une
communication avec la balise centrale. À ce moment-là, la balise centrale
envoie à son tour le message MAYDAY, pour signifier aux naufragés qu’elle
reçoit leur signal.
Voici un schéma explicatif de la manière dont notre protocole va fonctionner :
Pour résumer :
L’émetteur envoie SOS
Quand le récepteur reçoit SOS, il renvoie MAYDAY.
Quand l’émetteur reçoit MAYDAY, la connexion est établie, il renvoie OK pour faire valider la connexion par le récepteur.
Quand le récepteur reçoit OK, alors il sait qu’un nouvel émetteur est connecté.
L’émetteur et le récepteur peuvent communiquer.
Quand le récepteur ne reçoit plus de message, alors il considère que l’émetteur n’est plus dans sa zone de détection.
Une fois la connexion établie, le but va être de connaître le nombre de
naufragés aux alentours.
Nous pouvons estimer qu’un client qui n’a pas envoyé de messages depuis
un certain temps est déconnecté.
Côté naufragé (client/émetteur)
Désormais, il faut que le naufragé envoie le message OK lorsqu’il reçoit
le message MAYDAY.
À toi de jouer !
Écris le code permettant au client d’envoyer le message OK lorsque le message
MAYDAY est reçu.
Côté balise centrale (serveur/récepteur)
Maintenant que le client répond au message de la balise, il faut permettre
à la balise de lire les messages de tous les clients.
Info
Lorsque le module radio de la carte micro:bit reçoit un message, le
message est stocké dans la mémoire avant d’être lu. Tu peux lire les messages
stockés avec la fonction receive du module radio qui renvoie une
chaîne de caractères s’il y a encore des messages non lus, sinon None.
Ainsi, si le message renvoyé par receive vaut None alors, tous les messages
ont été lus.
Nous savons que le récepteur peut recevoir deux messages différents :
SOS: Si un naufragé ignore que la balise existe et est proche.
OK: Lorsque le naufragé sait que la balise existe.
À toi de jouer !
Modifie le code de la balise centrale pour qu’elle tienne un compte des
naufragés actuellement connectés à celle-ci.
Astuce : Le nombre de clients connectés correspond au nombre de messages
reçus contenant la chaîne de caractères OK sur les dernières 5 secondes
(par exemple).
Tu peux t’aider du pseudo-code ci-dessous.
1
2
3
4
5
6
7
8
9
10
# la balise est réceptrice.
tant qu'il y a des messages:
récupérer la puissance et le contenu du message
si la puissance est suffisante, alors:
si le message est `SOS`, alors:
envoyer le message `MAYDAY`
sinon si le message est `OK`, alors:
# un naufragé est détecté.
Incrémenter le compteur de naufragés.
N’oublie pas de remettre le compteur de naufragés à 0 après 5 secondes !
Info
Pour calculer le temps entre deux instants, tu peux utiliser le module
time, et les fonctions ticks_ms et ticks_diff
1
2
3
4
5
6
7
8
import time
compteur_1 = time.ticks_ms()
compteur_2 = time.ticks_ms()
# donne la différence en millisecondes entre compteur_1 et compteur_2difference = time.ticks_diff(compteur_1, compteur_2)
Info
Rappel : pour envoyer un message, tu peux utiliser la fonction send du
module radio qui prend une chaîne de caractères en paramètre.
Si jamais tu as besoin d’aide n’hésite pas à demander à un organisateur,
ils sont là pour toi !
Toujours plus loin !
Générer un identifiant pour chaque client
Tu auras remarqué que le compte de balises n’est pas très précis. Cela est dû
au fait que la balise centrale ne sait pas de qui provient chaque message.
Pour remédier à cela, il faut trouver un système fiable permettant à chaque
client d’avoir un identifiant unique.
Info
Pour générer un identifiant unique par machine, le plus simple étant d’utiliser
la fonction unique_id du module machine. Cette fonction va te renvoyer
une chaîne de caractères particulière qui peut contenir n’importe quel
caractère. Ce genre de chaînes de caractères s’appelle des byte string et
représentent en fait des listes d’octets.
Note: Un octet est un groupement de 8 bits qui forment un nombre entre 0 et
255. Chaque octet représente un caractère grâce à ce que l’on appelle la table
ASCII. Cette table est l’équivalent de l’alphabet où le A vaut 1 et le
Z 26 par exemple ou encore l’alphabet morse ou le A vaut .- et le Z
vaut --...
Pour utiliser le module machine, il faut l’importer au début de ton fichier grâce à cette ligne :
1
import machine
Tu peux ensuite créer une variable id qui contiendra machine.unique_id() avant de commencer ta boucle while, pour créer l’identifiant de ce micro:bit
À toi de jouer !
Adapte le mode émetteur de la balise pour que tous les messages envoyés par
celle-ci soient de la forme <ton_identifiant_unique>:<ton_message>.
Comme spécifié par le protocole.
Par exemple, si ma balise a pour identifiant unique 123456, et qu’elle doit
envoyer le message SOS, le message final doit etre 123456:SOS.
Connexion !
Désormais, chaque client possède un identifiant unique. Tu peux donc
savoir exactement combien de clients sont connectés à ta balise.
Comme spécifié dans le protocole, tous les messages envoyés par le client
doivent être sous la forme <identifiant>:<mon_message>, et le serveur doit
également répondre au client avec des messages de la même forme en spécifiant
l’identifiant du client.
Maintenant que tu as un moyen de savoir qui est l’émetteur d’un message,
pour connaître exactement le nombre de naufragés dans le rayon de la
balise, il faut savoir combien de naufragés différents ont envoyé des
messages dans les cinq dernières secondes.
À toi de jouer !
Modifie le code du serveur pour stocker l’heure du dernier message
reçu pour chaque client.
Astuce : tu peux modifier la liste des identifiants et remplacer par des
tuples contenant l’identifiant et l’heure du dernier message pour
cet identifiant.
Tu peux maintenant savoir précisément quand chaque client a envoyé un message
pour la dernière fois.
Il ne te reste plus qu’à récupérer tous les identifiants dont le dernier
message remonte à moins de 5 secondes pour connaître le nombre de clients
connectés en ce moment !
Conclusion
Bravo, tu es arrivée à la fin de la partie (plus ou moins) guidée de ce TP !
Tu as maintenant tous les outils nécessaires pour utiliser le module radio
pour toute sorte de projets.
Améliorations
Maintenant, ton système de balise devrait être parfaitement fonctionnel.
Tu peux continuer à améliorer ce projet en rajoutant encore d’autres
fonctionnalités.
Voici des exemples de choses que tu peux faire :
Améliorer le système de protocole pour permettre aux clients de demander à
la balise d’exécuter d’autres actions, comme par exemple la possibilité pour
une balise émettrice d’envoyer SOS à toutes les autres balises connectées.
Permettre à la balise d’envoyer des informations au naufragé lorsque
celui-ci se connecte, comme son nom par exemple.