Interfacciarsi con il Nunchuck della Nintendo – Appunti

Giovanni Bernardo | 2 febbraio 2011
Categorie: Robotica e Automazione - Sensori

La Nintendo WII utilizza un curioso controller di gioco chiamato Nunchuk (il cui nome deriva da Nunchaku, la famosa arma giapponese costituita da due mazze di legno unite da una catena o da una piccola fune). Tale controller è molto interessante per noi elettro-pic-smanettoni per tutta una serie di motivi che ora vi elenco:

  • All’interno ha un accelerometro a 10bit
  • Ha un joystick analogico a due assi
  • Ci sono due pulsanti
  • E’ possibile acquistare un Nunchuck non originale ad un prezzo ≤ €10 (quello originale si trova a 20)
  • Comunica utilizzando un protocollo I2C standard

Il primo punto unito agli ultimi due mi ha fatto subito correre a procurarmi un Nunchuck (non originale) nonostante  io non possegga una Nintendo WII:

Un accelerometro e un joystick analogico in un case così accattivante, per di più in I2C, a solo 10 euro?!

Il nunchuck non originale di discosta di poco da quello della Nintendo, mancano gli inserti ergonomici laterali, è leggermente diverso l’incavo dello stick e probabilmente è diversa anche la plastica, ma non è che mi importa più di tanto. Non voglio aggiungere che l’elettronica sia leggermente diversa perchè questo penso sia ovvio (se no come fa a costare 10 euro di meno, non è certo la plastica che fa tutta la differenza!) ma prima di affermarlo con certezza sto aspettando che mi arrivi un cacciavite tri-wings per poterlo smontare e darci un occhio all’interno:

A me questo controller sta simpatico

Pinout Nintendo Nunchuck

Bando alle ciance. Incominciamo a vedere dove mettere le mani. Partiamo dal connettore:

Notiamo innanzitutto che, come era logico aspettarsi, il connettore non è standard. Il pin n°5 a me non è presente, probabilmente sul Nuchuck originale c’è (non ne ho idea), comunque sia non serve a nulla perchè non è connesso. Il pinout è il seguente:

Pinout Nintendo Nunchuck, verificato. Diffidate dalle imitazioni!

Attenzione che su alcuni documenti è riportato un pinout in cui il pin di presenza è indicato come +3V e il pin 3 come non connesso: questo pinout è sbagliato ma funziona comunque e il perchè lo capirete tra poco. Su altri schemi in rete il pin che io ho chiamato “presenza” è indicato come “att”. Come vedete il Nunchuck funziona a 3.3V, per cui per alimentarlo dobbiamo procurarci una sorgente di alimentazione adatta. I pin 1 e 4 sono rispettivamente il canale dati del bus I2C e il clock. Il nunchuck funziona come dispositivo I2C Slave a 400KHz. Il pin n°2 serve alla WII per capire quando il controller è collegato o meno (internamente al Nunchuck i pin 2 e 3 sono collegati insieme, in pratica la WII “legge” 3.3V sul pin2 quando il Nunchuck è attaccato alla consolle :ecco perchè quei pinout sbagliati funzionano lo stesso).

Realizziamo un adattatore per il Nunchuck

Non mi piaceva assolutamente l’idea di spezzare il cavo e tirare fuori i fili: sarebbe un atto di cannibalizzazione troppo estremo e io odio la violenza! In giro esistono tante soluzioni per potersi collegare al cavo del Nunchuck, come questa ad esempio, ma andavo un po’ di fretta per cui ho pensato di realizzarmi da me un adattatore, un po’ spartano ma efficace. La distanza tra le due file di pin del connettore del Nunchuck è uguale a quella dei normali PCB, la distanza tra i pin, però, non è quella classica da 0.1″ ma leggermente inferiore, nonostante questo, trattandosi di solo 3 pin (3 sopra e 3 sotto), utilizzare un classico PCB con connettore a pettine da 0.1″ non causa nessun problema.

Ho quindi pensato bene di dare miglior utilizzo ad una vecchia scheda PCI per computer tagliando un pezzetto del connettore inferiore:

Usando un po’ di forza bruta (leggasi: minitrapano dotato di disco diamantato, una limetta e un po’ di cartavetrata):

Si riesce ad ottenere una cosa abbastanza decente e funzionale:

