Niveau à bulle numérique Raspberry Pi

Niveau à bulle numérique Raspberry Pi
YouTube video

Dans cet article, nous montrons comment créer un niveau à bulle numérique à l’aide d’un Raspberry Pi et d’un python.

Le code déplace les bulles à l’écran en fonction de l’angle lu par l’IMU.
Pièces utilisées dans ce projet ;

N’importe quel IMU ou TFT peut être utilisé, mais le code devra être mis à jour pour s’adapter aux différents appareils. Il est préférable d’utiliser un TFT 480×320 car les images sont redimensionnées pour s’adapter à cette résolution.

Ce guide suppose qu’une certaine compréhension de base d’un IMU (accéléromètre et gyroscope) est déjà connue. Et vous en avez déjà un qui fonctionne avec votre Raspberry Pi.

Si vous ne le faites pas, nous avons des guides qui couvrent cela.

Accéléromètre gyroscope BerryIMU Raspberry Pi

Nous avons utilisé notre code Python existant pour lire les valeurs de l’IMU, mais nous avons supprimé le code lié au magnétomètre car il n’est pas nécessaire pour ce projet.

Dépôt Git ici
Le code peut être extrait sur votre Raspberry Pi avec ;

pi@raspberrypi ~ $ git clone http://github.com/ozzmaker/BerryIMU.git

Placement de l’IMU

L’IMU peut être fixée n’importe où, mais il est préférable de la placer dans la même orientation que celle illustrée ci-dessous. Si vous modifiez l’orientation, vous devrez mettre à jour le code en conséquence.

espritNiveau1-600

Pygame

Pygame est utilisé pour afficher les images sur le TFT, donc la première tâche à faire est d’installer pygame.

pi@raspberrypi ~ $ sudo apt-get install python-pygame

Nous pouvons maintenant mettre à jour notre code IMU et lui dire d’utiliser pygame pour afficher les images.
Les prochains morceaux de code peuvent être ajoutés n’importe où avant la boucle principale.

Importez le framework pygame dans le code ;

import pygame

Nous définissons ensuite notre mode d’affichage pour obtenir une surface (écran) sur laquelle nous allons dessiner. Et nous obtenons également les dimensions de la surface qui seront utilisées pour indiquer à pygame quelle zone doit être mise à jour.

screen = pygame.display.set_mode ( ( 480,320 ))				#Set display mode
screen_rect = screen.get_rect()								#Get the rectangular area of the screen Surface

Nous pouvons maintenant initialiser pygame. Cependant, avant de faire cela, nous devons spécifier où nous voulons que la sortie soit affichée. Cela peut être fait en définissant la variable d’environnement SDL_FBDEV.

os.putenv('SDL_FBDEV', '/dev/fb1')		#Set the display to fb1, which is the small TFT
pygame.display.init()				#Initialise pygame.  	

Nous pouvons alors charger les images.

#Load images and convert to the correct format. Alpha is needed for PNGs to preserve alpha channel
img_background = pygame.image.load ( "spirit-level-background.jpg" ).convert()
img_Hbubble = pygame.image.load ( "spirit-level-Hbubble.png" ).convert_alpha()
img_Vbubble = pygame.image.load ( "spirit-level-Vbubble.png" ).convert_alpha()
img_Cbubble = pygame.image.load ( "spirit-level-Cbubble.png" ).convert_alpha()
img_overlay = pygame.image.load ( "spirit-level-overlay.png" ).convert_alpha()
#These images are used when only displaying the horizontal bar
img_background_H_only = pygame.image.load ( "spirit-level-H-only-background.jpg" ).convert()
img_Hbubble_H_only = pygame.image.load ( "spirit-level-H-only-bubble.png" ).convert_alpha()	
img_overlay_H_only = pygame.image.load ( "spirit-level-H-only-overlay.png" ).convert_alpha()

Le curseur de la souris est également désactivé

pygame.mouse.set_visible(False)								#Disable the mouse cursor

Afficher les images sur le TFT
L’affichage des images à l’écran peut être effectué en écrasant les images à la surface. L’ordre est important car nous voulons que l’arrière-plan soit réellement en arrière-plan.

