On s’intéresse ici à un dispositif de contrôle original. On va se faire plaisir en utilisant le Nunchuck, une manette de la console de jeu Nintendo Wii.
Il ne s’agit pas de la manette principale Wiimote (décrite dans cet article) mais d’un périphérique qui s’y connecte via un câble. En tant que tel, il est donc beaucoup plus simple, mais au vu de toutes les innovations dont il est doté, c’est déjà un bond en avant dans les dispositifs de télé-commande classique, qui se limitaient jusqu’ici à des boutons et une croix directionnelle à 8 directions .
Jugez plutôt : pour 15 euros, on trouve :
une croix analogique à 2 axes
un accéléromètre à 3 axes
deux boutons judicieusement placés sous l’index et le majeur
Les usages sont multiples, mais on peut imaginer le sketch suivant, basé sur le robot Pobot Easy muni d’une pince Easyrobotics à 2 degrés de liberté :
un bouton pour prendre la main sur le robot autonome (activer le nunchuck ou revenir au programme autonome)
un bouton "panique" pour revenir à une situation stable (arrêt du robot, ouverture de la pince, position repliée)
la croix analogique pour piloter les déplacements (un axe pour la vitesse, un axe pour l’angle, en déplacement polaire)
l’accéléromètre pour piloter la pince : monter le nunchuck pour monter la pince, pivoter le nunchuck pour ouvrir la pince, en l’utilisant en gravitomètre (une simple rotation lente donnant les mêmes résultats qu’une translation brève) et en utilisant les mouvements rapides pour des enchainements (lancer le nunchuck en avant ferme rapidement la pince) permettant de jouer aussi sur la vitesse.
Exemple d’utilisation pour le Mario Chuck :
Mario Chuck first demonstration from JulienPobot on Vimeo.
Faisabilité technique
Le matériel
L’avantage des périphériques Wii (et les ingénieurs de Nintendo sont bénis pour leur bonne idée) est d’utiliser des protocoles standards qu’on peut donc facilement reprendre et qu’on trouve déjà dans d’autres produits électroniques standards.
Ainsi le Nunchuck utilise le protocole I2C (ou TWI) qu’on retrouve dans beaucoup de capteurs et d’actionneurs en robotique, car issu de l’électronique grand public (magnétoscopes Philips au départ, puis un peu partout pour faire communiquer entre eux plusieurs circuits intégrés). Un inventaire des commandes I2C que le Nunchuck peut comprendre a été dressé par les passionnés, et de nombreuses bibliothèques de code sont disponibles pour les différents programmes électroniques courants.
Reste la connexion... mais là encore, vous n’êtes pas au bout de vos surprises :
- la prise a un interstice de l’épaisseur d’une carte électronique standard
- un adaptateur permet de récupérer les 4 signaux sur un connecteur standard 2,54 mm
Voici quelques images :
Le logiciel
On ne change pas une équipe qui gagne : depuis quelques mois, le prototypage rapide de nos ateliers est mené sur des cartes Arduino. On va donc très naturellement utiliser une carte Arduino, et cerise sur le gâteau, le génial Tod E. Kurt, concepteur - entre autres - du petit connecteur adaptateur, a choisi un ordre bien précis pour les signaux I2C, permettant d’utiliser directement sur le connecteur femelle de l’Arduino.
Pour se simplifier la vie, on va utiliser une librairie. Il en existe plusieurs :
celle de WindMeadow
celle de Tod
celle de Growdown
En fait, à la base c’est le même reverse engineering de WM, donc j’ai classié les solutions par ordre chronologique. On va logiquement utiliser la toute dernière :) qui a l’avantage d’avoir les honneurs du playground Arduino : http://www.arduino.cc/playground/Ma...
Voici un exemple d’utilisation :
#include "Wire.h"
#include "WiiChuck.h"
WiiChuck chuck = WiiChuck();
int valX = 0;
int valY = 0;
void setup() {
// alimentation du nunchuck (pas nécessaire de comprendre)
DDRC |= _BV(PORTC3) | _BV(PORTC2); // pattes Analog 2 et 3 en sortie
PORTC &=~ _BV(PORTC2); // patte Analog 2 à 0v
PORTC |= _BV(PORTC3); // patte Analog 3 à 5v
// NOTE : les variables PC2 et PC3 sont devenues PORTC2 et PORTC3 avec les nouvelles Arduino
// donc essayez l'un ou l'autre des noms selon votre carte.
delay(100); // une petite attente
//
Serial.begin(19200);
chuck.begin();
chuck.update();
}
void loop() {
delay(200);
chuck.update();
// lecture des valeurs du joystick 2D
valX = chuck.readJoyX();
valY = chuck.readJoyY();
// affichage
Serial.print(valX);
Serial.print(" ");
Serial.print(valY);
Serial.println();
}
Réalisation
Voici ce qu’on voit à l’oscilloscope processing :
L’affichage des valeurs c’est déjà bien, mais piloter des servomoteurs ce serait plus... visuel ! alors c’est parti. On va utiliser la bibliothèque officielle pour piloter les servos (attention, que 2 sur les pattes 9 et 10, pour plus de servos il faut utiliser une autre bibliothèque, qu’on peut trouver dans le Playground, comme SoftwareServo). Pour plus de fun, on va faire bouger une pince Easyrobotics à 2 degrés de liberté. Il y en a justement une qui est arrivée chez moi ce matin...
Le code spécifique au servo est très simple :
#include "Servo.h"
Servo servBras;
Servo servPince;
...
void setup()
{
...
//
servBras.attach(10);
servPince.attach(9);
servBras.write(90); // valeur milieu
servPince.write(90); // valeur milieu
}
void loop()
{
...
// lecture des valeurs du joystick 2D pour rappel
valX = chuck.readJoyX();
valY = chuck.readJoyY();
...
servBras.write(90+valX/2); // on divise par 2 la valeur reçue pour moins d'amplitude et plus de précision
servPince.write(90+valY/2);
}
Et une petite vidéo :
Nunchuck Wii makes move robotics arm with grip from JulienPobot on Vimeo.
Lisser les valeurs de l’accéléromètre
On va maintenant mettre en place un algorithme permettant de lisser la valeur de l’accéléromètre. Tout d’abord, on ne va pas utiliser les valeurs brutes des 3 axes mais les convertir en angles "roll" et "pitch".
Cette conversion est fournie par une librairie Arduino.
/**
* Nunchuck -- Use a Wii Nunchuck
* Tim Hirzel http://www.growdown.com
*/
// returns roll degrees
int readRoll() {
return (int)(atan2(readAccelX(),readAccelZ())/ M_PI * 180.0);
}
// returns pitch in degrees
int readPitch() {
return (int) (acos(readAccelY()/RADIUS)/ M_PI * 180.0); // Radius = 210
}
Voici tout d’abord ce qu’on obtient sans filtre.
Filtre PID
On va asservir une valeur "filtre" sur la valeur réelle, et on va utiliser un asservissement PID pour que notre valeur "filtre" suive la consigne donnée par la valeur réelle.
Voici le résultat de quelques tests :
Intéressant mais pas très utile finalement.
Filtre moyenne
En fait, le plus simple est de faire un effet retard en considérant comme valeur "filtre" la moyenne des n dernières valeurs réelles. Le choix de n influera sur la rapidité du filtre.
Voici ce que ça donne : c’est très satisfaisant et ça évitera que le nunchuck ne soit trop réactif.
Autres vidéos d’un Nunchuck
Des vidéos d’autres réalisations (non-Pobot) :
Et une réalisation complète avec un robot humanoïde Robonova :