Qualche cavetto, un paio di punti di saldatura, un pezzetto di termorestringente e uno strip maschio da 5 poli completano l’opera:

Interfacciarsi a livello elettrico

Ho detto che il Nunchuck funziona come dispositivo I2C Slave alla frequenza di 400KHz, ovviamente questo non basta perchè dobbiamo tener conto di due fattori importanti:

  1. Il Nunchuck funziona a 3.3Volts. Siamo abituati con le logiche a 5V, ma alimentare il nunchuck con una tensione inferiore non dovrebbe essere un problema. Possiamo riccorere anche ad un regolatore lineare come l’LM1117-3.3 o altri simili.
  2. Funzionando a 3.3Volts, è necessario anche adattare i livelli logici. L’adattamento può essere eseguito nel miglior modo utilizzando appositi circuitini come questo oppure porte logiche o ancora più semplicemente un partitore di tensione come già ho illustrato in questo articolo (paragrafo Adattare i livelli logici): a 400KHz anche il partitore dovrebbe funzionare correttamente senza falsare i segnali. Dovremo ovviamente ricordarci che il livello va adattato sia sulla linea dei dati che su quella del clock.

Ho visto un po’ dappertutto che in realtà nessuno si cura della questione dei 3.3V e fanno funzionare il Nunchuck a 5V senza problemi. A me non va di fare questa prova e non ho nemmeno la possibilità di verificare se la Nintendo WII fornisce davvero 3.3V o ne fornisce 5.

Il protocollo di comunicazione

Abbiamo imparato che un dispositivo I2C ha comunemente un indirizzo a 7 bit più un ottavo bit (il bit 0) che specifica la modalità di accesso alla periferica: 0=in scrittura 1=in lettura. Il Nunchuck ha l’indirizzo 0x52 (a 7 bit), aggiungendo il bit di lettura/scrittura gli indirizzi I2C completi del Nunchuck sono quindi:

0xA4 (scrittura)

0xA5 (lettura)

In questa pagina c’è un esempio di interfacciamento con Arduino: http://www.windmeadow.com/node/42

Il Nunchuck va inizializzato, una sola volta all’accensione, scrivendo il valore 0x00 nella locazione 0x40. La sequenza di inizializzazione del Nunchuck è quindi questa:

[I2C Start] 0xA4 0x40 0x00 [I2C Stop]

Ricordiamo che la sequenza di scrittura I2C è: Start – Indirizzo periferica in scrittura (0xA4) – Locazione di memoria in cui scrivere (0x40) – Valore da scrivere (0x00) – Stop.

Alcuni Nunchuck non originali (come il mio, ad esempio, marcato “Shiro” o alcuni marcati “DealExtreme”) utilizzano una sequenza di inizializzazione  differente:

[I2C Start] 0xA4 0xF0 0x55 [I2C Stop]

Troubleshooting
Questo “paragrafo” in realtà non andrebbe messo qui ma oramai ho imparato che la stragrande maggioranza dei lettori va sempre di fretta, si mangia interi paragrafi e subito si mette a provare senza aver finito di leggere, poi mi bombarda di email e solo dopo una decina di email si viene a sapere che magari un filo non faceva contatto. Come fare a capire che  la comunicazione non vi funziona? Semplice: o il dispositivo vi restituisce sempre NACK dopo ogni byte ricevuto, oppure quando andate ad eseguire la lettura vi vengono restituiti tutti 0xFF. Se a voi il nunchuck non comunica controllate in sequenza:

  1. L’adattatore che avete costruito fa bene contatto?
  2. La tensione di alimentazione arriva al Nunchuck?
  3. Provate a comunicare utilizzando la prima sequenza di inizializzazione, che fa riferimento al Nunchuck originale Nintendo e alla maggioranza dei Nunchuck non originali.
  4. Se l’inizializzazione “originale” non funziona, provate a comunicare utilizzando la seconda sequenza.
  5. Ancora non funziona? Rivolgetevi a Capitan Ventosa
  6. In ultima spiaggia provate con San Gennaro: è meglio non disturbarlo subito dall’inizio.

Dopo aver eseguito l’inizializzazione, si comunica al Nunchuck di voler leggere lo stato dei sensori (Accelerometro, Stick e pulsanti). Lo si fa con la sequenza:

