Una de las mejores cosas que tiene la electrónica es que puedes usar aparatos que se fabrican en serie con unas características increibles a precios muy bajos. En esta ocasión voy a explicar cómo usar el nunchuk de la wii para poder adaptarlo a vuestros proyectos electrónicos. En este artículo me centraré en la plataforma Arduino.
No es necesario tener la wii para adquirir un nunchuk, de hecho ni siquiera tiene por qué ser el oficial, un clónico puede llegar a costar 7 €. Por otra parte es necesario tener el wiichuck, que es un adaptador para el nunchuk con una tira de pines y hace más manejable el uso de este (no supera los 4€).
El nunchuk trabaja con una tensión de 3,3 v., pero también puede hacerlo a 5 v. (Limitando su vida útil, pero por 7€ …). Funciona mediante el bus I2C en su variante Fast (400Kb/s) y lo que podemos leer son los datos del acelerómetro XYZ, del joystick y de los dos botones que contiene. Lo que haré en este artículo es recuperar esa información y mostrarla por el puerto serie.
Para empezar hay que inicializar el nunchuk de la siguiente forma:
- Enviar a la dirección 0x52 los bytes 0xF0 y 0x55.
- Enviar a la dirección 0x52 los bytes 0xFB y 0x00.
A partir de entonces cada vez que queramos leer los datos tenemos que:
- Enviar a la dirección 0x52 el byte 0x00.
- Leer de la dirección 0x52 seis bytes.
Los 6 bytes que hemos leido contienen la información del acelerómetro, del joystick y de los botones, pero vienen formateados:
- Primer byte: La posición X del joystick (0-255)
- Segundo byte: La posición Y del joystick (0-255)
- Tercer byte: Los 8 bits de mayor peso del eje X del acelerómetro (Finalmente tendrá un valor entre 0 y 1023)
- Cuarto byte: Los 8 bits de mayor peso del eje Y del acelerómetro (Finalmente tendrá un valor entre 0 y 1023)
- Quinto byte: Los 8 bits de mayor peso del eje Z del acelerómetro (Finalmente tendrá un valor entre 0 y 1023)
- Sexto byte: que contiene
- los dos bits de menor peso del eje Z del acelerómetro
- los dos bits de menor peso del eje Y del acelerómetro
- los dos bits de menor peso del eje X del acelerómetro
- Un bit indicando el estado del botón C (0 si pulsado, 1 si no lo está)
- Un bit indicando el estado del botón Z (0 si pulsado, 1 si no lo está)
Tomaremos los 3,3 v. y la masa que ofrece arduino, conectaremos el pin de data del wiichuck al pin analógico 4 y el pin de clock al pin analógico 5. No son necesarias las resistencias pull-up típicas del bus I2C ya que los pines analógicos 4 y 5 ya las tienen implementadas internamente y son activadas al inicializar la librería wire:
El código fuente simplificado al máximo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include <Wire.h> // Necesario para trabajar con el bus I2C #include <utilitytwi.h> // Necesario para la constante CPU_FREQ void setup() { Serial.begin(4800); // Inicializamos el puerto serie a una velocidad baja para que se puedan ver los datos Wire.begin(); // Inicializamos la librería wire para trabajar con I2C TWBR = ((CPU_FREQ / 400000L) - 16) / 2; // Configuramos el I2C para el modo Fast (400Kb/s) // Inicializamos el nunchuk sin encriptación Wire.beginTransmission(0x52); Wire.send(0xF0); Wire.send(0x55); Wire.endTransmission(); Wire.beginTransmission(0x52); Wire.send(0xFB); Wire.send(0x00); Wire.endTransmission(); } void loop () { uint8_t buffer[6]; // Pedimos que se actualicen los datos Wire.beginTransmission(0x52); Wire.send(0); Wire.endTransmission(); // Recogemos y guardamos los datos Wire.requestFrom(0x52, 6); for(int indice = 0; indice < 6; indice++) { buffer[indice] = Wire.receive(); } // Imprimimos los datos en el puerto serie Serial.print("JX:"); Serial.print(buffer[0], DEC); Serial.print(" JY:"); Serial.print(buffer[1], DEC); Serial.print(" AX:"); Serial.print((buffer[2] << 2) | ((buffer[5] & 0x0c) >> 2)); Serial.print(" AY:"); Serial.print((buffer[3] << 2) | ((buffer[5] & 0x30) >> 4)); Serial.print(" AZ:"); Serial.print((buffer[4] << 2) | ((buffer[5] & 0xc0) >> 6)); Serial.print(" C:"); Serial.print((buffer[5] >> 1) & 1); Serial.print(" Z:"); Serial.println(buffer[5] & 1); } |
Y así es como se ven los datos de una de las pruebas que he hecho:
Si os ha gustado me plantearé hacer otro artículo donde explico cómo hacer lo mismo para microcontroladores AVR y PIC.