Wii Nunchuck a Arduino

Akcelerometr je hezká hračka a čím dál častěji se používá v nejrůznějších aplikacích. Pokud se s touto zajímavou součástkou chcete pohrát, máte dvě možnosti. Buď si koupíte nějaký kit (například na sparkfun.com stojí něco kolem 20 dolarů) nebo využijete herního ovladače Nunchuck od Nintenda Wii. Tento ovladač totiž kromě dvou tlačítek a jednoho joysticku obsahuje i akcelerometr. Pojďme se teď podívat, jak s tímto ovladačem komunikovat pomocí Arduina a na co všechno se dá použít.

Základní popis ovladače

Herní ovladač Wii Nunchuk obsahuje dvojici tlačítek, joystick a akcelerometr.
Herní ovladač Wii Nunchuk obsahuje dvojici tlačítek, joystick a akcelerometr. (Zdroj: Wikipedia)

Ovladač je velmi jednoduchý kus hardwaru, který obsahuje dvě tlačítka, joystick a akcelerometr. Pomocí konektoru jej lze připojit k ovladači Wii Remote a spolu se pak používají ve hrách na konzoli Nintendo Wii. Samotný Nunchuk neobsahuje žádné baterie, je napájen přes kabel 3,3 V.

Konektor ovladače má 6 pinů, z nichž nás budou zajímat jen 4 — dva pro napájení a dva pro datovou komunikaci (I²C). Aby se dal Nunchuck použít, budete muset konektor buď odstřihnout, nebo si vyrobit protikus (inspirovat se můžete například na webu Sparkfun.com, kde prodávají tuto redukci za necelých 1,5 €).

Jakmile vyřešíte problém s konektorem, již nic nebrání tomu, aby se Nunchuck připojil k Arduinu a začal používat.

Připojení k Arduinu

Na obrázku je vidět zapojení konektoru. Nás budou zajímat dvě dvojice krajních pinů — GND a VCC pro napájení (upozorňuji, že Nunchuck pracuje s 3,3 V; některé zdroje uvádějí že se nic nestane i při použití 5 V, ale raději bych to neriskoval) a SCL a SDA pro I²C komunikaci.

Konektor ovladače Wii Nunchuk.
Konektor ovladače Wii Nunchuk. (Zdroj: Wiibrew.org)

Pro ty z vás, co jste zvolili odstřihnutí konektoru je zde ještě tahle tabulka:

Barva vodiče Funkce
Bílá GND
Červená Napájení 3,3 V
Zelená I²C data
Žlutá I²C hodiny

Jakmile se vám podaří úspěšně propojit ovladač s Arduinem, můžeme začít programovat.

Komunikace s ovladačem

Další podrobnosti můžete najít na Wiibrew.org.

Všechny ovladače (nejenom Nunchuck), které se dají připojit k Wii Remote komunikují pomocí sběrnice I²C v režimu slave na adrese 0x52. Rychlost hodin, které generuje master je 400kHz.

Před samotnou komunikací je nutné provést handshake. Stačí poslat ovladači konstantu 0x00 na adresu 0x40. Kód pro Arduino tak může vypadat následovně:

  Wire.begin();                // zahájíme komunikaci na I2C sběrnici
                               // Arduino se bude chovat jako master
  Wire.beginTransmission(0x52);// zahájíme přenos se zařízením 0x52
  Wire.send(0x40);             // odešleme adresu paměti
  Wire.send(0x00);             // odešleme handshake konstantu
  Wire.endTransmission();      // konec přenosu

Poté již můžete číst data z ovladače, který je posílá vždy v šesti bajtových blocích. Každý přijatý bajt je pak potřeba upravit, protože ovladač je posílá zakódované (viz dále).

Tento handshake ale bude fungovat jenom pro originální Nunchucky od Nintenda. Pokud máte ovladač od jiného výrobce, pravděpodobně se zahájení komunikace nepovede. V takovém případě je nutné odeslat dva bajty 0x55 a 0x00 na adresy 0xF0 a 0xFB. Například:

  Wire.begin();                // zahájíme komunikaci na I2C sběrnici
                               // Arduino se bude chovat jako master
  Wire.beginTransmission(0x52);// zahájíme přenos se zařízením 0x52
  Wire.send(0xF0);             // odešleme adresu paměti
  Wire.send(0x55);             // odešleme handshake konstantu
  Wire.endTransmission();      // konec přenosu

  delay(1);

  Wire.beginTransmission(0x52);
  Wire.send(0xFB);
  Wire.send(0x00);
  Wire.endTransmission();

  delay(1);

  // Teď ještě musíme zjistit typ připojeného ovladače...
  Wire.beginTransmission(0x52);
  Wire.send(0xFA);
  Wire.endTransmission();

  // ...a přečíst odpověď.
  Wire.beginTransmission(0x52);
  Wire.requestFrom(0x52, 6);  // Ovladače vždy odesílají 6 bajtů

  int i = 0;
  byte status[6];
  while (Wire.available ()) {
    // Data, které přijmete budou pravděpodobně:
    //   0x0000 0xA420 0x0000 pro Nunchuck
    //   0x0000 0xA420 0x0101 pro Classic Controller
    status[cnt] = Wire.receive();
    i++;
  }

