Kontroler Wii Nunchack

ODPOWIEDZ
Awatar użytkownika
SunRiver
Użytkownik
Posty: 1051
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Festung Oppeln
Kontakt:

Kontroler Wii Nunchack

Post autor: SunRiver »

Konsola Nintendo Wii ma ciekawy kontroler zawierający w sobie nie tylko Analog ale i akcelerometr i aż dwa buttony
można to wiec wykorzystać np do zabawy z serwami .... Napisałem to jakiś czas temu , ale myślę że warto wspomnieć gdyż kontrolery do Wii tanieją.

Obrazek

Sam akcelerometr w postaci modułu jest dosyć drogi , ale nunchacka można nabyć tanio i wykorzystać go do własnych celów.
W przypadku płytek zgodnych z Duino możemy w bardzo prosty sposób wykorzystać dostępną w IDE bibliotekę Wire. Oczywiście w gcc
również nie będzie kłopotu z używaniem kontrolera bowiem on komunikuje się po magistrali TWI (I2C) więc odczytanie go nie sprawi nam
wiele problemów , a w związku z faktem że ma ładną obudowę i gotowe okablowanie możemy użyć go do np obsługi robota, serva czy wielu
innych celów:)

Niestety w świecie konsol każdy producent robi sobie swoje .... i tu jest również nietypowe gniazdo wiec jeśli nie mamy Wii do rozebrania
to możemy poradzić sobie na dwa sposoby z tym problemem:

1.  Pozbywamy się gniazda :
w przewodzie są tylko 4 kable których znaczenie jest następujące:
   -- biały  --- Masa (GND)
     -- czerwony --- +3.3V
    -- zielony --- DATA
   -- żółty  ---CLK (zegar)

Jak więc widać nic skomplikowanego , podłączamy do naszej płytki xxxDuino następująco:
Biały na GND , czerwony do +5V , Pozostałe 2 do I2C co opisze niżej

UWAGA !!

Jak zauważyliście kontroler uzywa 3,3V, a ja go podłączyłem do +5V Jak do tej pory pracuje dobrze, 
Niemniej choć mieści się napięcie w zakresie zasilania to jednak jest to górna granica i może negatywnie wpłynąć
na żywotność układów. A testy robiłem akurat na Atemendzie więc sami rozumiecie ....
2. Przez adapter gniazda :
    adapter taki jest bardzo łatwo wykonać na płytce z laminatu -- tylko czy warto ??

Kiedy się już uporamy z naszym podłączeniem i wybierzemy odpowiedni sposób przystępujemy do zabawy z bibliotek? :)

Komunikacja z nunchackiem wygląda następująco :

Najpierw wysyłamy 2 bajty (0x40, 0x00), a następnie jeden bajt (0x00) za każdym razem prosząc o dane z kontrolera,
na co kontroler odpowiada 6 bajtowymi paczkami. Znaczenie poszczególnych bajtów pokazuje tabelka

Obrazek

