Wii 눈척살펴보기 여기에서는 Wii 눈척 (Nunchuk) 의데이터처리에대해서살펴봅니다. 위눈척 (Wii nunchuk) 는 3축 (X Y Z) 가속도를측정할수있는장치로 ST사의 LIS3L02AL 소자를사용하고내부 MCU 가 I2C 방식으로데이터를처리해줍니다. 따라서사용자는 I2C 통신과해당통신프로토콜을이해하여접속사용하면됩니다. 멀티위콥터에서눈척은수평기능유지센서로사용되며, 보다편한비행이가능하도록합니다. 센서관련상세관련자료는 http://wiibrew.org/wiki/wiimote/extension_controllers 웹자료참조바랍니다. 눈척모양 X축이동 Y축이동 ( 중앙값 :512) ( 중앙값 :512) 각부구성 Z 축이동 ( 중앙값 :512) NunChuck 핀기능 1. 적색 : +3.3V 2.Nc 3. 황색 : SCL 4. 녹색 :SDA 이부분 5. 백색 : GND 잘라내도됨 6. 흑색 : GND 작성 : 2010.11.04 KCO 핀기능 1
Wii 눈척신호연결 AVR 과직접연결의경우 아두이노 AVR 핀 I2C 통신연결 A5 A4 눈척커넥터 SCL SDA 눈척을모션플러스를통과하여연결하는경우 눈척데이터 ( 통과모드, Pass-through mode) 눈척데이터 ( 단독동작모드 ) 2
I2C 통신포맷및눈척통신프로토콜 I2C 데이터예 ) 이데이터값은 0x52 읽기 =1 쓰기 =0 I2C 통신데이터를다룰때, 가끔혼란스러운경우가있습니다. 함수에따라위의데이터를 0x52 로다루는경우도있고, 0xA4( 쓰기 ), 0xA5( 읽기 ) 로다루는경우도있죠. 그이유는 R/W 비트를빼고위의 7 비트값만읽느냐? 또는전체값으로읽느냐에따라달라지므로이점에주의하시면됩니다. 앞에서도살펴보았지만눈척을단독으로연결하여사용하는경우데이터형태는아래와같습니다. Joystick X = 눈척위부분에있는조이스틱 X값으로 8비트크기이므로중앙값이128 이고 0 ~ 255 범위의값을갖겠죠? Joystick Y = 눈척위부분에있는조이스틱 Y값으로 8비트크기이므로중앙값이128 이고 0 ~ 255 범위의값. Accelerometer X = X축가속도값, 10비트크기이므로 0 ~ 1023 범위값. Accelerometer Y = Y 축가속도값, 10 비트크기이므로 0 ~ 1023 범위값. Accelerometer Z = Z축가속도값, 10비트크기이므로 0 ~ 1023 범위값. C 및 Z 버튼 : 버튼은누르면 0, 놓으면 1로됨 한가지주의가필요한것은눈척을단독모드로사용시에는읽은데이터에아래와같이 decoding 후사용해야되고, 통과모드로사용시에는그냥사용하시면되는데, 왜이렇게하는지저도궁금해요.( 아마분석이어렵도록닌텐도개발자가시큐리티처리?) 사용데이터 = ( 읽은데이터 XOR 0x17) + 0x17 3
눈척통신프로토콜 : 단독사용모드 눈척초기화명령 : 눈척을초기화하는명령으로처음한번실행해주어야함. 0xA4( 또는 0x52) 0x40 0x00 순서로쓰기 눈척변환시작명령 : 눈척에게 6바이트데이터를저장하라는명령으로데이터를읽기전에실행해주어야함 0xA4( 또는 0x52) 0x00 순서로쓰기참고 : 변환에약간시간이소요되는것같음. 이명령후약간의지연후데이터를읽거나또는데이터읽은후, 다음데이터변환을위해서이명령을실해하기도함 눈척데이터읽기 : 6 바이트눈척데이터를읽기위해 0xA5( 또는 0x53) 쓰기후연속으로 6 바이트데이터를읽어오면됨. 4
아두이노프로그램소스 눈척시험용프로그램 // 2010.11.4 KCO // Wii Nunchuk test 0: 통신터미널로데이터확인 #include <Wire.h> 1: PROCESSING 그래프로확인 #define forprocessing 1 byte data[6]; // six data bytes word accx,accy,accz; byte joy_x,joy_y; byte z_button,c_button; void initnc(){ Wire.begin(); Wire.beginTransmission(0x52); // address 0x52, (0x52<<1 = 0xA4) Wire.send(0x40); Wire.send(0x00); Wire.endTransmission(); void SendZero(){ Wire.beginTransmission(0x52); // now at address 0x52 Wire.send(0x00); // send zero to signal Wire.endTransmission(); static char nc_decode_byte (char x){ x = (x ^ 0x17) + 0x17; return x; void receivedata(){ Wire.requestFrom(0x52,6); for (int i=0;i<6;i++){ data[i] = nc_decode_byte(wire.receive()); SendZero(); // send zero before each request accx = ((data[2]<<2) ((data[5]>>2) & 0x3)); accy = ((data[3]<<2) ((data[5]>>4) & 0x3)); accz = ((data[4]<<2) ((data[5]>>6) & 0x3)); joy_x = data[0]; joy_y = data[1]; void setup(){ Serial.begin(115200); delay(100); initnc(); delay(100); void loop(){ receivedata(); //receive data and calculate yaw pitch and roll if(forprocessing){ Serial.print('N',BYTE); // Nunchuck = 10bit Serial.print((accx>>8) & 0xff,BYTE); Serial.print(accx & 0xff,BYTE); Serialprint((accy>>8) Serial.print((accy>>8) & 0xff,BYTE); Serialprint(accy Serial.print(accy & 0xff,BYTE); Serial.print((accz>>8) & 0xff,BYTE); Serial.print(accz & 0xff,BYTE); Serial.print(joy_x,BYTE); Serial.print(joy_y,BYTE); Serial.print(0x0d,BYTE); else{ Serial.print("\n\r"); Serial.print("X="); Serial.print(accx,DEC); Serial.print("\tY="); Serial.print(accy,DEC); Serial.print("\tZ="); Serial.print(accz,DEC); Serial.print( print("\tjx="); Serial.print(joy_x,DEC); Serial.print("\tjY="); Serial.print(joy_y,DEC); delay(20); 5
눈척데이터관찰 아두이노프로그램 여기눌러서 통신으로데이터관찰 시험장치모습 6
프로세싱프로그램소스 눈척시험용프로그램 // 2010.11.04 KCO void draw(){ import processing.serial.*; int cr, cnt=0, cnt_old=0; Serial port; // Create object from Serial class while (port.available() >= 10) { int val0,val1,val2,val3,val4; // Data received from the serial if (port.read() == 'N') { port val0 = (port.read() << 8) (port.read()); int[] values0; val1 = (port.read() << 8) (port.read()); int[] values1; int[] values2; int[] values3; int[] values4; val2 = (port.read() << 8) (port.read()); val3 = port.read(); val4 = port.read(); cr = port.read(); cnt++; 포트번호적절히변경사용 void setup() { if(cnt!= cnt_old){ size(640, 480); port = new Serial(this, "COM155", 115200); // Change COM port values0 = new int[width]; values1 = new int[width]; values2 = new int[width]; values3 = new int[width]; values4[i] = values4[i+1]; values4 = new int[width]; smooth(); int gety(int val) { return (int)(val/1023.0f * (height-1)); // NC: 10 bit data background(0); for (int x=1; x<width; x++) { cnt_old = cnt; for (int i=0; i<width-1; i++){ values0[i] = values0[i+1]; values1[i] = values1[i+1]; values2[i] = values2[i+1]; values3[i] = values3[i+1]; values0[width-1] = val0; values1[width-1] = val1; values2[width-1] = val2; values3[width-1] = val3; values4[width-1] = val4; stroke(255,0,0); // Red,accX line(width-x, height-1-gety(values0[x-1]), width-1-x, height-1-gety(values0[x])); stroke(0,255,0); // Green,accY line(width-x, height-1-gety(values1[x-1]), width-1-x, height-1-gety(values1[x])); stroke(0,0,255); // Blue,accZ line(width-x, idth height-1-gety(values2[x-1]), ht ty( 1]) width-1-x, height-1-gety(values2[x])); ht ty( stroke(255,255,0); // joy_x line(width-x, height-1-gety(values3[x-1]), width-1-x, height-1-gety(values3[x])); stroke(0,255,255); // joy_y line(width-x, height-1-gety(values4[x-1]), width-1-x, height-1-gety(values4[x])); 7
프로세싱으로눈척데이터관찰 눈척데이터를프로세싱으로관찰해봅니다. Red : accx 데이터 Green : accy 데이터 Blue : accz 데이터 Yellow : joy_x 데이터 Cyan : joy_y 데이터 8