V případě tohoto druhého postupu se projeví jeden (příjemný) vedlejší efekt. Data, která bude ovladač odesílat již nebudou kódovaná, a tak můžete s přijatými bajty pracovat přímo.

Po úspěšném handshaku již můžeme ze zařízení jednoduše číst informace z akcelerometru a tlačítek:

  byte data[6];
  int i = 0;
  Wire.requestFrom (0x52, 6);
  while (Wire.available ()) {
    // V případě handshaku s originálním ovladačem
    // je nutné bajty dekódovat. Podrobnosti viz
    // http://wiibrew.org/wiki/Wiimote/Extension_Controllers

    // data[i] = (Wire.recieve() ^ 0x17) + 0x17;
    data[i] = Wire.receive();
    i++;
  }

Ovladač odesílá data v šesti bajtových blocích, které obsahují veškeré informace, které potřebujeme. Data jsou v tomto bloku uspořádaná následovně:

Zdroj: Wiibrew.org Bit
Bajt 7 6 5 4 3 2 1 0
0 SX<7:0>
1 SY<7:0>
2 AX<9:2>
3 AY<9:2>
4 AZ<9:2>
5 AZ<1:0> AY<1:0> AX<1:0> BC BZ

Kde bajty SX a SY jsou polohy analogového joysticku, AX, AY a AZ jsou data z akcelerometru (všimněte si, že data jsou 10 bitová a část z nich je i v 5. bajtu). V bitech BC a BZ je informace o zmáčknutí tlačítek C a Z.

Bajty, které obsahují informaci o poloze analogového joysticku se pohybují v rozmezí od cca 30 do 220 (přesné hodnoty se liší, je nutné je zjistit experimentálně) se středem ve 128.

Akcelerometr vrací hodnoty v rozmezí od 0 do 1024 pro každou osu. Tlačítka jsou aktivní (zmáčknutá) v 0, neaktivní v 1.

Knihovna pro Arduino

Otázky?
Pokud máte k tématu jakékoliv otázky (nedaří se vám číst z Nunchucku, nevíte co s přijatými daty, apod.) zeptejte se na našem webu qa.uart.cz.

Podle výše popsaného si můžete napsat vlastní kód pro Arduino, který bude číst data z ovladače a následně s nimi pracovat. To by ale bylo vymýšlení kola, protože různě po internetu se dají nalézt již hotové (více či méně kvalitní) knihovny. Jedna z nich je přímo na stránkách Arduino.cc.

Jmenuje se WiiChuck a její použití je velmi jednoduché a přímočaré. Také by měla fungovat i pro Nunchucky od jiných výrobců než Nintendo (používá druhý handshake popsaný v textu výše).

Jednoduchý ukázkový kód:

#include "Wire.h"
#include "WiiChuck.h"

WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;

void setup() {
  // Data z ovladače budeme posílat po
  // sériové lince do PC.
  Serial.begin(115200);

  // Handshake a 'dummy read' dat.
  chuck.begin();
  chuck.update();
}

void loop() {
  delay(20);
  chuck.update(); // přečteme data z ovladače

  // a následně je zpracujeme
  Serial.print(chuck.readRoll()); // Natočení
  Serial.print(", ");

  Serial.print(chuck.readPitch()); // Náklon
  Serial.print(", ");

  // Data z akcelerometru
  Serial.print((int)chuck.readAccelX());
  Serial.print(", ");
  Serial.print((int)chuck.readAccelY());
  Serial.print(", ");
  Serial.print((int)chuck.readAccelZ());

  Serial.println();
}

Další zdroje

Závěr

V textu jsme si ukázali jak lze jednoduše použít herního ovladače Wii Nunchuck jako akcelerometru pro Arduino. Na rozdíl od jednoduchých akcelerometrů, které se dají koupit různě v obchodě má Nunchuck tu výhodu, že je v pevném platovém obalu a navíc obsahuje tlačítka a joystick. Ideální kousek hardwaru pro ovládání robotů, kamer, nebo i her na počítači. Pro inspiraci, co vše lze s Nunchuckem udělat, se podívejte na Youtube (zajímavé videa jsou uvedeny zde, v sekci Další zdroje).