Napiszemy teraz prosty program , który będzie odczytywać dane z kontrolera nunchuck i wysyłać je do komputera na terminal.
Jako że ciężko będzie nadążyć z odczytem na TWI i wysyłaniem danych na terminal w tym samym czasie będzie widoczne niewielkie opóźnienie
i sporadycznie mogą się pojawiać dziwne znaki na terminalu (przekłamania). Ale nie będziemy się tym przejmować program napisany na kolanie
w ardupino tylko w celu sprawdzenia czy zamysł i kierunek są dobre w rozumowaniu całości.
  1. #include "wire.h";
  2. #include "string.h";
  3.  
  4. #undef int
  5. #include "stdio.h";
  6.  
  7. uint8_t outbuf[6];        // tablica przechowująca dane wyjściowe
  8. int cnt = 0;
  9. int ledPin = 13;
  10.  
  11. void setup ()
  12. {
  13.      beginSerial (19200);
  14.      Serial.print ("Ustawienia OKn");
  15.      Wire.begin ();        //  połączenie z TWI pod addresem 0x52
  16.      nunchuck_init ();   // procedura inicjacji nunchucka
  17. }
  18.  
  19. void nunchuck_init ()
  20. {
  21.     Wire.beginTransmission (0x52);    // transmisja do urzadzenia 0x52
  22.     Wire.send (0x40);                        // wysłanie adresu pamięci
  23.     Wire.send (0x00);                        // wysyłanie zera
  24.     Wire.endTransmission ();             // koniec transmisji
  25. }
  26.  
  27. void send_zero ()
  28. {
  29.      Wire.beginTransmission (0x52);    // urządzenie na 0x52
  30.      Wire.send (0x00);                        // wysłanie jednego bajta
  31.      Wire.endTransmission ();             // stop
  32. }
  33.  
  34. void loop ()
  35. {
  36.    Wire.requestFrom (0x52, 6);    // rządanie danych z nunchacka
  37.    while (Wire.available ())
  38.    {
  39.          outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());    // odbieranie danych
  40.          digitalWrite (ledPin, HIGH);    // ustawienie diody LED na ON
  41.          cnt++;
  42.    }
  43.  
  44.    // Odebrane zostało 6 bajtów  -- wysyłka na terminal
  45.    if (cnt >= 5)
  46.    {
  47.          print ();
  48.    }
  49.  
  50.    cnt = 0;
  51.    send_zero ();  // żądanie następnych 6 bajtów
  52.    delay (100);    // odbierane dane akcelerometra maja długość 10 bitów
  53.                          // dlatego zastosujemy mała sztuczkę mnożenia przez 2*2
  54.                          // przez co dodamy 2 ostatnie bity
  55. }
  56.  
  57. void print ()
  58. {
  59.    int joy_x_axis = outbuf[0];
  60.    int joy_y_axis = outbuf[1];
  61.    int accel_x_axis = outbuf[2] * 2 * 2;
  62.    int accel_y_axis = outbuf[3] * 2 * 2;
  63.    int accel_z_axis = outbuf[4] * 2 * 2;
  64.  
  65.    int z_button = 0;
  66.    int c_button = 0;
  67.  
  68.    // outbuf[5] zawiera w sobie tez bity przycisku c
  69.    // zawiera też najmniej znaczące bity akcelerometra
  70.    // więc musimy sprawdzić każdy bit tablicy outbuf[5]
  71.    if ((outbuf[5] >> 0) & 1)
  72.    {
  73.          z_button = 1;
  74.    }
  75.    if ((outbuf[5] >> 1) & 1)
  76.    {
  77.          c_button = 1;
  78.    }
  79.  
  80.    if ((outbuf[5] >> 2) & 1)
  81.    {
  82.         accel_x_axis += 2;
  83.    }
  84.    if ((outbuf[5] >> 3) & 1)
  85.    {
  86.         accel_x_axis += 1;
  87.    }
  88.  
  89.    if ((outbuf[5] >>  4) & 1)
  90.    {
  91.        accel_y_axis += 2;
  92.    }
  93.    if ((outbuf[5] >> 5) & 1)
  94.    {
  95.        accel_y_axis += 1;
  96.    }
  97.  
  98.    if ((outbuf[5] .. 6) & 1)
  99.    {
  100.          accel_z_axis += 2;
  101.    }
  102.    if ((outbuf[5] >> 7) & 1)
  103.    {
  104.         accel_z_axis += 1;
  105.     }
  106.  
  107. Serial.print (joy_x_axis, DEC);
  108. Serial.print ("t");
  109.  
  110. Serial.print (joy_y_axis, DEC);
  111. Serial.print ("t");
  112.  
  113. Serial.print (accel_x_axis, DEC);
  114. Serial.print ("t");
  115.  
  116. Serial.print (accel_y_axis, DEC);
  117. Serial.print ("t");
  118.  
  119. Serial.print (accel_z_axis, DEC);
  120. Serial.print ("t");
  121.  
  122. Serial.print (z_button, DEC);
  123. Serial.print ("t");
  124.  
  125. Serial.print (c_button, DEC);
  126. Serial.print ("t");
  127.  
  128. Serial.print ("rn");
  129. }
  130.  
  131. // dekodowanie danych z nunchuck
  132. char nunchuk_decode_byte (char x)
  133. {
  134.     x = (x ^ 0x17) + 0x17;
  135.     return x;
  136. }
  137.  
I tak by to w skrócie wyglądało ... za niską cenę fajna zabawa pozostaje się tylko cieszyć i myśleć do czego by to użyć :)
ODPOWIEDZ

Wróć do „Na luzie”