Wii как джойстик для World of Tanks

Тема в разделе "Глядите, что я сделал", создана пользователем id90, 7 авг 2013.

  1. id90

    id90 Нерд

    Сделал джойстик для игры World of Tanks, проект получился совсем простой легкий для повторения, изучения работы шины I2C и взаимодействия с нунчаком wii. В проекте использовался клон ардуино микро Freaduino Micro v1.2 но может быть использовано Леонардо и Микро.
    [​IMG]


    Для работы нунчака нужно соединить его с ардуиной [​IMG]
    линии SDA SCL у каждой ардуины в другом месте для Freaduino Micro v1.2 это d4 и d3 соответственно.
     
  2. id90

    id90 Нерд

    Код (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
     
  3. id90

    id90 Нерд

    Пример из презентации 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;
    }
    инициализация значительно короче но с моим нунчаком это не заработало, возможно с вашим заработает.
     
  4. id90

    id90 Нерд

    теперь когда научились читать данные с нунчака хорошо бы научиться что-то делать с ними, в моем случае это просто эмитировать клавиатуру (пробовал и мышь эмитировать но это хоть и забавно но не очень удобно), как это делается? команда 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 или выше
     
    atompost нравится это.