[Start] 0xA4 0x00 [Start Ripetuto] 0xA5 [Lettura bulk di 6 bytes] [Stop]

Ricordo che la sequenza di lettura di un dispositivo I2C è la seguente: Start – Indirizzo periferica in scrittura (0xA4)- indirizzo locazione dalla quale iniziare a leggere (0x00) – Start ripetuto – Indirizzo periferica in lettura (0xA5) – Lettura dei bytes restituiti dalla periferica – Stop.

Per eseguire la lettura Bulk (sequenziale) basta dare un ACK dopo ogni byte ricevuto: in questo modo la periferica Slave fornisce il contenuto dei registri successivi a quello di partenza fino a che il master non da un NACK seguito da STOP per terminare la comunicazione. Questa modalità è piu vantaggiosa perchè richiede meno tempo e i bytes vengono restituiti tutti di fila. Se volete eseguire la lettura classica di un byte singolo basta che partite col fornire l’indirizzo 0x00 e leggere singolarmente tutte le locazioni fino ad arrivare alla 0x05.

Questa sequenza di lettura è uguale sia per il Nunchuck originale che non.

Il nunchuck restituirà quindi un pacchetto composto da 6 bytes:

C’è da dire una cosa: un po’ dappertutto c’è scritto che i bytes ricevuti vanno “decodificati”. Su ogni byte ricevuto si deve eseguire un XOR con il valore 0x17 e quindi al risultato sommare ancora il valore 0x17 ma personalmente ho ancora qualche perplessità su questa questione e capirete perchè. Analizziamo il contenuto dei bytes ricevuti:

Byte 0 : posizione dello stick analogico sull’asse X (0=tutto a sinistra, 255=tutto a destra). A questo punto la questione della decodifica mi pare piuttosto strana. Eseguendo la decodifica sui valori estremi 0 e 255 non c’è nessun problema perchè ottengo sempre 0 e 255. Il dubbio ce l’ho sui valori di mezzo. Avendo un valore di stick analogico che varia tra 0 e 255 è logico pensare che con lo stick fermo in posizione centrale io ottenga il valore 0x80 (128), e difatti così ottengo SENZA decodifica, se invece eseguo la decodifica sul valore ricevuto (0x80) ottengo:

(0x80 XOR 0x17) + 0x17 = 0xAE (174)

che non mi odora proprio di valore centrale… Per cui… fate voi delle prove con i vostri Nunchuck e fatemi sapere…

Byte 1 : posizione dello stick analogico sull’asse Y (0=tutto giù, 255=tutto su)

Byte 2 : 8 bit alti del valore a 10 bit relativo all’asse X dell’accelerometro. La variazione dell’asse X la si ha quando si trasla il controller in senso laterale. Quando il controller è fermo il valore a 10bit è intorno a 512, muovendosi verso sinistra il valore diminuisce, muovendosi verso destra il valore aumenta:

