Gen 07 2013

Arduino + Nunchuck

Category: TecnologiaAntonio @ 17:50


Purtroppo non ho la Nintendo Wii, ma può darsi che prima o poi non resisterò a comprarne una…

Nel frattempo ho comprato il controller Nunchuck della Wii perché avevo scoperto in rete che “parla” su una TWI (two-wire interface) a 3.3V restituendo, ad ogni interrogazione, la posizione X/Y del joystick analogico, lo stato dei due tasti Z e C, e i valori dell’accelerometro 3D integrato.

Con un programmino sulla Arduino leggo tali valori e li sparo sulla seriale USB del Mac (il cavetto nero) e quindi sicuramente anche verso Linux).

La Arduino “parla” a 5 volt: ha funzionato, ma non posso giurare che la Nunchuck funzionerà sempre senza problemi. Probabilmente mi toccherà inventarmi qualcosa per abbassare i 5V sui pin clock/dato ai 3.3V della Nunchuck (per i +3V3 provvede già la Arduino).

Qui sotto, il codice sorgente che ho ripescato in rete da più parti e ho riadattato alle mie maniacali precisazioni (avrei dovuto usare un modo più elegante per la questione della taratura, che cambia da Nunchuck a Nunchuck, però l’importante era pubblicare velocemente questa pagina con un esempio funzionante).

Notate che i due pin TWI sono sugli “analog” 4 e 5 della Arduino (così vuole la libreria Wire… e tutto sommato ci fa anche comodo; suppongo che la libreria non li usi in analogico), e gli altri due fili sono su 3.3V e GND.

Il connettore della Arduino ha sei pin (ma il 2 e il 5 non sono utilizzati).

| 1 2 3 |
| 6 5 4 |
Nota: i colori qui sotto si riferiscono al cavo Nunchuck (quello rivestito di bianco), non alle “prolunghe” non saldate che si vedono nella mia foto:

pin 1: verde – data (Arduino analog pin 4)
pin 2: (not connected)
pin 3: rosso – 3.3V
pin 4: giallo – clock (Arduino analog pin 5)
pin 5: (not connected)
pin 6: bianco – GND

//
// nunchuck.pde
//

#include

uint8_t buf[6]; // buffer for the six-bytes packet coming from Nunchuck
int cnt=0; // count of bytes in the buffer
int readcnt=0; // number of times we read a packet from Nunchuck
int ledPin=13; // which pin will host the blinking LED

uint8_t nunchuk_decode(uint8_t x) // decode nunchuck data
{
return (x^0x17)+0x17; // not that an hard encryption…
}

void nunchuck_ack() // acknowledge a Nunchuck packet
{
Wire.beginTransmission(0x52); // send a zero to device 0x52
Wire.send(0);
Wire.endTransmission();
}

void setup() // initialization
{
int n;
digitalWrite(ledPin, HIGH); // turn on LED

for(n=0; n<6; n++) buf[n]=0; // fill buffer with zero values beginSerial(115200); // console init Wire.begin(); // TWI init Wire.beginTransmission(0x52); // nunchuck init Wire.send(0x40); Wire.send(0); Wire.endTransmission(); digitalWrite(ledPin, LOW); // turn off LED Serial.print(“!– start\n”); } void loop() // main loop { Wire.requestFrom(0x52, 6); // request data from nunchuck while(Wire.available()) // read data and light the LED { buf[cnt++] = nunchuk_decode(Wire.receive()); digitalWrite(ledPin, HIGH); } if(cnt>=6) // an entire Nunchuck packet was read?
{
printdata(); // yes, print it
cnt=0; // clear buffer counter
nunchuck_ack(); // acknowledge received packet
digitalWrite(ledPin, LOW); // turn off the LED
delay(800); // wait 800msec before next loop
}
}

void printdata() // print out the values
{
int n; // note: the 123,131,524,597… depend on my Nunchuck calibration

Serial.print(++readcnt, DEC);

Serial.print(“\t”); // joystick x/y values
Serial.print((int)buf[0]-123);
Serial.print(“\t”);
Serial.print((int)buf[1]-131);

n=(buf[2]<<2)+((buf[5]>>2)&3)-524; // accel X
Serial.print(“\t”);
Serial.print(n);

n=(buf[3]<<2)+((buf[5]>>4)&3)-597; // accel Y
Serial.print(“\t”);
Serial.print(n);

n=(buf[4]<<2)+((buf[5]>>6)&3)-668; // accel Z
Serial.print(“\t”);
Serial.print(n);

Serial.print(buf[5]&1 ? “\t- ” : “\t[z] “);
Serial.print(buf[5]&2 ? “-” : “[c]”);

Serial.print (“\r\n”);
}

Rispondi