Les deuxièmes valeurs dans les fonctions ci-dessous sont les coordonnées X et Y de l’endroit où nous blitons les images sur la surface. Changer les valeurs de hBposition, vBposition cBposition est la façon dont nous déplaçons les bulles.

screen.blit(img_background, screen_rect)							
screen.blit(img_Hbubble, hBposition)							
screen.blit(img_Vbubble, vBposition)							
screen.blit(img_Cbubble, cBposition)
screen.blit(img_overlay, screen_rect)

Et enfin, nous retournons la surface pour que le TFT soit mis à jour

pygame.display.flip()	

Bouger les bulles !

Nous pouvons facilement déplacer les bulles en utilisant les angles renvoyés par l’IMU.

Cela peut être fait en redimensionnant les valeurs d’un angle, qui sont ensuite utilisées pour déplacer les bulles sur l’écran.

Regardons l’angle X qui est représenté sur l’écran comme la barre horizontale inférieure dans l’image ci-dessous.

Le tableau hSlideLimit stocke la limite gauche et la limite droite de l’endroit où la bulle peut se déplacer. Celles-ci correspondent aux coordonnées X de l’affichage. La bulle horizontale ne peut se déplacer qu’entre 62 et 252.

Niveau à bulle Raspberry Pi

Les valeurs de l’axe X de -90 à +90 de l’IMU seront représentées par la bulle du bas.
Cela signifie que nous devons convertir la plage de ;
-90 à +90 (0 est le centre)
à
61 à 252 (95 est le centre)

Cela peut être fait avec la fonction ci-dessous.

hSlideLimit = [62,252]
angleLimit  = 90
def scaleH(value):
	min = -angleLimit
	max = angleLimit
	minScale = hSlideLimit[0]
	maxScale = hSlideLimit[1]
	scaled = minScale + (value - min)/(max-min) * (maxScale - minScale)
	return scaled

min et max sont la plage que nous accepterons de l’IMU, qui se situe entre -90 et +90
micScale et maxScale sont les valeurs vers lesquelles nous voulons les convertir.
La fonction renvoie alors la nouvelle valeur mise à l’échelle.

Voici le code que nous utilisons pour appeler la fonction ci-dessus ;

newHvalue = int(scaleH(CFangleX))
hBposition = (newHvalue,244)
screen.blit(img_Hbubble, hBposition)

Nous passons CFangleX à scaleH(). Et nous stockons la valeur renvoyée dans newHvalue.
Nous tapons également cast comme int car une valeur à virgule flottante sera renvoyée et nous avons besoin d’un nombre entier à tracer sur l’affichage.
hBposition est mis à jour avec la nouvelle valeur horizontale. 244 ne change jamais pour cette bulle car il s’agit de la position Y de la bulle sur l’écran.
La bulle s’affiche ensuite à l’écran avec les nouvelles coordonnées.

Deux modes d’affichage différents
Il existe deux modes d’affichage différents.
Si l’angle de Y est supérieur à 70 ou inférieur à -70, nous n’affichons que la grande barre horizontale. Sinon, nous montrons les trois.

if CFangleY > 70 or CFangleY < -70:

Filtre passe bas

Nous utilisons un filtre passe-bas pour réduire le bruit. Cela empêchera les bulles de rebondir, mais cela ajoutera un peu de retard dans le mouvement. Ce délai rend également les bulles plus réalistes lorsqu’elles se déplacent. Plus le facteur de filtre passe-bas (LPF_FACT0R) est faible, moins il y a de bruit et plus le retard est important.
Le filtre est appliqué aux valeurs brutes de l’accéléromètre et doit être appliqué juste après la lecture des valeurs de l’accéléromètre.

#Apply low pass filter to reduce noise
ACC_LPF_FACTOR = 0.05
ACCx =  ACCx  * ACC_LPF_FACTOR + oldXAccRawValue*(1 - ACC_LPF_FACTOR);
ACCy =  ACCy  * ACC_LPF_FACTOR + oldYAccRawValue*(1 - ACC_LPF_FACTOR);
ACCz =  ACCz  * ACC_LPF_FACTOR + oldZAccRawValue*(1 - ACC_LPF_FACTOR);
oldXAccRawValue = ACCx;
oldYAccRawValue = ACCy;
oldZAccRawValue = ACCz;