roboforum.ru

Технический форум по робототехнике.

Использование джойстика от приставки Wii nunchuck.

Использование джойстика от приставки Wii nunchuck.

frwind » 18 мар 2011, 11:31

Разобрался с подключением нунчак(джойстика) от приставки Wii
В общем подключив его имеем пульт управления с 3х осевым акселерометром, 2х осевой миниджойстик, 2х кнопки.
Для наглядности:



Подключаем нунчак по протоколу I2C, к SDA SCL
Изображение

Питание в идеале надо 3,3в, но как показали многочисленные форумы, работает и от 5в, от самой Ардуины.
В некоторых схемах используют питание и землю с аналоговых выходов самой Ардуины.

Приобрести это чудо можно легко на ebay'e
Цены на китайские от 1$-10$
Я брал тут
http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=220644955204&ssPageName=ADME:X:RTQ:US:1123#ht_3052wt_977

Самое главное: Китайские дешевые нунчаки, за 1-3$ инициализируются не как оригинальные, код инициализации нужно заменять.

В оригинале код инициализации:
Код: Выделить всёРазвернуть
//========================================
Wire.begin();                // join i2c bus as master
    Wire.beginTransmission(0x52);// transmit to device 0x52
    Wire.send(0x40);// sends memory address
    Wire.send(0x00);// sends sent a zero. 
    Wire.endTransmission();// stop transmitting
//========================================


Для инициализации китайских дешевых, вместо него пишем:

Код: Выделить всёРазвернуть
//========================================
byte cnt;
uint8_t ctrlr_type[6];

Wire.begin();
           
// init controller
delay(1);
Wire.beginTransmission(0x52);   // device address
Wire.send(0xF0);              // 1st initialisation register
Wire.send(0x55);              // 1st initialisation value
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0xFB);              // 2nd initialisation register
Wire.send(0x00);              // 2nd initialisation value
Wire.endTransmission();
delay(1);
           
// read the extension type from the register block       
Wire.beginTransmission(0x52);
Wire.send(0xFA);              // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6);            // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
    if (Wire.available()) {
        ctrlr_type[cnt] = Wire.receive(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
    }
}
Wire.endTransmission();
delay(1);
           
// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.send(0xF0);              // crypto key command register
Wire.send(0xAA);              // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0x40);              // crypto key data address
for (cnt = 0; cnt < 6; cnt++) {
    Wire.send(0x00);              // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);              // sends memory address
for (cnt = 6; cnt < 12; cnt++) {
    Wire.send(0x00);              // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);              // sends memory address
for (cnt = 12; cnt < 16; cnt++) {
    Wire.send(0x00);              // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init
//========================================

И все прекрасно работает.

Кодов с использованием нунчак полно, главное не забываем менять строку инициализации.

Вот один из примеров.

Код: Выделить всёРазвернуть
//========================================
/*
* NunchuckPrint
*
* 2007 Tod E. Kurt, http://todbot.com/blog/
*
* The Wii Nunchuck reading code is taken from Windmeadow Labs
*   http://www.windmeadow.com/node/42
*/

#include <Wire.h>


void setup()
{
  Serial.begin(19200);
// nunchuck_setpowerpins(); // use analog pins 2&3 as fake gnd & pwr
  nunchuck_init(); // send the initilization handshake
  Serial.print ("Finished setup\n");
}

void loop()
{
  nunchuck_get_data();
  nunchuck_print_data();
  delay(100);
}


//
// Nunchuck functions
//

static uint8_t nunchuck_buf[6];   // array to store nunchuck data,

// Uses port C (analog in) pins as power & ground for Nunchuck
//static void nunchuck_setpowerpins()
//{
//#define pwrpin PORTC3
//#define gndpin PORTC2
//   DDRC |= _BV(pwrpin) | _BV(gndpin);
//   PORTC &=~ _BV(gndpin);
//    PORTC |=  _BV(pwrpin);
//    delay(100);  // wait for things to stabilize       
//}

// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{
//  Wire.begin();                   // join i2c bus as master
//  Wire.beginTransmission(0x52);   // transmit to device 0x52
//  Wire.send(0x40);      // sends memory address
//  Wire.send(0x00);      // sends sent a zero. 
//  Wire.endTransmission();   // stop transmitting
byte cnt;
uint8_t ctrlr_type[6];
Wire.begin();
           
// init controller
delay(1);
Wire.beginTransmission(0x52);   // device address
Wire.send(0xF0);              // 1st initialisation register
Wire.send(0x55);              // 1st initialisation value
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0xFB);              // 2nd initialisation register
Wire.send(0x00);              // 2nd initialisation value
Wire.endTransmission();
delay(1);
           
// read the extension type from the register block       
Wire.beginTransmission(0x52);
Wire.send(0xFA);              // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6);            // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
    if (Wire.available()) {
        ctrlr_type[cnt] = Wire.receive(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
    }
}
Wire.endTransmission();
delay(1);
           
// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.send(0xF0);              // crypto key command register
Wire.send(0xAA);              // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0x40);              // crypto key data address
for (cnt = 0; cnt < 6; cnt++) {
    Wire.send(0x00);              // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);              // sends memory address
for (cnt = 6; cnt < 12; cnt++) {
    Wire.send(0x00);              // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);              // sends memory address
for (cnt = 12; cnt < 16; cnt++) {
    Wire.send(0x00);              // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init
}

// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request()
{
  Wire.beginTransmission(0x52);   // transmit to device 0x52
  Wire.send(0x00);      // sends one byte
  Wire.endTransmission();   // stop transmitting
}

// Receive data back from the nunchuck,
int nunchuck_get_data()
{
    int cnt=0;
    Wire.requestFrom (0x52, 6);   // request data from nunchuck
    while (Wire.available ()) {
      // receive byte as an integer
      nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
      cnt++;
    }
    nunchuck_send_request();  // send request for next data payload
    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5) {
     return 1;   // success
    }
    return 0; //failure
}

// 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 nunchuck_print_data()
{
  static int i=0;
  int joy_x_axis = nunchuck_buf[0];
  int joy_y_axis = nunchuck_buf[1];
  int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
  int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
  int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;

  int z_button = 0;
  int c_button = 0;

  // byte nunchuck_buf[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 ((nunchuck_buf[5] >> 0) & 1)
    z_button = 1;
  if ((nunchuck_buf[5] >> 1) & 1)
    c_button = 1;

  if ((nunchuck_buf[5] >> 2) & 1)
    accel_x_axis += 2;
  if ((nunchuck_buf[5] >> 3) & 1)
    accel_x_axis += 1;

  if ((nunchuck_buf[5] >> 4) & 1)
    accel_y_axis += 2;
  if ((nunchuck_buf[5] >> 5) & 1)
    accel_y_axis += 1;

  if ((nunchuck_buf[5] >> 6) & 1)
    accel_z_axis += 2;
  if ((nunchuck_buf[5] >> 7) & 1)
    accel_z_axis += 1;

  Serial.print(i,DEC);
  Serial.print("\t");
 
  Serial.print("joy:");
  Serial.print(joy_x_axis,DEC);
  Serial.print(",");
  Serial.print(joy_y_axis, DEC);
  Serial.print("  \t");

  Serial.print("acc:");
  Serial.print(accel_x_axis, DEC);
  Serial.print(",");
  Serial.print(accel_y_axis, DEC);
  Serial.print(",");
  Serial.print(accel_z_axis, DEC);
  Serial.print("\t");

  Serial.print("but:");
  Serial.print(z_button, DEC);
  Serial.print(",");
  Serial.print(c_button, DEC);

  Serial.print("\r\n");  // newline
  i++;
}

// 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;
}
//========================================

И немного полезных ссылок:
Благодаря этому решилась проблема с инициализацией.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264805255/0

Подробное описание Wii remote
http://wiibrew.org/wiki/Wiimote#Extension_Controllers

О использовании фильтра Калмана
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1253202298

Полезная информация:
http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/
Последний раз редактировалось frwind 18 мар 2011, 13:03, всего редактировалось 1 раз.

Re: Использование джойстика от приставки Wii nunchuck.

avr123.nm.ru » 18 мар 2011, 11:46

Очень интересная тема. Спасибо.

Re: Использование джойстика от приставки Wii nunchuck.

blindman » 18 мар 2011, 11:47

frwind, оформите код тэгом [code] - невозможно такие портянки читать

Re: Использование джойстика от приставки Wii nunchuck.

frwind » 18 мар 2011, 13:04

blindman писал(а):frwind, оформите код тэгом [code] - невозможно такие портянки читать

Подправил.

Re: Использование джойстика от приставки Wii nunchuck.

noonv » 18 мар 2011, 13:15

опередили :)
мне только недавно пришёл такой джойстик :)

