In questi giorni ho trovato in rete un paio di video dove gli “attori” utilizzavano il nunchuck della wii per comandare servomotori o semplici macchinine, allora mi sono chiesto come fanno. La risposta è semplice, il nunchuck comunica tramite protocollo I2C e guarda caso l’arduino tramite la libreria wire è in grado di utilizzare questo protocollo.

Mi sono subito precipitato a comprare un nunchuck (da gamestop, uno compatibile costa 15€).

Tramite questa guida: http://www.windmeadow.com/node/42 , sono riuscito a fare gli opportuni collegamenti.

Il codice presente sul sito però non mi dava la possibilità di controllare i servomotori quindi ho dovuto scrivere qualche parte del codice.

Ecco il link del video su youtube: 

Nunchuck & Arduino UNO, seconda puntata

Ed ecco il link del primo video: http://www.youtube.com/watch?v=Ci4n1VxAnRY

Il nunchuck dispone di un joypad, due pulsanti (C e Z) e di un accellerometro.

Il joypad comanda direttamente i servo su tutti e due gli assi, il pulsante C accende un semplice LED ed il pulsante Z, se premuto, permette di pilotare i servo tramite l’accellerometro.

Di seguito riporto il codice:

#include <Wire.h>
#include <string.h>
/*Come collegare i 4 fili del Nunchuck:
Bianco: Massa
Rosso: +3.3V oppure +5V
Verde: Data -> A4
Giallo: Clock -> A5
*/
#include <Servo.h>
Servo servo_orizzontale;
Servo servo_verticale;
int posor = 90;
int posve = 90;
long wait = 0;
long waitservo = 0;
#undef int
#include <stdio.h>
uint8_t outbuf[6]; // array to store arduino output
int cnt = 0;
int ledPin = 13;
int led = 8;
int joy_x_axis = 0;
int joy_y_axis = 0;
int accel_x_axis = 0;
int accel_y_axis = 0;
int accel_z_axis = 0;
int z_button = 1;
int c_button = 1;
void
setup ()
{
pinMode(led, OUTPUT);
servo_orizzontale.attach(3);
servo_orizzontale.write(posor);
servo_verticale.attach(5);
servo_verticale.write(posve);
Serial.begin (19200);
Serial.print (“Finished setup\n”);
Wire.begin (); // join i2c bus with address 0x52
nunchuck_init (); // send the initilization handshake
}
void
nunchuck_init ()
{
Wire.beginTransmission (0x52); // transmit to device 0x52
Wire.send (0x40); // sends memory address
Wire.send (0x00); // sends sent a zero.
Wire.endTransmission (); // stop transmitting
}
void
send_zero ()
{
Wire.beginTransmission (0x52); // transmit to device 0x52
Wire.send (0x00); // sends one byte
Wire.endTransmission (); // stop transmitting
}
void
loop ()
{
if (wait < millis()){
wait = millis() + 100;
Wire.requestFrom (0x52, 6); // request data from nunchuck
while (Wire.available ())
{
outbuf[cnt] = nunchuk_decode_byte (Wire.receive ()); // receive byte as an integer
digitalWrite (ledPin, HIGH); // sets the LED on
cnt++;
}
// If we recieved the 6 bytes, then go print them
if (cnt >= 5)
{
print ();
}
cnt = 0;
send_zero (); // send the request for next bytes
}
//Comando led con il pulsante C
if (c_button == 0){
digitalWrite(led, HIGH);
}
else if (c_button == 1){
digitalWrite(led, LOW);
}
//Comando servomotori
if (z_button == 1){
if (waitservo < millis()){
waitservo = millis() + 10;
//Servo orizzontale
posor = map(joy_x_axis, 0, 255, 0, 180);
servo_orizzontale.write(posor);
//Servo verticale
posve = map(joy_y_axis, 0, 255, 0, 180);
servo_verticale.write(posve);
}
}
else if (z_button == 0){
if (waitservo < millis()){
waitservo = millis() + 10;
//Servo orizzontale
posor = map(accel_x_axis, 300, 700, 0, 180);
servo_orizzontale.write(posor);
//Servo verticale
posve = map(accel_y_axis, 300, 700, 0, 180);
servo_verticale.write(posve);
}
}
}
// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits.  That is why I
// multiply them by 2 * 2
void
print ()
{
joy_x_axis = outbuf[0];
joy_y_axis = outbuf[1];
accel_x_axis = outbuf[2] * 2 * 2;
accel_y_axis = outbuf[3] * 2 * 2;
accel_z_axis = outbuf[4] * 2 * 2;
z_button = 0;
c_button = 0;
// byte outbuf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if ((outbuf[5] >> 0) & 1)
{
z_button = 1;
}
if ((outbuf[5] >> 1) & 1)
{
c_button = 1;
}
if ((outbuf[5] >> 2) & 1)
{
accel_x_axis += 2;
}
if ((outbuf[5] >> 3) & 1)
{
accel_x_axis += 1;
}
if ((outbuf[5] >> 4) & 1)
{
accel_y_axis += 2;
}
if ((outbuf[5] >> 5) & 1)
{
accel_y_axis += 1;
}
if ((outbuf[5] >> 6) & 1)
{
accel_z_axis += 2;
}
if ((outbuf[5] >> 7) & 1)
{
accel_z_axis += 1;
}
Serial.print (joy_x_axis, DEC);
Serial.print (“\t”);
Serial.print (joy_y_axis, DEC);
Serial.print (“\t”);
Serial.print (accel_x_axis, DEC);
Serial.print (“\t”);
Serial.print (accel_y_axis, DEC);
Serial.print (“\t”);
Serial.print (accel_z_axis, DEC);
Serial.print (“\t”);
Serial.print (z_button, DEC);
Serial.print (“\t”);
Serial.print (c_button, DEC);
Serial.print (“\t”);
Serial.print (“\r\n”);
}
// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char
nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}
Nunchuck & Arduino
Tags:                                 
  • ehi, compare, mi sono arrivati i pezzi, ed ho provato, però ho 2 problemini:
    -è normale che il led si accenda cliccando i pulsanti (perchè si accende con entrambi)?
    -perchè quando ci collego pure i servo, la connessione usb, se ne va ogni  secondo e poi ritorna, ed i servo fanno ciò che vogliono?

    grazie ;)

    • ho fatto altri test, e diciamo che il problema non si verifica più quando il servo è uno solo, lo fa solo quando sono entrambi, a questo punto credo sia un problema di assorbimento, che posso risolvere con alim. esterna

      resta la questione del led comunque…

      • Anonimo

        Per i servo ovviamente serve un’alimentazione esterna. Come hai detto tu è un problema di assorbimento! Per quanto riguarda il led, dovrebbe accendersi solo con il pulsante C

        • forse il nunchuck cinese non ha i collegamenti perfetti xD, sulla seriale, mi da dei pulsanti entrambi rilasciati “1   1”, uno dei due cliccato “1  0”, l’altro cliccato “0   0″…
          se è solo un problema del cavolo, mi basta modificare il filo di com tra i pulsanti sul nunchuck ed è risolto :P cmq io a differenza tua l’ho preso 6 euro e qualcosa, sped gratis… xD

          • Anonimo

            Se intendi che per NON premuto ti da 1, non significa che è un problema! Il nunchuck restituisce il valore 1 per NON premuto e 0 per premuto.

          • si, questo l’avevo capito da solo xD, però se premo c mi da “1  0”, se premo z, credo dovrebbe dare “0  1” invece da “0  0″…

          • Anonimo

            Fai qualche altra prova selezionando solo i bit dei pulsanti!
            Il bit 0 del 6° byte è il valore di Z mentre il bit 1 del 6° byte è il valore di C.

          • non ho capito o_o

          • Anonimo

            Fa per esempio:

            if (z_button == 0)
            digitalwrite(LED1, HIGH);
            else
            digitalwrite(LED1, LOW);

            e lo fai anche con il pulsante C.

            Un’altra soluzione potrebbe essere che non funziona bene il Nunchuck.

          • siamo dinuovo li u.u, quando clicco il pulsante z e come se assieme cliccassi anche il pulsante c u.u

          • Anonimo

            Sarà un problema del Nunchuck allora!

          • eheh è qll che sostendo dall’inizio xD

  • V_mc_113

    Hello, thahts nice, wich version programa have you used? it doesn’t works on mine 1.0, give lots of errors. Grazie

    • Xfox1

      I used version 0022.
      Try to tell me the errors.

      • V_mc_113

        Oh, thanks to write me, thats the problem and I don’t know pretty anything about program…
        H:arduino-0022librariesstring/string.h:114: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:117: error: ‘size_t’ does not name a typeH:arduino-0022librariesstring/string.h:120: error: ‘size_t’ does not name a typeH:arduino-0022librariesstring/string.h:137: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:138: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:156: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:157: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:164: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:165: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:166: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:179: error: ‘size_t’ has not been declaredH:arduino-0022librariesstring/string.h:180: error: ‘size_t’ has not been declaredIn file included from H:arduino-0022hardwarearduinocoresarduino/WProgram.h:5,                 from sketch_may08a.cpp:10:H:arduino-0022librariesstring/string.h:191: error: expected declaration before ‘}’ tokenThank you.

        • Xfox1

          Probably a mistake to regard the library string (this is obvious). I do not know what could be!
          Try asking on the official forum: http://arduino.cc/forum/index.php

  • Igor

    Salve,il link:http://www.windmeadow.com/node/42
    non funziona:(
    potete aiutarmi con i collegamenti?
    grazie in anticipo.