Сделал джойстик для игры World of Tanks, проект получился совсем простой легкий для повторения, изучения работы шины I2C и взаимодействия с нунчаком wii. В проекте использовался клон ардуино микро Freaduino Micro v1.2 но может быть использовано Леонардо и Микро. Для работы нунчака нужно соединить его с ардуиной линии SDA SCL у каждой ардуины в другом месте для Freaduino Micro v1.2 это d4 и d3 соответственно.
Код (C): // запустить систему I2C, подсоединиться к шине I2C, // и сообщить нунчаку, что мы с ним разговариваем void nunchuck_init() { //======================================== byte cnt; uint8_t ctrlr_type[6]; Wire.begin(); // Начинаем разговор с нунчаком // Хитрая инициализация китайского нунчака delay(1); Wire.beginTransmission(0x52); // Адрес устройства Wire.write(0xF0); // 1st initialisation register Wire.write(0x55); // 1st initialisation value Wire.endTransmission(); delay(1); Wire.beginTransmission(0x52); Wire.write(0xFB); // 2nd initialisation register Wire.write(0x00); // 2nd initialisation value Wire.endTransmission(); delay(1); // read the extension type from the register block Wire.beginTransmission(0x52); Wire.write(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.read(); // 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.write(0xF0); // crypto key command register Wire.write(0xAA); // sends crypto enable notice Wire.endTransmission(); delay(1); Wire.beginTransmission(0x52); Wire.write(0x40); // crypto key data address for (cnt = 0; cnt < 6; cnt++) { Wire.write(0x00); // sends 1st key block (zeros) } Wire.endTransmission(); Wire.beginTransmission(0x52); Wire.write(0x40); // sends memory address for (cnt = 6; cnt < 12; cnt++) { Wire.write(0x00); // sends 2nd key block (zeros) } Wire.endTransmission(); Wire.beginTransmission(0x52); Wire.write(0x40); // sends memory address for (cnt = 12; cnt < 16; cnt++) { Wire.write(0x00); // sends 3rd key block (zeros) } Wire.endTransmission(); delay(1); // конец инициализации нунчака //======================================== } здесь начало разговора с КИТАЙСКИМ нунчаком они дешевле. естественно в самом начале кода #include <Wire.h> // Библиотека I2C
Пример из презентации Bionic arduino наглядно иллюстрирует взаимодействие с нунчака Wii с ардуино. скачать ее можно отсюдаскачать он выглядит так: Код (C): /* * NunchuckPrint * * 2007 Tod E. Kurt, http://todbot.com/blog/ * * Код для считывания Wii-Нунчака взят из Windmeadow Labs * http://www.windmeadow.com/node/42 */ #include <Wire.h> void setup() { Serial.begin(19200); nunchuck_init(); // инициализация соединения Serial.print ("Finished setup\n"); } void loop() { nunchuck_get_data(); nunchuck_print_data(); delay(100); } // // Функции Нунчака // static uint8_t nunchuck_buf[6]; // массив для хранения данных нунчака, // запустить систему I2C, подсоединиться к шине I2C, // и сообщить нунчаку, что мы с ним разговариваем void nunchuck_init() { Wire.begin(); // подключиться к i2c как ведущий Wire.beginTransmission(0x52); // передать на устройство 0x52 Wire.send(0x40); // передать адрес в памяти Wire.send(0x00); // передать нуль Wire.endTransmission(); // остановить передачу } // Посылает нунчаку запрос о данных // было "send_zero()" void nunchuck_send_request() { Wire.beginTransmission(0x52); // передать на устройство 0x52 Wire.send(0x00); // передать один байт Wire.endTransmission(); // остановить передачу } // Получить данные от нунчака, int nunchuck_get_data() { int cnt=0; Wire.requestFrom (0x52, 6); // запросить данные у нунчака while (Wire.available ()) { // получить байт как целое число nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive()); cnt++; } nunchuck_send_request(); // послать запрос о следующей // порции данных // Если мы получили 6 байтов, тогда напечатаем их if (cnt >= 5) { return 1; // успех } return 0; //неудача } // Печатаем полученные данные // Акселерометр выдаёт 10 бит // Так что мы считываем 8 битов, затем нужно добавить // последние 2 бита. Поэтому я // умножаю их на 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; // байт nunchuck_buf[5] содержит биты для кнопок z и c // также содержит младшие биты для с данными акселерометра // так что посмотрим каждый бит байта 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"); // новая срока i++; } // Перекодировать данные в формат, который принимают // большинство драйверов wiimote. Нужно только, если // используете один из стандартных драйверов wiimote char nunchuk_decode_byte (char x) { x = (x ^ 0x17) + 0x17; return x; } инициализация значительно короче но с моим нунчаком это не заработало, возможно с вашим заработает.
теперь когда научились читать данные с нунчака хорошо бы научиться что-то делать с ними, в моем случае это просто эмитировать клавиатуру (пробовал и мышь эмитировать но это хоть и забавно но не очень удобно), как это делается? команда Arduino выпустив Леонардо и Мини, встроила в их драйвера возможность эмитировать мышь и клавиатуру для этого надо лишь объявить что они будут использоваться: Mouse.begin(); // для мышки Keyboard.begin(); // для клавиатуры Далее loop Keyboard.press('A'); // нажать латинскую букву A Keyboard.release('A'); // отжать латинскую букву A Keyboard.write(KEY_TAB); нажать и отжать клавишу TAB и самая интересная команда Keyboard.println("hello world"); она последовательно вышлет все буквы а потом еще и Enter нажмет. и такая же только без Enter в конце. Keyboard.print("hello world"); для клавиатуры это все за полным списком сокращений служебных клавиш ходим сюда сюда у мыши левая кнопка 1 правая 2 колесо 3 Mouse.click () // "кликает" нажимает и тут же отжимает. Mouse.move (10,0,-2) перемещает указатель на вектор указный в скобках, третий параметр это колесо мыши вращение Mouse.press (1) // нажать кнопку в скобках какую Mouse.release () // отжать кнопку в скобках какую Mouse.isPressed () // проверяет нажата ли кнопка которая указана в скобках // подробнее смотрим тут // все это веселье возможно только если у вас среда разработки версии 1.0.2 или выше