Adaptateur Nintendo NunChuk
Ce tutoriel explique comment mettre en œuvre un adaptateur Grove pour manette Nintendo NunChuk.
Description
La NunChuk est une manette supplémentaire venant se connecter à la WiiMote (une manette destinée à être utilisée pour la console Nintendo Wii). Elle comporte :
- Un joystick 2 axes (x, y)
- Un accéléromètre 3 axes (x, y, z)
- Des boutons poussoirs (C et Z)
Elle communique en liaison I2C avec la WiiMote.
L’adaptateur NunChuk Grove :
Crédit image : Seeed Studio
Matériel requis
- Une carte d’extension de base Grove
- La carte NUCLEO-WB55
- Un module adaptateur Nintendo NunChuk Grove
Branchez le module à un connecteur I2C du Grove Base Shield.
Le code MicroPython
Vous pouvez télécharger les scripts MicroPython de ce tutoriel (entre autres) en cliquant ici.
Etape 1 : Pour faire fonctionner le programme nous devons dans un premier temps importer 3 bibliothèques au tout début de notre code de cette façon :
from machine import I2C, Pin
from time import sleep_ms
from wiichuck import WiiChuck
Etape 2 : Ensuite il faut les initialiser en rajoutant ces lignes de codes. La première ligne précise quel canal I2C nous utiliserons (dans notre cas le canal 1). La deuxième ligne de code définit une variable wii qui récupèrera les informations retournées par la bibliothèque.
i2c = I2C(1)
# Pause d'une seconde pour laisser à l'I2C le temps de s'initialiser
time.sleep_ms(1000)
wii = WiiChuck(i2c)
Etape 3 : Enfin nous affichons les informations retournées par la manette sous forme de tableau. Celui-ci sera affiché dans notre terminal au sein d’une “boucle infinie” ([CTRL]-[C] pour l’interrompre).
while True:
direction = ''
if wii.joy_up:
direction = 'Haut'
elif wii.joy_down:
direction = 'Bas'
elif wii.joy_right:
direction = 'Droite'
elif wii.joy_left:
direction = 'Gauche'
else:
direction = '-----'
if(wii.c):
Cbutton = 'C'
else:
Cbutton = '-'
if(wii.z):
Zbutton = 'Z'
else:
Zbutton = '-'
print("Joystick: (%3d, %3d) %6s \t| Accelerometre XYZ: (%3d, %3d, %3d) \t| Boutons: %s %s" %(wii.joy_x, wii.joy_y, direction, wii.accel_x, wii.accel_y, wii.accel_z, Cbutton, Zbutton))
wii.update()
sleep_ms(100)
Résultat
Et voilà ! Nous pouvons à présent observer le résultat avec les données extraites du NunChuk sous cette forme :
Si vous faites un mouvement avec le NunChuk les valeurs de l’accéléromètre varient selon les axes de son déplacement. Vous pouvez également faire bouger le joystick et voir où celui-ci se situe. De plus vous avez un retour d’informations sur l’état des boutons poussoirs.
Pour aller plus loin
Dans cet exercice nous avons vu l’affichage des données du NunChuk. Pour aller plus loin nous pouvons, par exemple, récupérer ces données et les traiter pour activer des servomoteurs et moteurs en fonction de la direction du joystick.
Le but ici est de récupérer le déplacement du joystick sur l’axe horizontal (axe x) et faire tourner un servomoteur de façon très précise. Nous utiliserons également l’axe vertical (axe y) pour faire tourner un autre moteur à courant continu dans un sens ou dans l’autre.
Ce code peut nous servir de base si on souhaite créer un véhicule capable de se déplacer avec des moteurs à courant continu pour le faire avancer/reculer et un servomoteur pour contrôler sa direction.
Montage
On reprend le montage précédent avec la manette auquel ajoute un servomoteur et un moteur. Si vous n’avez pas encore abordée la partie sur le servomoteur et le moteur je vous invite à les consulter afin de mieux comprendre cet exercice.
Le câblage entre le servomoteur et la carte NUCLEO-WB55 est le suivant :
Servomoteur | ST Nucleo |
---|---|
Signal | D6 |
GND | GND |
3.3V | 3.3V |
La câblage entre le moteur et la carte NUCLEO-WB55 est le suivant :
Driver moteur | ST Nucleo | Moteur | Alim externe |
---|---|---|---|
Enable 1 | D1 | ||
Input 1 | D0 | ||
Output 1 | Oui | ||
GND | GND | GND | |
GND | |||
Output 2 | Oui | ||
Input 2 | D2 | ||
VS | 5V |
Afin de fournir la puissance adéquate aux moteurs on les alimente avec, par exemple, une batterie ou une pile.
Le code MicroPython
Vous pouvez télécharger les scripts MicroPython de ce tutoriel (entre autres) en cliquant ici.
Etape 1 : Pour faire fonctionner le programme nous devons dans un premier temps importer 4 bibliothèques au tout début de notre code de cette façon :
import pyb
from machine import I2C
from time import sleep_ms
from wiichuck import WiiChuck
from pyb import Pin, Timer
import math
Etape 2 : On initialise ensuite la connexion avec le servomoteur sur le port D6 auquel on applique une fréquence de 50Hz (soit une période de 20 ms) provenant du timer 1 sur le canal 1. On configure les pattes du driver moteur et applique une fréquence de 1000 Hz provenant du timer 2 canal 3. On initialise la liaison I2C avec la manette en précisant quel canal nous utilisons (dans notre cas le canal 1). Enfin on définit une variable wii qui récupèrera les informations retournées par la bibliothèque.
# Initalisation servomoteur (Timer 1 channel 1, fréquence = 50 Hz)
servo = pyb.Pin('D6')
tim_servo = pyb.Timer(1, freq=50)
# Driver moteur ("enable" + "input 1" et "input 2" en sorties)
motor_enable = pyb.Pin('D1')
motor_pin1 = pyb.Pin('D0', Pin.OUT_PP)
motor_pin2 = pyb.Pin('D2', Pin.OUT_PP)
motor_pin1.low()
motor_pin2.low()
# PWM pour le moteur (Timer 2 channel 3, fréquence = 1kHz et sur "enable")
tim2 = Timer(2, freq=1000)
ch3 = tim2.channel(3, Timer.PWM, pin=motor_enable)
# PWM pour régler la tension du moteur
ch3.pulse_width_percent(0)
# Initialisation Nunchuk en I2C
i2c = I2C(1)
sleep_ms(1000)
wii = WiiChuck(i2c)
Etape 3 : Nous utilisons une boucle infinie qui nous permettra de contrôler le servomoteur en continu. L’axe X du joystick peut avoir des valeurs comprises entre -100 (orienté à gauche) et 100 (orienté à droite) tandis que le pulse_width_percent du servomoteur n’accepte que des valeurs comprises entre 2,5 et 12,5. Il faut donc trouver un rapport entre les deux. Pour un angle total plus petit que 180° on augmente la valeur du Joystick de +200 afin que toutes les valeurs deviennent positives et on divise le tout par 27. De cette façon si on reprend les calculs avec la formule suivante :
pulse_width_percent = (wii.joy_x + offset) / x
Avec nos valeurs on obtient :
- Minimum : (-100 + 200) / 27 = 3,7% –> soit proche de 2,5% qui correspond à un angle de -90°
- Medium : (0 + 200) / 27 = 7,4% –> soit proche de 7,5% qui correspond à un angle de 0°
- Maximum : (100 + 200) / 27 = 11,1% –> soit proche de 12,5% qui correspond à un angle de 90°
Enfin vous l’avez compris, modifier ce calcul permettra de modifier les angles d’inclinaison du servo-moteur.
Dans notre cas nous avons fait exprès d’avoir des extrema moins importants que les vrais extrema car, avec la précision du calcul, le servomoteur peut se retrouver en butée d’un côté mais pas de l’autre. Cependant voici la formule si vous voulez essayer un angle (presque parfait) de 180° :
(wii.joy_x + 150) / 20
Et si on reprend les calculs on obtient :
- Minimum : (-100 + 150) / 20 = 2,5%
- Medium : (0 + 150) / 20 = 7,5%
- Maximum : (100 + 150) / 20 = 12,5%
Pour revenir à notre code :
while True:
# Si mouvement sur l'axe X alors fait tourner le servo
joystick_x = (wii.joy_x + 200)/27
tim_servo.channel(1, pyb.Timer.PWM, pin=servo, pulse_width_percent=joystick_x)
Etape 4 : Toujours dans la boucle while on contrôle le moteur avec l’axe y du joystick. Pour rappel l’axe renvoie une valeur comprise en -100 au minimum, 100 au maximum et environ 0 au repos. Si celui ci est poussé vers le bas alors on active la sortie input 1 et on lit la valeur de l’axe y. Dans ce cas là cette valeur est comprise entre 0 et -100. Afin de la ramener de 0 à 100 on prend sa valeur absolue. On procède de même si on pousse le joystick vers le haut ; on active la sortie input 2 sans besoin cette fois-ci de valeur absolue. Enfin, au repos, on arrête tout.
# Si mouvement sur l'axe Y
if(wii.joy_y < -5): #Vers le bas
motor_pin1.high()
motor_pin2.low()
ch3.pulse_width_percent(abs(wii.joy_y))
elif(wii.joy_y > 5): #Vers le haut
motor_pin1.low()
motor_pin2.high()
ch3.pulse_width_percent(wii.joy_y)
else: #Au repos
motor_pin1.low()
motor_pin2.low()
ch3.pulse_width_percent(0)
wii.update()
Résultat
Vous êtes maintenant en mesure de contrôler un servomoteur et un moteur à l’aide du joystick d’une manette Wii de façon assez simple. A partir de cette base vous pouvez même concevoir un mini-véhicule capable de se déplacer à droite ou à gauche par le joystick en utilisant le servomoteur relié à un axe de direction des roues. Si vous souhaitez continuer l’exercice vous pouvez par exemple câbler un deuxième moteur et le programmer de la même manière que nous venons de l’expliquer.