Questa immagine e le seguenti due sono prelevate dal manuale del “ZX-Nunchuck – WII Nunchuck interface Board” scaricato dal sito robotshop.com (http://www.robotshop.com/content/PDF/inex-zx-nunchuck-datasheet.pdf)

I valori restituiti dall’accelerometro hanno una variazione proporzionale alla velocità del movimento (uno spostamento molto veloce fa variare il valore in misura più alta), quando il movimento è terminato i valori si riportano al centro. In condizioni di stasi, quindi, i 3 valori restituiti dall’accelerometro dovrebbero trovarsi più o meno intorno a 512, in realtà io mi ritrovo valori tra 400 e 700 (sia con che senza decodifica).

Ricordo che un accelerometro misura l’accelerazione e non va confuso con un giroscopio che misura l’inclinazione.

Byte 3 : 8 bit alti del valore a 10 bit relativo all’asse Y dell’accelerometro. La variazione dell’asse Y si ha quando il controller viene traslato in senso longitudinale. Muovendo il controller in avanti il valore aumenta, tirandolo verso sè il valore diminuisce.

Byte 4 : 8 bit alti del valore a 10 bit relativo all’asse Z dell’accelerometro. La variazione dell’asse Z si ha quando il controller viene traslato verso il soffitto o verso il pavimento (maccheronicamente parlando!). Traslando in alto il valore aumenta, traslando verso il basso il valore diminuisce:

Byte 5 : in questo byte è contenuto un po’ di tutto:

Bits 7 e 6 : corrispondono ai 2 bit bassi (rispettivamente 1 e 0) del valore a 10 bit dell’asse Z dell’accelerometro

Bits 5 e 4 : corrispondono ai 2 bit bassi (rispettivamente 1 e 0) del valore a 10 bit dell’asse Y dell’accelerometro

Bits 3 e 2 : corrispondono ai 2 bit bassi (rispettivamente 1 e 0) del valore a 10 bit dell’asse X dell’accelerometro

Bit 1 : pulsante C (quello più piccolo posto in alto). Tale bit vale zero quando il pulsante è premuto

Bit 0 : pulsante Z (quello più grande posto in basso). Tale bit vale zero quando il pulsante è premuto

Come avete capito, quindi, l’interfacciamento di questo simpatico dispositivo può essere eseguito sfruttando le periferiche di comunicazione I2C ed eseguendo delle semplici operazioni. Se non si vuole ottenere la piena risoluzione a 10 bit dell’accelerometro è anche possibile utilizzare i soli 8 bit alti evitando di eseguire bitshift e maschere sul 5°byte ricevuto. In questo momento sto facendo delle prove di collegamento con il Bus Pirate giusto per capirne perfettamente il funzionamento prima di passare a cose più complicate, quindi non escludo che tra poco piazzo qualche appunto su questo argomento.

come mi diverto!

Edit: Ringrazio l’utente “Fiacca” per le correzioni

Puoi andare alla fine dell'articolo e lasciare un commento. I trackback e i ping non sono attualmente consentiti.

  1. #1 da Astronomer il 2 febbraio 2011

    Stupendo questo articolo! Geniale!

  2. #3 da filep il 2 febbraio 2011

    ho notato che il pinout del nunchuk nel pdf
    http://www.robotshop.com/content/PDF/inex-zx-nunchuck-datasheet.pdf
    è diverso dal pinout che hai messo nell’articolo.
    é un errore?

  3. #6 da Fiacca il 3 febbraio 2011

    Articolo molto ben fatto. Complimenti.
    Solo una nota chiarificatrice per non generare confusione. Lo slave address di un device I2C e’ composto da 7 bit a cui si aggiunge l’8 bit (LSB) per indicare l’operazione che si intende fare sul device ( 0= Write device, 1=Read device ).
    Il comando 0xA4 (0b10100100 ) eseguira’ un write sul device address 1010010 che tradotto in hex diventa 0x52.
    Il comando 0xA5 (0b10100101 ) eseguira’ un read sul device address 1010010 ( sempre 0x52 ).
    Per definizione, l’indirizzo del device e’ 0x52 mentre 0xA4 e’ da considerare composto da ADDR+(R/W).
    Cio’ spiega perche’ Arduino usi l’indirizzo 0x52. Il, il bit R/W verra’ aggiunto automaticamente a seconda della chiamata a Wire.transmit ( write device ) o Wire.request ( read device ).

  4. #9 da Filartrix il 16 febbraio 2011

    Salve,
    io ho provato ad interfacciare un nunchuck non originale con l’arduino, in effetti anche se ci sono molti esempi già pronti su internet, questo articolo mi è stato utile.
    Posso confermare anche io che la decodifica non serve, anzi, quando la utilizzo i valori non sono affatto sequenziali.

  5. #10 da Francesco il 2 giugno 2011

    Salve.
    Complimenti, trovo l’articolo molto ben fatto ed accattivante, solo che adesso, quando finalmente sono riuscito a mettere le mani sul Nintendo originale di mio figlio, incontro delle difficoltà e spero che voi possiate aiutarmi.
    Premetto che sto usando la porta parallela del mio pc per interfacciarmi col Nunchuck, lavorando con un clock bassissimo, per seguire visivamente con dei led, tutto quello che transita sui fili SDA ed SCL (sistema già sperimentato su altri dispositivi).
    Mi succede che dopo aver inviato il primo byte “A4” mi ritrovo come previsto un ack dal Nunchuk,
    però, dopo l’invio del secondo byte “40” l’ack il nunchuck non me lo da più, quindi non riesco a proseguire coi byte successivi. Dove sbaglio ?….forse il problema è dovuto alla bassa velocità d’esecuzione delle istruzioni ?…
    Ringrazio sin d’ora per la cortese attenzione e per i preziosi consigli che mi darete.
    Saluti…Francesco.

  6. #11 da Matteo il 4 novembre 2011

    Ciao,
    complimenti per l’articolo, proprio ben fatto e utile!
    Solo un paio di note:
    – Le letture in uscita dall’accelerometro sono proporzionali all’accelerazione, non alla velocità di movimento;
    – In condizioni di stasi (nunchuck appoggiato e fermo) leggerai in generale valori diversi da 512 sui tre assi perché l’accelerometro rileva la gravità terrestre.

    Saluti

  7. #13 da viugamant il 29 maggio 2012

    Ciao,
    complimenti per l’articolo!
    Qualcuno conosce quale chip accelerometro (costruttore e modello) è montato all’interno del Nunchuck?

    Saluti
    Fabio

  8. #14 da Lucasss il 29 luglio 2012

    Vi è mai capitato che il nunchuck vi risponda sempre 255 in tutti i campi letti?
    Ho un nunchuck originale, e ho quindi utilizzato la sequenza d’inizializzazione: Start, 0xA4, 0x40, 0x00, Stop. Verificando l’ack nella scrittura di 0x00 in nunchuck mi risponde, quindi l’inizializzazione pare andare a buon fine. Quando però vado a leggere: Start, 0xA4, 0x00, StartRip, 0xA5, ricevo, Stop, ottengo solo 255.
    Ho provato anche con l’inizializzazione per nunchuck non originali, ma il risultato non cambia.
    Sapete se magari vi sono comandi diversi anche per i nunchuck originali delle varie annate?

    • #15 da mene il 31 marzo 2016

      ciao lucasss scusa se non risolvo il tuo problema ma è esattamente ciò che accade anche a me. per caso sei riuscito a risolvere?

      • #16 da Giovanni Bernardo il 26 aprile 2016

        Hai provato, anche se si tratta del nunchuck originale, la sequenza di inizializzazione alternativa? Hai controllato che la tensione arrivi correttamente al nunchuck, che i livelli del segnale sono compatibili, a 3.3V? Ci sono le resistenze di pull-up sul circuito che utilizzi?

  9. #17 da QuasarLex il 26 luglio 2014

    Ciao

    Grazie per l’ articolo molto chiaro per il funzionamento con Arduino ( testato e funziona ). Sto provando però a fare la stessa cosa ma con un STM32F3 Discovery, che necessita di impostare tempi di rise, fall, ecc ecc per dato e clock di I2C. Non sono riuscito a trovare nessuna informazione in rete sui tempi stabiliti da nintendo per il nunchuck e non dispongo di un oscilloscopio per tentare di capirci qualcosa con delle prove… Sapresti darmi qualche indicazione?

    Grazie e ciao

  10. #18 da johnnydsg il 19 ottobre 2014

    Potrebbe per favore ricreare il link giusto al circuitino per l’adattamento dei livelli di tensione da 3,3 V a 5 V, venduta dalla Robot-Italy?

Devi essere collegato per lasciare un commento.

  1. Ancora nessun trackback
Settorezero.com e il logo Zroid™ ©2007÷2017 Giovanni Bernardo - E' vietata la copia e la distribuzione anche parziale dei contenuti di questo sito web senza l'esplicito consenso dell'autore. I contenuti di settorezero.com sono distribuiti sotto una licenza Creative Commons Attribuzione-Non Commerciale-Non Opere derivate 2.5 Italia e sono soggetti alle condizioni definite nel disclaimer. Settorezero.com e tutti i suoi contenuti sono tutelati dalla legge sul diritto d'autore per cui i trasgressori sono perseguibili a norma di legge. Settorezero fa uso dei cookie leggi l'informativa estesa. Il tema di questo sito è basato sul tema Fusion per wordpress, realizzato originariamente da digitalnature e fa uso del plugin Wassup per il computo delle statistiche. Per contattare l'autore siete pregati di utilizzare la sezione contatti. Siamo presenti anche su Facebook e, meno assiduamente, anche su Twitter - Tumblr - Google+ - Blogspot - Youtube.
Creative Commons BY-NC-ND 2.5