Re: Использование джойстика от приставки Wii nunchuck.

frwind » 18 мар 2011, 13:28

Да долго пропарился с инициализацией, пока не нашел нужного кода.

Re: Использование джойстика от приставки Wii nunchuck.

Strijar » 18 мар 2011, 13:38



Пишет, что Excludes: ...Russian Federation... Это не правда?

Re: Использование джойстика от приставки Wii nunchuck.

frwind » 18 мар 2011, 16:44

Strijar писал(а):


Пишет, что Excludes: ...Russian Federation... Это не правда?


Видать я его достал и он отказался от России :crazy:
Шло почти два месяца.
Но поддержка у них хорошая, отписываются сразу и по делу.

Добавлено спустя 3 часа 57 секунд:
Немножко подчистил, подправил, вся обработка в библиотеке, чтобы код почище был

Код: Выделить всёРазвернуть
//========================================
#include <Wire.h>
#include "nunchuck_funcs_m.h"
byte accx,accy,accz,zbut,cbut,joyx,joyy;

void setup()
{
    Serial.begin(19200);
    nunchuck_init(); // send the initilization handshake
}

void loop()
{
        nunchuck_get_data();
        accx  = nunchuck_accelx();
        accy  = nunchuck_accely();
        accz = nunchuck_accelz();
        zbut = nunchuck_zbutton();
        cbut = nunchuck_cbutton();
        joyx = nunchuck_joyx();
        joyy = nunchuck_joyy();             
        Serial.print("aX: "); Serial.print((byte)accx,DEC);
        Serial.print("\taY: "); Serial.print((byte)accy,DEC);
        Serial.print("\taZ: "); Serial.print((byte)accz,DEC);
        Serial.print("\tjX: "); Serial.print((byte)joyx,DEC);
        Serial.print("\tjY: "); Serial.print((byte)joyy,DEC);
        Serial.print("\tbZ: "); Serial.print((byte)zbut,DEC);
        Serial.print("\tbC: "); Serial.println((byte)cbut,DEC);   
}

//========================================


И в этой же папке создаем файл с именем nunchuck_funcs_m.h
в него записываем вот это

Код: Выделить всёРазвернуть
//=======nunchuck_funcs_m.h==================
/*
* Nunchuck functions  -- Talk to a Wii Nunchuck
*
* This library is from the Bionic Arduino course :
*                          http://todbot.com/blog/bionicarduino/
*
* 2007 Tod E. Kurt, http://todbot.com/blog/
*
* The Wii Nunchuck reading code originally from Windmeadow Labs
*   http://www.windmeadow.com/node/42
**
** fixed Mark, for china low cost Wii Nunchuk
*/

#include <WProgram.h>

static uint8_t nunchuck_buf[6];   // array to store nunchuck data,



// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
static void nunchuck_init()
{
 
   byte cnt21;
uint8_t ctrlr_type[6];

Wire.begin();
           
// init controller
delay(1);
Wire.beginTransmission(0x52);   // device address
Wire.send(0xF0);              // 1st initialisation register
Wire.send(0x55);              // 1st initialisation value
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0xFB);              // 2nd initialisation register
Wire.send(0x00);              // 2nd initialisation value
Wire.endTransmission();
delay(1);
           
