vendredi 25 février 2011

nunchuck wii et teensy ++ 2


Aujourd'hui j'ai regardé comment interfacer un nunchuck wii avec ma teensy ++ 2.
Sur la vidéo l'axe x et y du stick contrôle 2 servos, et les boutons c et z 2 leds.



Voici un bout de code qui ma bien aidé: (pour les nunchuck non officiel ex:ebay ne fonctionne pas avec un original)
/*
** This code works with a Nyko Kama Wireless nunchuk and
** a black wired nunchuk. This code has not been tested
** with any other nunchuk.
**
** To use a Wired Nunchuk just comment out the #define for WIRELESS_KAMA_NUNCHUK.
** To use a Wireless Nyko Kama Nunchuk uncomment the #define for WIRELESS_KAMA_NUNCHUK.
**
*/

#include <Wire.h>

/* Debug definitions */
#define PRINT_NUNCHUK_DATA
#define WIRELESS_KAMA_NUNCHUK    /* Comment out this line if using a Wired Nunchuk */

#define READ_DELAY        5      /* (milliseconds) - Increase this number to not read the nunchuk data so fast */
#define SERIAL_BAUD_RATE  115200

unsigned int joy_x = 0;
unsigned int joy_y = 0;
unsigned int acc_x = 0;
unsigned int acc_y = 0;
unsigned int acc_z = 0;
unsigned int btn_c = 0;
unsigned int btn_z = 0;

unsigned long previous_read_time = 0;

void setup()
{
    Serial.begin(SERIAL_BAUD_RATE);
    Wire.begin();
   
    initialize_nunchuk();

    previous_read_time = millis();
}

void loop()
{
    if (millis() - previous_read_time > READ_DELAY)
    {
        read_nunchuk_data();
        previous_read_time = millis();
    }
}

void read_nunchuk_data()
{
    unsigned int buffer[6];
    byte buffer_index = 0;
 
    Wire.beginTransmission(0x52);
    Wire.send(0x00);
    Wire.endTransmission();
   
#ifndef WIRELESS_KAMA_NUNCHUK   
    delay(1); /* This delay is required for a wired nunchuk otherwise the data will appear maxed out */
#endif
 
    Wire.requestFrom(0x52, 6);
    while(Wire.available())   
    {
        buffer[buffer_index] = Wire.receive();
        buffer_index++;
    }
   
    joy_x = buffer[0];
    joy_y = buffer[1];
    acc_x = ((buffer[2] << 2) | ((buffer[5] & 0x0C) >> 2) & 0x03FF);
    acc_y = ((buffer[3] << 2) | ((buffer[5] & 0x30) >> 4) & 0x03FF);
    acc_z = ((buffer[4] << 2) | ((buffer[5] & 0xC0) >> 6) & 0x03FF);
    btn_c = !((buffer[5] & 0x02) >> 1);
    btn_z = !(buffer[5] & 0x01);
   
#ifdef PRINT_NUNCHUK_DATA
    Serial.print("    "); Serial.print(joy_x);
    Serial.print("      "); Serial.print(joy_y);
    Serial.print("      "); Serial.print(acc_x);
    Serial.print("       "); Serial.print(acc_y);
    Serial.print("       "); Serial.print(acc_z);
    Serial.print("        "); Serial.print(btn_c);
    Serial.print("          "); Serial.print(btn_z);
    Serial.println("");
#endif
}

void initialize_nunchuk()
{
#ifdef WIRELESS_KAMA_NUNCHUK
    Wire.beginTransmission(0x52);
    Wire.send (0xF0);
    Wire.send (0x55);
    Wire.endTransmission();
    delay(30);
 
    Wire.beginTransmission (0x52);
    Wire.send (0xFB);
    Wire.send (0x00);
    Wire.endTransmission();
    delay(30);
   
    Wire.beginTransmission(0x52);
    Wire.send (0xFA);
    Wire.endTransmission();
    delay(30);
 
    Wire.requestFrom(0x52, 6);
    Serial.print("Device ID is: ");
    while(Wire.available()) 
    {
        byte c = Wire.receive();
        Serial.print(c, HEX);
        Serial.print(" ");
    }
    delay(30);
   
#else
    Wire.beginTransmission(0x52);
    Wire.send (0x40);
    Wire.send (0x00);
    Wire.endTransmission();
    delay(30);
#endif

#ifdef PRINT_NUNCHUK_DATA   
    Serial.println(""); 
    Serial.println("  X-axis   Y-axis   X-accel   Y-accel   Z-accel   C-button   Z-button");#endif
}
Fonctionne sur les copies ainsi que pour les nunchuck sans fils.


Voici un code qui devrai marcher avec les nunchuck officiel (non testé):

#include <Wire.h>
#include <string.h>

#undef int
#include <stdio.h>

uint8_t outbuf[6];  // array to store arduino output
int cnt = 0;
int ledPin = 13;

void
setup ()
{
  beginSerial (19200);
  Serial.print ("Finished setup\n");
  Wire.begin ();  // join i2c bus with address 0x52
  nunchuck_init (); // send the initilization handshake
}

void
nunchuck_init ()
{
  Wire.beginTransmission (0x52); // transmit to device 0x52
  Wire.send (0x40);  // sends memory address
  Wire.send (0x00);  // sends sent a zero.  
  Wire.endTransmission (); // stop transmitting
}

void
send_zero ()
{
  Wire.beginTransmission (0x52); // transmit to device 0x52
  Wire.send (0x00);  // sends one byte
  Wire.endTransmission (); // stop transmitting
}

void
loop ()
{
  Wire.requestFrom (0x52, 6); // request data from nunchuck
  while (Wire.available ())
    {
      outbuf[cnt] = nunchuk_decode_byte (Wire.receive ()); // receive byte as an integer
      digitalWrite (ledPin, HIGH); // sets the LED on
      cnt++;
    }

  // If we recieved the 6 bytes, then go print them
  if (cnt >= 5)
    {
      print ();
    }

  cnt = 0;
  send_zero (); // send the request for next bytes
  delay (100);
}

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

  int z_button = 0;
  int c_button = 0;

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

  if ((outbuf[5] >> 2) & 1)
    {
      accel_x_axis += 2;
    }
  if ((outbuf[5] >> 3) & 1)
    {
      accel_x_axis += 1;
    }

  if ((outbuf[5] >> 4) & 1)
    {
      accel_y_axis += 2;
    }
  if ((outbuf[5] >> 5) & 1)
    {
      accel_y_axis += 1;
    }

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

  Serial.print (joy_x_axis, DEC);
  Serial.print ("\t");

  Serial.print (joy_y_axis, DEC);
  Serial.print ("\t");

  Serial.print (accel_x_axis, DEC);
  Serial.print ("\t");

  Serial.print (accel_y_axis, DEC);
  Serial.print ("\t");

  Serial.print (accel_z_axis, DEC);
  Serial.print ("\t");

  Serial.print (z_button, DEC);
  Serial.print ("\t");

  Serial.print (c_button, DEC);
  Serial.print ("\t");

  Serial.print ("\r\n");
}

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

1 commentaire:

  1. beginSerial (19200);
    // is
    Serial.begin(19200);

    The original nunchuck code not work.

    RépondreSupprimer