Bachelier en Informatique et Systèmes, finalité réseaux et télécommunications
Initiation aux nano-ordinateurs Laboratoires
Projet Raspberry Pi - IMU
Thomas DELCAMPE Jordan QUICKEN Section Informatique
Année académique 2016-2017
Bachelier en Informatique et Systèmes, finalité réseaux et télécommunications
Initiation aux nano-ordinateurs Laboratoires
Projet Raspberry Pi - IMU Thomas DELCAMPE Jordan QUICKEN Section Informatique
Année académique 2016-2017
4
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
5
Table des matières
1. Introduction .......................................................................................................................................... 6 2. Le Sense Hat ....................................................................................................................................... 7
2.1. Les capteurs du Sense Hat .......................................................................................................... 7 3. Installation du Raspberry Pi............................................................................................................... 10
3.1. Installation de Raspbian ............................................................................................................. 10 3.2. Connexion au Raspberry Pi ....................................................................................................... 11
3.2.1. Branchement ....................................................................................................................... 11 3.2.2. Problème : la connexion en mode graphique ...................................................................... 11 3.2.3. Connexion ........................................................................................................................... 11
3.3. Configuration du Raspberry Pi ................................................................................................... 12 3.3.1. Installation des paquets et mises à jour .............................................................................. 12 3.3.2. Lancement du programme et choix de l’IDE ....................................................................... 12
4. Programme principal ......................................................................................................................... 13 4.1. Importation des modules ............................................................................................................ 13 4.2. Définition de la matrice LED ....................................................................................................... 13 4.3. Récupération du mouvement du gyroscope............................................................................... 14 4.4. Fonction de calcul des axes ....................................................................................................... 14 4.5. Allumage des LED’s et du display .............................................................................................. 15
4.5.1. Problème : Allumer plusieurs LED’s simultanément ........................................................... 15 4.5.2. Problèmes : Éteindre les LED’s ........................................................................................... 15
4.6. Duplication des fonctions pour les autres axes .......................................................................... 16 4.7. Programme principal final ........................................................................................................... 17
4.7.1. Problème : Plusieurs paires de LED’s clignotent ................................................................ 17 4.8. Code du programme principal .................................................................................................... 18
5. Programme secondaire ..................................................................................................................... 20 5.1. Orientations ................................................................................................................................ 20
5.1.1. Utilisation et prise en charge du joystick ............................................................................. 20 5.1.2. Récupération des orientations ............................................................................................. 20 5.1.3. Création d’une boucle et d’un booléen par direction ........................................................... 20 5.1.4. Récupération des orientations en radians ........................................................................... 21 5.1.5. Ajout à la matrice ................................................................................................................. 21
5.2. Températures ............................................................................................................................. 22 5.2.1. Récupération de la température .......................................................................................... 22 5.2.2. Découpage des chiffres ....................................................................................................... 22 5.2.3. Affichage sur la matrice LED ............................................................................................... 22 5.2.4. Création d’une boucle et d’un booléen ................................................................................ 22 5.2.5. Conversion de la température en Fahrenheit ...................................................................... 22 5.2.6. Ajout à la matrice ................................................................................................................. 22
5.3. Création d’une procédure ........................................................................................................... 23 5.4. Code final commenté .................................................................................................................. 23
6. Programme complet .......................................................................................................................... 24 6.1. Fusion des programmes ............................................................................................................. 24 6.2. Code final commenté et structuré .............................................................................................. 25
7. Conclusion et améliorations possibles .............................................................................................. 28 8. Sitographie......................................................................................................................................... 29
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
6
1. Introduction
Notre projet consiste à utiliser le Gyroscope du Sense Hat afin d’interagir avec la matrice LED 8x8 de celui-ci. Le but étant d’allumer une certaine série de LED en fonction du degré et sens d’inclinaison de notre Raspberry Pi. Pour ce faire nous avons codé l’ensemble de notre algorithme en Python. Pour la réalisation de ce projet, nous avons utilisé le matériel suivant :
- Un Raspberry Pi. - Un module Sense Hat - Une alimentation AC/DC 2.4A - Un câble Ethernet - Un câble TTL - Une carte SD vierge.
Software utilisé :
- OS : Raspbian Jessie with Pixel - Logiciel sur Windows :
o SD formater o Win32DiskImager o MobaXterm (connexion SSH ou Console)
Présentation générale du projet :
- Séparation de la matrice LED en 3 colonnes de 2 pixels de large et séparation entre chaque colonne
- Détection des variations d’orientation selon les axes pitch, roll et yaw - Mouvement d’une série de 2 pixels par colonnes, selon l’évolution des angles - Définition d’un code couleur se rapportant au logo ISIMS trouvé sur Google et HEH campus
technique o Colonne 1 : Orange ISIMS o Colonne 2 : Bleu ISIMS o Colonne 3 : Jaune ISIMS o Séparation : Rouge HEH campus technique
- Affichage de la valeur des angles d’orientation en degrés - Affichage de la valeur des angles d’orientation en radians - Affichage de la température en Celsius sur la matrice LED - Affichage de la température en Fahrenheit sur la matrice LED
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
7
2. Le Sense Hat
2.1. Les capteurs du Sense Hat
o Gyroscope
Le gyroscope permet de mesurer l’orientation du Raspberry Pi. Les valeurs sont reprises en tant qu’angles entre 0 et 360°.
o Capteur de pression et température
Le Sense Hat est également équipé d’un capteur de pression et de température. Celui-ci peut mesurer une pression absolue comprise entre 260 et 1260 HPa avec une précision d’1hPa. Il peut donner la pression atmosphérique en Pascals ou en millibars, ainsi que la température en °C allant de -40 à +120°C. (Le Sense Hat dispose de deux capteurs de température. L’un se trouve avec le capteur de pression atmosphérique, tandis que l’autre avec le capteur d’humidité.)
Figure 1: Le capteur de Pression et d'humidité.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
8
o Centrale inertielle Le LSM9DS1 peut mesurer des accélérations de ±2g/±4g/±8g/±16g, un champ magnétique de ±4/±8/±12/±16 gauss ainsi qu’une vitesse angulaire de ±245/±500/±2000 degrés/seconde. Cette puce contient donc les 3 fonctionnalités suivantes : Gyroscope, accéléromètre, magnétomètre.
Figure 2: L'accéléromètre, le gyroscope, magnétomètre se trouvent à l'arrière de l'image près des
LED
o Capteur d’humidité et de température Notre Sense Hat intègre également un capteur d’humidité avec une sonde de température. Ce capteur permet de fournir le pourcentage d’humidité, mais également la température en degrés centigrades. Celui-ci est assez sensible afin de détecter la vapeur d’eau contenue dans l’haleine humaine permettant de mesurer l’humidité relative de 0 à 100% avec une précision de 4,5% entre 20% et 80% d’humidité relative. Lors de la fabrication, le capteur est calibré et intègre des correcteurs dans des registres internes. De plus, il mesure la température avec une précision de +/- 0,5°C entre 15 et 40°C.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
9
• Autre (Atmel Tiny88) La matrice LED 8x8 ainsi que le joystick est géré par un microcontrôleur Atmel Tiny88
Figure 3: Le microcontrôleur Atmel Tiny88
o La matrice LED 8X8
La matrice LED est pilotée par un pilote de LED courant constant (LED2472G) en combinaison avec l’ATTiny88 qui exécute un firmware qui charge l’affichage 8x8 en RVB avec une résolution de 15bits.
Figure 4: Le circuit LED2772G sous la matrice LED
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
10
3. Installation du Raspberry Pi
3.1. Installation de Raspbian
Pour débuter le projet, nous devons préparer une carte SD de 8 Go qui fera office de disque dur
système pour le Raspberry, avec SDFormatter par exemple.
Suite à une première installation d’un Système Linux sur une carte SD, l’on risque fortement de se
retrouver avec une capacité ne correspondant pas à une carte qui faisait à l’origine plus de 4GB.
Windows ne peut pas voir les partitions Linux. C’est pourquoi formater la carte SD avec SDFormatter
est une étape indispensable.
Figure 5: Capture d'écran de SD Formatter
Ensuite, il faut installer le système d’exploitation, Raspbian sur la carte SD en question. Cette
procédure se fait quasi automatiquement avec Win32DiskImager après avoir téléchargé la dernière
version de l’OS en mode complète, nommée Jessie. En plus, de graver l’image, il nous a également
permis de réaliser des back up’s de notre travail. Afin de pouvoir repartir sur une base fonctionnelle
en cas de problèmes que l’on n’arriverait pas à résoudre.
Figure 6: Capture d'écran de Win32Disk Imager
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
11
3.2. Connexion au Raspberry Pi
3.2.1. Branchement Pour nous connecter au Raspberry Pi, nous avons utilisé une connexion SSH. Ayant plusieurs
problèmes lors de notre connexion au routeur fourni à l’école. Nous avons décidé de nous connecter
au Raspberry Pi à l’aide d’un câble Ethernet branché à un ordinateur portable, qui est configuré en
‘ bridge Ethernet’ afin de nous fournir la connexion internet depuis le wifi de l’ordinateur portable.
Figure 7: Capture d'écran des propriétés Wi-Fi pour le bridge Ethernet sur Windows
Pour cela nous avons édité le fichier « cmdline.txt » qui se trouve dans le dossier « /boot ». Dans
lequel, nous avons ajouté une adresse IP (comprise entre 169.254.0.0 et 169.254.255.255).
3.2.2. Problème : la connexion en mode graphique Le tutoriel pour la connexion au Raspberry-Pi en mode graphique vu au cours était beaucoup trop
long à réaliser (une séance de cours complète, à refaire en partie à chaque fois) et était imparfait : en
mode XRDP, qui était la méthode de connexion finale voulue par le tutoriel, le clavier était en anglais
QWERTY, et impossible à modifier sans d’autres manipulations encore plus longues.
Afin de pallier à ce problème, nous avons réalisé que nous n’avions pas vraiment besoin d’utiliser le
mode graphique de Raspbian et avons donc réalisé tout le reste du projet en utilisant le Raspberry en
mode console via une connexion SSH.
3.2.3. Connexion Pour nous connecter au Raspberry Pi, nous avons besoin d’un logiciel client SSH tel que MobaXterm
ou Putty. Il nous suffit de lancer le programme de notre choix, introduire l’IP du Raspberry et d’entrer
les logs par défaut pour la connexion : « pi » comme username, et « raspberry » comme mot de
passe. La connexion se fait immédiatement en SSH vers le mode console de Rasbpian.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
12
3.3. Configuration du Raspberry Pi
3.3.1. Installation des paquets et mises à jour Le Raspberry-Pi et son système d’exploitation connecté et configurer, il nous faut maintenant
brancher le Sense Hat, puis vérifier que le système soit mis à jour, avec les commandes Debian en
mode console.
sudo apt-get update
sudo apt-get upgrade
Installation du paquet logiciel du Sense Hat ainsi que de Pillow, tel que recommandé par la fondation
Raspberry-Pi, suivi d’un reboot.
sudo apt-get install sense-hat
sudo pip-3.2 install pillow
sudo reboot
3.3.2. Lancement du programme et choix de l’IDE Notre programme a pu être codé sur Windows via un éditeur de texte classique (Notepad ++) et
ensuite émulé via l’application en ligne Trinket afin de réaliser des tests plus rapides.
Côté Raspbian en mode console, il nous suffisait de créer un fichier avec l’extension .py et de l’éditer
avec un éditeur Linux classique tel que Nano.
sudo nano programme.py
Puis de le lancer sur le Sense Hat.
python programme.py
Ensuite, nous installons la dernière version du compilateur Python, ou du moins vérifions sa
présence. Pip et Pygame, par exemple, étant installés par défaut sur Raspbian Jessie, mais pas sur la
version Jessie Lite.
sudo apt-get install python3
Sudo apt-get install python3-picamera
sudo apt-get install python3-pip
sudo apt-get install python-pygame
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
13
4. Programme principal
Pour réaliser ce programme, nous avons commencé par poser le problème à plat en définissant la
liste des tâches demandées. Une fois cette étape effectuée, nous avons décomposé la création de ce
programme, tout d’abord en une partie principale et une partie secondaire.
Afin de faciliter encore plus le travail et les recherches, nous avons, pour chaque partie du
programme, imaginé un plan de travail en définissant clairement les différentes parties du code à
effectuer, dans un ordre logique pour la réalisation de ce projet. Globalement, ces étapes
correspondent à l’ordre dont ce rapport a été écrit.
4.1. Importation des modules
Nous débutons le programme par ces trois lignes, permettant, dans l’ordre d’importer le package du
sense_hat, d’activer son accès, et finalement de remettre à zéro la totalité de la matrice LED.
from sense_hat import SenseHat sense = SenseHat()
sense.clear()
4.2. Définition de la matrice LED
Pour commencer le programme, nous définissons l’affichage de la matrice LED. Cette dernière est un
afficheur au format 8x8 et peut être utilisée de plusieurs manières différentes. Nous avons choisi,
pour notre programme, de la délimiter par défaut et lui donner des couleurs dès le départ en
séparant les colonnes liées aux différents axes par une bande de LED’s rouge, et en laissant les autres
en noir, donc éteintes.
Pour cela, nous créons des variables avec le code couleur au format Red - Green - Blue : la variable
« r » étant pour red, « b » pour black
r = (255,0,0) b = (0,0,0)
Ensuite, on imagine l’affichage.
0 1 2 3 4 5 6 7
0 b b r b b r b b
1 b b r b b r b b
2 b b r b b r b b
3 b b r b b r b b
4 b b r b b r b b
5 b b r b b r b b
6 b b r b b r b b
7 b b r b b r b b
Et on le crée en Python sous forme d’une variable qui contient une liste de liste
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
14
display = [[b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b],
[b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b]]
Le package Sense Hat précédemment importé nous permet d’utiliser la fonction « sense.set_pixels »
qui allume les 64 LED’s de l’affichage selon l’ordre défini. En plus de cette fonction prédéfinie, nous
utilisons la fonction « sum(display,[]) » qui transforme notre liste de liste en une seule liste.
L’affichage prédéfini s’allume sur la matrice du Sense Hat.
sense.set_pixels(sum(display,[]))
4.3. Récupération du mouvement du gyroscope
Toujours grâce à notre package Sense Hat initialisée au début du programme, nous pouvons utiliser
la fonction « sense.get_orientation() » afin de récupérer les données d’inclinaison d’un ou de
plusieurs axes en degrés. Nous allons donc récupérer un premier axe : pitch et stocker la valeur dans
une variable afin de plus facilement l’utilisé par après.
pitch = sense.get_orientation()['pitch']
4.4. Fonction de calcul des axes
Maintenant que l’affichage est défini et le degré d’inclinaison du premier axe dont nous allons nous
occuper est stocké dans une variable, nous devons créer une fonction qui va permettre de définir
dans quelle direction la LED va s’allumer.
Les axes prenant une valeur de 0 à 360 degrés selon l’orientation, il est facilement compréhensible
que le pitch va devoir croître de la valeur « 0 » (le 0 étant quand le Sense Hat est à plat) jusqu’à la
moitié de sa valeur totale, soit 180 pour finalement décroître de 180 à 360 degrés.
Nous allons donc commencer par créer deux variables initialisées à « 0 ». Dans la première sera
stockée la valeur de la case (de 0 à 7) de l’axe x pour pitch, nommé « ap », et dans l’autre la valeur de
l’axe y, que nous pourrons utiliser pour la totalité du programme étant donné que cet axe n’est pas
modifié par l’orientation.
ap = 0 y = 0
Nous créons enfin une fonction qui permet d’augmenter la valeur x de 1 quand le degré d’orientation
est de 1 à 179, puis de le diminuer quand il est de 359 à 181. Ces valeurs seront stockées dans une
variable tampon (new_ap) puis retournées dans la variable finale (ap) via la fonction.
Afin de parer à d’éventuelles erreurs dans le cas où le sol ne serait pas totalement plat (à 0) ou que
les LED’s ne bougent pas au moindre tremblement, nous avons utilisé les valeurs citées au lieu de 0 à
180 et 360 à 180.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
15
def move_pitch(pitch,ap): new_ap = ap
if 1 < pitch < 179 and ap != 0: new_ap -= 1 elif 359 > pitch > 179 and ap != 7 : new_ap += 1
return new_ap
Cette fonction sera ensuite appelée et initialisée dans le programme final.
ap = move_pitch(pitch,ap)
Pour enfin pouvoir enregistrer les valeurs des deux axes, ap et y dans la matrice LED prédéfinie avec
la couleur choisie et stockée dans une variable.
orange = (255,50,0)
display[x][y] = orange
4.5. Allumage des LED’s et du display
Nous créons finalement la boucle principale du programme. Cette dernière sera appelée avec un
While True : c’est donc une boucle infinie étant donné que notre programme doit tourner non-stop
pour récupérer les variations des axes.
• Cette boucle va finalement réaliser les commandes précédemment illustrées :
• Récupération de la valeur de l’axe et stockage dans une variable
• Appel et initialisation dans une variable de la fonction de calcul du mouvement de l’axe
• Modification de l’axe du display en assignant une couleur à une LED
• Appel de l’affichage prédéfini
While True : pitch = sense.get_orientation()['pitch'] ap = move_pitch(pitch,ap) display[ap][y] = orange
sense.set_pixels(sum(display,[]))
4.5.1. Problème : Allumer plusieurs LED’s simultanément Le premier problème rencontré était assez logique : il n’y avait qu’une seule LED sur l’axe y qui
s’allumait… car nous l’avons initialisée à 0, et qu’elle n’est jamais modifiée ailleurs dans le
programme. Il suffit donc, d’au lieu d’utiliser une variable y, de sélectionner manuellement les cases
sur l’axe y qui seront utilisées, soit 0 et 1, 3 et 4 puis 6 et 7.
display[ap][0] = orange display[ap][1] = orange
4.5.2. Problèmes : Éteindre les LED’s Le second problème rencontré lors du test de cette première version du programme est que les LED
s’allument une par une, mais ne s’éteignent jamais. De ce fait, il n’y avait que la première partie de la
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
16
fonction if (de 0 à 7) qui apparaissait sur la matrice. La résolution de celui-ci est simple : il suffit de
reprendre le code d’allumage des LED’s en orange, et de les remettre en black après un court
« sleep » permettant d’avoir une jolie transition entre les états allumé et éteint.
sleep(0.5) display[ap][0] = b
display[ap][1] = b
Pour faire fonctionner le sleep, il faut intégrer le package « time » en début de programme.
from time import sleep
4.6. Duplication des fonctions pour les autres axes
Le programme étant terminé et fonctionnel pour un axe, il faut faire de même pour les deux autres,
roll et yaw, en :
Créant deux nouvelles fonctions (move_roll et move_yaw) ainsi que deux nouvelles variables (ar et
ay) qui contiendront les valeurs des axes roll et yaw.
ar = 0
ay = 0
def move_roll(roll,ar): new_ar = ar if 1 < roll < 179 and ar != 0:
new_ar -= 1 elif 359 > roll > 179 and ar != 7 :
new_ar += 1 return new_ar
def move_yaw(yaw,ay): new_ay = ay if 1 < yaw < 179 and ay != 0: new_ay -= 1 elif 359 > yaw > 179 and ay != 7 : new_ay += 1
return new_ay
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
17
Dupliquant le contenu de la boucle et modifiant les valeurs du pitch par celles des deux autres axes
roll = sense.get_orientation()['roll'] ar = move_roll(roll,ar) display[ar][0] = blue display[ar][1] = blue sense.set_pixels(sum(display,[]))
sleep(0.5) display[ar][0] = b display[ar][1] = b yaw = sense.get_orientation()['yaw'] ay = move_yaw(yaw,ay)
display[ay][6] = yellow display[ay][7] = yellow sense.set_pixels(sum(display,[])) sleep(0.5) display[ay][6] = b display[ay][7] = b
4.7. Programme principal final
Pour la dernière étape, après avoir testé les codes de chacun des axes séparément, il fallait bien
entendu tout mettre ensemble, pour que tout se fasse en même temps, sur le même affichage. Cette
étape semblait triviale, mais une grosse partie du temps de travail a été consacrée au bon
fonctionnement de celle-ci…
Car comme pour le problème avec l’axe y au début, nous utilisions une variable « x » pour le pitch,
variable qui est restée x pour tous les axes au lieu de variables distinctes par axe (ap, ar et ay). Ça
fonctionnait lors des tests de chaque axe distinctement, mais une fois mis ensemble, les fonctions
move_ modifiaient le x constamment dans toutes les directions possible, en même temps, ce qui
corrompait l’entièreté du programme. Une fois cette résolution comprise et appliquée, le
programme a fonctionné directement.
4.7.1. Problème : Plusieurs paires de LED’s clignotent Le programme était fonctionnel, à l’exception que les LED’s des deux derniers axes se sont mise à
clignoter. Pour résoudre ce problème, il a fallu créer, pour chaque axe du programme, une nouvelle
variable temporaire nommée « oldap » et une condition « if » qui vérifie à chaque boucle si la valeur
de ap (pour le premier axe) a été modifiée pour lancer la procédure d’allumage des LED’s. Les
variables temporaires ont dû être initialisées à -1 pour que la condition soit toujours exécutée lors de
la première boucle, car ap, lui, ne vaudra jamais -1.
if oldap != ap: display[ap][3] = orange display[ap][4] = orange display[oldap][3] = b display[oldap][4] = b sense.set_pixels(sum(display,[]))
oldap = ap
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
18
4.8. Code du programme principal
from sense_hat import SenseHat from time import sleep sense = SenseHat() sense.clear() r = (255,0,0) b = (0,0,0) orange = (255,50,0) blue = (0,0,255) yellow = (255,255,0) ar = 0 ap = 0 ay = 0 y = 0 oldar = -1 oldap = -1 olday = -1 display = [[b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b]] def move_roll(roll,ar): new_ar = ar if 1 < roll < 179 and ar != 0: new_ar -= 1 elif 359 > roll > 179 and ar != 7 : new_ar += 1 return new_ar def move_pitch(pitch,ap): new_ap = ap if 1 < pitch < 179 and ap != 0: new_ap -= 1 elif 359 > pitch > 179 and ap != 7 : new_ap += 1 return new_ap def move_yaw(yaw,ay): new_ay = ay if 1 < yaw < 179 and ay != 0: new_ay -= 1 elif 359 > yaw > 179 and ay != 7 : new_ay += 1 return new_ay while True: roll = sense.get_orientation()['roll']
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
19
ar = move_roll(roll,ar) if oldar != ar: display[ar][0] = blue display[ar][1] = blue display[oldar][0] = b display[oldar][1] = b sense.set_pixels(sum(display,[])) oldar = ar pitch = sense.get_orientation()['pitch'] ap = move_pitch(pitch,ap) if oldap != ap: display[ap][3] = orange display[ap][4] = orange display[oldap][3] = b display[oldap][4] = b sense.set_pixels(sum(display,[])) oldap = ap yaw = sense.get_orientation()['yaw'] ay = move_yaw(yaw,ay) if olday != ay: display[ay][6] = yellow display[ay][7] = yellow display[olday][6] = b display[olday][7] = b sense.set_pixels(sum(display,[])) olday = ay sleep(0.5)
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
20
5. Programme secondaire
5.1. Orientations
5.1.1. Utilisation et prise en charge du joystick Sur un Sense Hat, le joystick est mis en correspondance avec les touches du clavier. Ainsi, un appui
sur la touche directionnelle gauche du clavier correspondra à un appui sur le joystick vers la gauche,
et vice-versa. Le clic sur le joystick équivaut, lui, avec la touche « return ». Cette technique est
appelée « Keyboard Mapping », soit « mappage clavier » en français.
Nous utiliserons donc un pilote et le Keyboard Mapping afin de détecter quelle touche est pressée.
Pour ce faire, nous importons et initialisons Pygame.
import pygame from pygame.locals import * pygame.init()
pygame.display.set_mode((640, 480))
Ensuite, nous créons, comme pour la première partie du projet, une boucle principale infinie qui
contient le code de mappage des quatre touches directionnelles du clavier.
while True: for event in pygame.event.get(): if event.type == KEYDOWN: if event.key == K_DOWN: elif event.key == K_UP:
elif event.key == K_RIGHT:
elif event.key == K_LEFT:
5.1.2. Récupération des orientations Nous avons ensuite besoin de récupérer et stocker les valeurs des trois axes. Pour ce faire, nous
réutilisons les fonctions du précédent programme.
pitch = sense.get_orientation()['pitch'] roll = sense.get_orientation()['roll']
yaw = sense.get_orientation()['yaw']
Il suffit ensuite d’effectuer un print de ses trois variables afin de les afficher à l’écran.
print("pitch %s roll %s yaw %s" % (pitch, roll, yaw))
5.1.3. Création d’une boucle et d’un booléen par direction Nous avons la base, il nous faut maintenant créer une boucle afin que le programme détecte quand
une touche est pressée ou non. Pour se faire, il suffit de créer une variable booléenne (valeur soit
True or False) et de l’utiliser dans une boucle qui lancera le programme quand la touche est pressée
(bool à True) et le remettra à False après l’exécution, quand elle n’est pas pressée, pour chaque
condition.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
21
booldroite = True while booldroite == True:
pitch = sense.get_orientation()['pitch'] roll = sense.get_orientation()['roll'] yaw = sense.get_orientation()['yaw'] print("pitch %s roll %s yaw %s" % (pitch, roll, yaw))
booldroite = False
5.1.4. Récupération des orientations en radians Pour faire de même, mais en radians, il suffit d’utiliser la fonction Sense Hat adéquate.
Sense.get_orientation_radians()
Puis de dupliquer la fonction précédente en remplaçant les fonctions de détection de l’orientation,
ainsi qu’en créant une nouvelle variable booléenne pour cette touche.
boolgauche = True while boolgauche == True: pitch = sense.get_orientation_radians()['pitch'] roll = sense.get_orientation_radians()['roll'] yaw = sense.get_orientation_radians()['yaw']
print("pitch %s roll %s yaw %s" % (pitch, roll, yaw)) boolgauche = False
5.1.5. Ajout à la matrice Nous pouvons enfin ajouter ces deux fonctions dans la matrice du joystick, sous les conditions liées
aux touches droite et gauche.
for event in pygame.event.get(): if event.type == KEYDOWN: if event.key == K_DOWN: elif event.key == K_UP: elif event.key == K_RIGHT: booldroite = True while booldroite == True: pitch = sense.get_orientation()['pitch'] roll = sense.get_orientation()['roll'] yaw = sense.get_orientation()['yaw'] print("pitch %s roll %s yaw %s" % (pitch, roll, yaw))
booldroite = False elif event.key == K_LEFT: boolgauche = True while boolgauche == True:
pitch = sense.get_orientation_radians()['pitch'] roll = sense.get_orientation_radians()['roll']
yaw = sense.get_orientation_radians()['yaw'] print("pitch %s roll %s yaw %s" % (pitch, roll, yaw))
boolgauche = False
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
22
5.2. Températures
5.2.1. Récupération de la température Tout comme pour l’orientation, Sense Hat, grâce au package que nous avons importé, dispose d’une
fonction prédéfinie pour récupérer la température. Nous utilisons donc cette fonction, et stockons
son résultat dans une variable « temp ».
temp = sense.get_temperature()
5.2.2. Découpage des chiffres Cette variable retourne un nombre avec beaucoup trop de chiffres insignifiants après la virgule, nous
la coupons donc avec cette fonction issue de Python.
temp = round(temp, 1)
5.2.3. Affichage sur la matrice LED Heureusement pour nous, Sense Hat dispose d’une fonction permettant de diffuser une fois une
chaine de caractère (string) sur la matrice LED.
sense.show_message()
Cette fonction prend deux paramètres : un string, et la couleur voulue du texte. Notre variable temp
est un float, nous la convertissons donc en string grâce à a fonction adéquate, et définissons la
couleur sur rouge afin de rester en adéquation avec le code couleur de la première partie du
programme.
sense.show_message(str(temp), text_colour=[255, 0, 0])
5.2.4. Création d’une boucle et d’un booléen Tout comme pour les touches gauche et droite avec les orientations, nous créons une boucle
booléenne.
boolbas = True while boolbas == True: temp = sense.get_temperature() temp = round(temp, 1)
sense.show_message(str(temp), text_colour=[255, 0, 0]) boolbas = False
5.2.5. Conversion de la température en Fahrenheit L’affichage de la température en Fahrenheit se fait exactement de la même manière, à l’exception
qu’il nous faut convertir la valeur de notre variable temp au bon format grâce à la formule de
conversion.
temp = sense.get_temperature() * 9/5 + 32
5.2.6. Ajout à la matrice Nous ajoutons nos deux nouvelles fonctions à la matrice du joystick sur les touches bas et haut cette
fois.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
23
if event.key == K_DOWN: boolbas = True
while boolbas == True: temp = sense.get_temperature() temp = round(temp, 1) sense.show_message(str(temp), text_colour=[255, 0, 0]) boolbas = False elif event.key == K_UP:
boolhaut = True while boolhaut == True: temp = sense.get_temperature() * 9/5 + 32 temp = round(temp, 1) sense.show_message(str(temp), text_colour=[255, 0, 0])
boolhaut = False
5.3. Création d’une procédure
Le mappage des touches et leurs fonctions étant codées et fonctionnelles, nous transformons cette
boucle en une procédure afin de pouvoir l’intégrée plus facilement par la suite dans notre
programme complet.
Pour se faire, il suffit de supprimer notre boucle infinie et de mettre le mappage dans un def, pour
ensuite l’appeler dans la boucle finale.
def joystick():
joystick()
5.4. Code final commenté
import pygame from pygame.locals import * from sense_hat import SenseHat pygame.init() sense = SenseHat() sense.clear() def joystick(): for event in pygame.event.get(): if event.type == KEYDOWN: if event.key == K_DOWN: boolbas = True while boolbas == True: temp = sense.get_temperature() temp = round(temp, 1) sense.show_message(str(temp), text_colour=[255, 0, 0]) boolbas = False
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
24
elif event.key == K_UP: boolhaut = True while boolhaut == True: temp = sense.get_temperature() * 9/5 + 32 temp = round(temp, 1) sense.show_message(str(temp), text_colour=[255, 0, 0]) boolhaut = False elif event.key == K_RIGHT: booldroite = True while booldroite == True: pitch = sense.get_orientation()['pitch'] roll = sense.get_orientation()['roll'] yaw = sense.get_orientation()['yaw'] print("pitch %s roll %s yaw %s" % (pitch, roll, yaw)) booldroite = False elif event.key == K_LEFT: boolgauche = True while boolgauche == True: pitch = sense.get_orientation_radians()['pitch'] roll = sense.get_orientation_radians()['roll'] yaw = sense.get_orientation_radians()['yaw'] print("pitch %s roll %s yaw %s" % (pitch, roll, yaw)) boolgauche = False while True: joystick()
6. Programme complet
6.1. Fusion des programmes
Une fois les deux parties du programme finies, il suffit de fusionner le secondaire au principal en
ajoutant les packages requis, la procédure du Joystick, et finalement en appelant cette dernière à la
fin de la boucle infinie.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
25
6.2. Code final commenté et structuré
#importation des modules nécessaire à Sense Hat, au Joystick et à la fonction Sleep import pygame from pygame.locals import * from sense_hat import SenseHat from time import sleep #initialisation du module nécessaire pour le mappage du joystick pygame.init() sense = SenseHat() #réinitialise Sense Hat sense.clear() #création des variables contenant les couleurs utilisées dans le programme #r pour rouge, couleur HEH campus technique, b pour black = éteintes #orange blue yellow pour les 3 couleurs de l'ancien logo ISIMS r = (255,0,0) b = (0,0,0) orange = (255,50,0) blue = (0,0,255) yellow = (255,255,0) #création des variables contenant les positions des axes ar = 0 ap = 0 ay = 0 y = 0 #création des variables temporaires nécessaires à la vérification de modification des axes #initialisés à -1 pour que le if se lance toujours au moins une fois oldar = -1 oldap = -1 olday = -1 #création d'une liste de liste qui définit la matrice LED 8x8 avec 3x2 colonnes en black (éteintes) et 2 séparations en rouge, couleur HEH display = [[b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b], [b,b,r,b,b,r,b,b]] #fonction permettant d'incrémenter x quand la valeur du roll en degré est de 1 à 179 et de la diminuer quand elle est de 359 à 181 def move_roll(roll,ar): new_ar = ar if 1 < roll < 179 and ar != 0: new_ar -= 1 elif 359 > roll > 179 and ar != 7 : new_ar += 1
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
26
return new_ar #idem pour le pitch def move_pitch(pitch,ap): new_ap = ap if 1 < pitch < 179 and ap != 0: new_ap -= 1 elif 359 > pitch > 179 and ap != 7 : new_ap += 1 return new_ap #idem pour le roll def move_yaw(yaw,ay): new_ay = ay if 1 < yaw < 179 and ay != 0: new_ay -= 1 elif 359 > yaw > 179 and ay != 7 : new_ay += 1 return new_ay #procédure contenant la matrice joystick def joystick(): for event in pygame.event.get(): if event.type == KEYDOWN: #si joystick bas est pressé, on met le booleen boolbas a true et on lance la boucle if event.key == K_DOWN: boolbas = True while boolbas == True: #récupère la température et découpe le nombre pour ne garder qu'un chiffre après la virgule temp = sense.get_temperature() temp = round(temp, 1) #diffuse le message à l'écran sous forme d un string en rouge sense.show_message(str(temp), text_colour=[255, 0, 0]) #remet le bool à 0 boolbas = False elif event.key == K_UP: boolhaut = True while boolhaut == True: #idem mais avec une formule de transformation Celsius en Fahrenheit temp = sense.get_temperature() * 9/5 + 32 temp = round(temp, 1) sense.show_message(str(temp), text_colour=[255, 0, 0]) boolhaut = False elif event.key == K_RIGHT: booldroite = True while booldroite == True: #récupère les orientations en degrés et les stocke dans des variables pitch = sense.get_orientation()['pitch'] roll = sense.get_orientation()['roll'] yaw = sense.get_orientation()['yaw'] #fais un print à l'écran de ces variables print("pitch %s roll %s yaw %s" % (pitch, roll, yaw)) booldroite = False elif event.key == K_LEFT: boolgauche = True while boolgauche == True:
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
27
#idem mais en radians pitch = sense.get_orientation_radians()['pitch'] roll = sense.get_orientation_radians()['roll'] yaw = sense.get_orientation_radians()['yaw'] print("pitch %s roll %s yaw %s" % (pitch, roll, yaw)) boolgauche = False while True: #récupère l'orientation du roll et la stocke dans une variable roll = sense.get_orientation()['roll'] # stocke le résultat de la fonction précédemment créée dans ar ar = move_roll(roll,ar) #vérifie à chaque boucle si la valeur a changé par rapport à la temporaire. Si oui (valeur différente), on la change. if oldar != ar: display[ar][0] = blue display[ar][1] = blue display[oldar][0] = b display[oldar][1] = b sense.set_pixels(sum(display,[])) oldar = ar #idem pour le pitch pitch = sense.get_orientation()['pitch'] ap = move_pitch(pitch,ap) if oldap != ap: display[ap][3] = orange display[ap][4] = orange display[oldap][3] = b display[oldap][4] = b sense.set_pixels(sum(display,[])) oldap = ap #idem pour le yaw yaw = sense.get_orientation()['yaw'] ay = move_yaw(yaw,ay) if olday != ay: display[ay][6] = yellow display[ay][7] = yellow display[olday][6] = b display[olday][7] = b sense.set_pixels(sum(display,[])) olday = ay #sleep de 0.5 seconde avant de refaire une boucle (défini le temps de réponse entre chaque modification des LED's) sleep(0.5) #appel de la procédure du joystick joystick()
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
28
7. Conclusion et améliorations possibles
Nous avons réussi à interagir avec l’orientation de notre Raspberry Pi et à effectuer le déplacement
de nos LED’s en fonction de son orientation. Mais elles s’éteignent et ne laissent pas une trainée
derrière comme l’image sur la feuille de présentation du projet.
Nous avons également pus réaliser les différentes prises en charge du Joystick qui nous ont été
demandées en supplément, tel que l’affichage des degrés de rotation, affichage de la température
sur la matrice LED 8x8 …
Pour améliorer ce programme, nous pourrions, afin qu’il ressemble encore plus à la photo fournie,
essayer de faire en sorte que les LED’s ne s’éteignent pas instantanément après l’allumage de la case
suivante, mais qu’elles laissent une sorte de trainée, donc qu’une paire reste allumée quand l’autre
s’allume, et ainsi de suite.
Le second point d’amélioration possible est l’optimisation du code et son amélioration. Il doit être
possible de réduire ou de concaténer certaines commandes, ainsi que de créer des procédures pour
les codes des axes dans la boucle afin de les sortir de celle-ci et de rendre le code plus buvable.
De plus, afin de démarrer notre algorithme automatiquement au démarrage du Raspberry Pi, nous
pouvons créer un script qui démarre notre programme au démarrage de ce dernier.
HEH Catégorie technique Projet Raspberry Pi - IMU Initiation aux nano-ordinateurs - Labo Section informatique Thomas DELCAMPE Année académique 2016-2017 Jordan QUICKEN
29
8. Sitographie http://www.circuitbasics.com/how-to-write-and-run-a-python-program-on-the-raspberry-pi/
http://davidbriddock.blogspot.be/2013/06/learn-python-pygame-installation.html
https://www.raspberrypi.org/documentation/linux/software/python.md
https://wiki.mchobby.be/index.php?title=RASP-SENSE-HAT-ASTRO-PI
https://www.sky-future.net/2017/02/22/comment-se-connecter-a-un-raspberry-pi-a-laide-dun-cable-ethernet/
https://www.raspberrypi.org/learning/
https://astro-pi.org/resources/
https://www.raspberrypi.org/learning/astro-pi-guide/
http://mchobby.be/wiki/index.php?title=RASP-SENSE-HAT-ASTRO-PI-D%C3%A9buter
http://www.kubii.fr/1081-raspberry-pi-sense-hat-640522710799.html
https://www.raspberrypi.org/blog/the-sense-hat-headgear-for-the-terminally-curious/
https://www.raspberrypi.org/products/sense-hat/
http://astro-pi.org/hardware/
https://www.raspberrypi.org/blog/astro-pi-tech-specs/
https://www.raspberrypi.org/blog/buy-the-sense-hat-as-seen-in-space/
https://trinket.io/sense-hat