// read the extension type from the register block       
Wire.beginTransmission(0x52);
Wire.send(0xFA);              // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6);            // request data from controller
for (cnt21 = 0; cnt21 < 6; cnt21++) {
    if (Wire.available()) {
        ctrlr_type[cnt21] = Wire.receive(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
    }
}
Wire.endTransmission();
delay(1);
           
// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.send(0xF0);              // crypto key command register
Wire.send(0xAA);              // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0x40);              // crypto key data address
for (cnt21 = 0; cnt21 < 6; cnt21++) {
    Wire.send(0x00);              // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);              // sends memory address
for (cnt21 = 6; cnt21 < 12; cnt21++) {
    Wire.send(0x00);              // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);              // sends memory address
for (cnt21 = 12; cnt21 < 16; cnt21++) {
    Wire.send(0x00);              // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init
}

// Send a request for data to the nunchuck
// was "send_zero()"
static void nunchuck_send_request()
{
    Wire.beginTransmission(0x52);// transmit to device 0x52
    Wire.send(0x00);// sends one byte
    Wire.endTransmission();// stop transmitting
}

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
static char nunchuk_decode_byte (char x)
{
    x = (x ^ 0x17) + 0x17;
    return x;
}

// Receive data back from the nunchuck,
// returns 1 on successful read. returns 0 on failure
static int nunchuck_get_data()
{
    int cnt=0;
    Wire.requestFrom (0x52, 6);// request data from nunchuck
    while (Wire.available ()) {
        // receive byte as an integer
        nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
        cnt++;
    }
    nunchuck_send_request();  // send request for next data payload
    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5) {
        return 1;   // success
    }
    return 0; //failure
}


// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_zbutton()
{
    return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1;  // voodoo
}

// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_cbutton()
{
    return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1;  // voodoo
}

// returns value of x-axis joystick
static int nunchuck_joyx()
{
    return nunchuck_buf[0];
}

// returns value of y-axis joystick
static int nunchuck_joyy()
{
    return nunchuck_buf[1];
}

// returns value of x-axis accelerometer
static int nunchuck_accelx()
{
    return nunchuck_buf[2];   // FIXME: this leaves out 2-bits of the data
}

// returns value of y-axis accelerometer
static int nunchuck_accely()
{
    return nunchuck_buf[3];   // FIXME: this leaves out 2-bits of the data
}

// returns value of z-axis accelerometer
static int nunchuck_accelz()
{
    return nunchuck_buf[4];   // FIXME: this leaves out 2-bits of the data
}
//========================================

Re: Использование джойстика от приставки Wii nunchuck.

Angel71 » 19 мар 2011, 21:00

Strijar, отправили по запарке наверно, бывает. но лучше брать у тех, у кого страна (пока ещё?) не в исключениях. :) хлопот меньше.
этот на данный момент самый недорогой при штучном заказе http://cgi.ebay.com/New-nunchuk-nunchuck-controller-remote-Nintendo-Wii-/280644087525?pt=Video_Games_Accessories&hash=item4157b0eee5 (поиск по "Wii nunchuck" с включённым "Buy It Now" и сортировкой "Price + Shipping: lowest first")
П.С. еще есть "wii wireless nunchuck", значительно дороже (редко за 7..10, обычно 10..20), но штука крайне приятная. дешевле можно, но в основном это если торговаться на аукционе.

Re: Использование джойстика от приставки Wii nunchuck.

Myp » 01 апр 2011, 09:32

на молотке проводной за 250р. беспроводной за 500р.

Re: Использование джойстика от приставки Wii nunchuck.

landStalker » 01 апр 2011, 20:19

Myp писал(а):на молотке проводной за 250р. беспроводной за 500р.



Сразу же захотел себе такое дело для дуины

Что лучше с Молотка заказать себе беспроводной или китайских с ебая штук 5 1$? есть у кого опыт заказа с ебая или кто может помочь с оформлением????


Добавлено спустя 2 часа 54 минуты 41 секунду:
всё в это же топку

Вот такой вот переходник!

Изображение
Изображение
Изображение
Изображение


Можно и самим замутить =)

Изображение
Изображение


Вот и мануал вроде как за буржуйском сайте!
http://www.instructables.com/id/Wii-Nunchuck-Adapter/
Изображение


Ну конечно же вот такой вот девайсь заводской!
http://www.hvwtech.com/products_view.asp?ProductID=1081

Изображение
Изображение

Re: Использование джойстика от приставки Wii nunchuck.

Angel71 » 01 апр 2011, 21:00

на молотке большинство нунчак с ибея, только быстрей приедет и немного дороже. :) оригинальные стоят в разы дороже. :D и под видом оригиналов многие торгуют именно аналогами.

Re: Использование джойстика от приставки Wii nunchuck.

landStalker » 01 апр 2011, 21:10

Тогда вопрос frwind подойдет ли беспроводной нунчак под этот протокол?(тоже самое что и проводной только беспроводной???)

Ну кто поделится опытом в покупке с ибея???

Re: Использование джойстика от приставки Wii nunchuck.

avr123.nm.ru » 01 апр 2011, 23:15

Arduino nano наверно уместней в данном прожекте.

Re: Использование джойстика от приставки Wii nunchuck.

landStalker » 01 апр 2011, 23:54

avr123.nm.ru писал(а):Arduino nano наверно уместней в данном прожекте.


Это почему?какая разница?(ну только в размерах)


Rambler\'s Top100 Mail.ru counter