Moin.
Ich hänge gerade bei dem Problem, eine Wii MotionPlus mit daranhängendem Nunchuk auszulesen; das ganze über den Passthrough-Modus.
Initialisier ich den Nunchuk allein, kann ich den problemlos auslesen. Initialisier ich die MotionPlus allein, kann ich die auch fehlerfrei auslesen.
Start ich jedoch den Passthrough-Modus (wie in http://wiibrew.org/wiki/Wii_MotionPlus beschrieben), um beide gleichzeitig auszulesen, krieg ich aber nur die M+-Daten.
Entweder überles ich da irgendwas oder es fehlt irgend ne wichtige Angabe.
Wie ichs mach:
M+ initialisieren:
- an 0xA6 senden: 0xFE, 0x05 (Register FE, 05 = Passthrough)
Daten lesen:
- 0x00 an 0xA4 senden
- 3ms warten
- 6 Bytes von 0xA4+1 lesen
- frühestens nach 3ms wiederholen
Und da würde ich jetzt nach der Beschreibung erwarten, dass ich abwechselnd 2 verschiedene Datensätze bekomme, die einmal die M+-Daten (Byte 5, Bit 1 = 1) und einmal die Nunchuk-Daten (Byte 5, Bit 1 = 0). Letzteres ist aber nie der Fall.
"Umschalten", also M+ deaktivieren, Nunchuk lesen, M+ aktivieren, M+ lesen und wieder von vorn möcht ich vermeiden, da das Umschalten auch zusätzlich Zeit kostet und zudem auch nicht zuverlässig funktioniert.
Hat da jemand ne Lösung dafür?
mfG
#ifndef MfG
#define MfG
Hi,
bin noch nicht ganz fertig mit meiner Doku, aber hier schon mal ein erster Wurf. Die Sache mit dem Pass Through Mode funktioniert bei mir ziemlich straight Foreward wir in Wiibrew beschrieben.
Einziger Punkt: Ich frage noch keine Systemmeldungen von der Wii ab, auch sind mir die tatsächlich erforderlichen Delay-Zeiten noch nicht ganz klar, die Werte kommen allerdings sehr sauber rüber.
Allerdings beobachte ich aktuell noch, dass ich am besten mit einer unter Strom gesetzten WM+/Nunchuck- Kombi starte, ein Verlassen des Pass Through Modes hin zu einer anderen (z.B. puren WM+-) Betriebsart über ein weiteres Check Programm ist mit dem Code nciht möglich.
Diese Option ist allerdings für mich nicht wichtig, für meine Anwendung brauch' ich halt nur eine definerte Betriebsart und die muss ich nicht ändern.
Ich habe das Testprogramm auf Basis der I2C Routinen des LM Sensor Projekts gegen einen NGW100 compiliert. Das Ganze läuft in einer Buildroot Umgebung, in der ich die LMSensor Tools ebenfalls compiliert hatte (läuft mit PWM von Bill Gatcliff und I2C). Ich bin jetzt mal gespannt ob ich mein Projekt fertig kriege über Weihnachten, Ihr könnt mal raten, was rauskommen soll...
Hier mein Code, aber überholt mich jetzt nicht )
Dank an alle, die mir beim Lernen gehlolfen haben besonderer Dank an krulkip:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include "i2cbusses.h"
#include "util.h"
#define FALSE 0
#define TRUE (0==0)
// Nunchuck Defines
//#define ALWAYSZERO 0x01
//#define WM+DATA 0x02
#define NCBZ 0x04
#define NCBC 0x08
#define NCEXT 0x10
//WM+ Defines
#define ALWAYSZERO 0x01
#define WMPDATA 0x02
#define WMPEXT 0x04
#define WMPROLLSMODE 0x08 // WM+ Roll Slow Mode
#define WMPPITCHSMODE 0x10 // WM+ Pitch Slow Mode
#define WMPYAWSMODE 0x20 // WM+ Yaw Slow Mode
unsigned int getWiiData(unsigned char *, int);
int main()
{
int dev;
char filename[20];
unsigned char data[]={0,0,0,0,0,0};
unsigned char wmpModes;
short int yaw=0,yaw0=0;
short int pitch=0,pitch0=0;
short int roll=0,roll0=0;
unsigned char ncModes;
short int joy_x=0,joy_y=0;
short int accel_x=0,accel_x0=0;
short int accel_y=0,accel_y0=0;
short int accel_z=0,accel_z0=0;
// open I2C device
dev = open_i2c_dev(0, filename, 0);
usleep(3000);
// now make Wii Motion plus the active extension
// nunchuk mode = 05, wm+ only = 04, classic controller = 07
set_slave_addr(dev, 0x53, FALSE); // wm+: 0x53 nunchuck: 0x52, 0
usleep(3000);
i2c_smbus_write_byte_data(dev, 0xFE, 0x05); // wm+: 0xFE 0x04 nunchuck: 0x40, 0x00
usleep(3000);
set_slave_addr(dev, 0x52, FALSE); // wm+: 0x52 nunchuck: 0x52, 0
usleep(3000);
for(;
{
if(getWiiData(data, dev)){
if(data[5]&WMPDATA) {
// Found WM+:
/* Decoding the data from wm+:
Bit
Byte 7 6 5 ... 1 0
0 Yaw Down Speed<7:0>
1 Roll Left Speed<7:0>
2 Pitch Left Speed<7:0>
3 Yaw Down Speed<13:8> Yaw slow mode<1> Pitch slow mode<0>
4 Roll Left Speed<13:8> Roll slow mode<1> Ext. connected<0>
5 Pitch Left Speed<13:8> 1 0
*/
//see http://wiibrew.org/wiki/Wiimote Extension_Controllers#Wii_Motion_Plus
wmpModes = (data[3] & 0x03)<<4; // wichtig für SlowMode-Berechungen
wmpModes |= (data[4] & 0x03)<<2;
wmpModes |= (data[5] & 0x03)<<0;
yaw=((data[3]>>2)<<+data[0]-yaw0;
pitch=(short int)(((data[4]>>2)<<+data[1])-pitch0;
roll=((data[5]>>2)<<+data[2]-roll0;
printf("WM+: %u,%u,%u,SM:%u\n",yaw,pitch,roll,
wmpModes&(WMPROLLSMODE|WMPYAWSMODE|WMPPITCHSMODE)) ;
} else {
// Found Nunchuck:
/* Decoding the data of Nunchuck (Passthrough mode):
Bit
Byte 7 ... 5 4 3 2 1 0
0 SX<7:0>
1 SY<7:0>
2 AX<9:2>
3 AY<9:2>
4 AZ<9:3> Ext. connected
5 AZ<2:1> AY<1> AX<1> BC BZ 0 0
*/
ncModes = (data[4] & 0x01) << 4;
ncModes |= data[5] & 0x0F;
joy_x = data[0];
joy_y = data[1];
accel_x = (data[2] << 1) + ((data[5] & 0x10) >> 4);
accel_y = (data[3] << 1) + ((data[5] & 0x20) >> 5);
accel_z = ((data[4]&0xfe) << 1) + ((data[5] & 0xc0) >> 6);
printf("NC: %u,%u,%u\n",accel_x,accel_y,accel_z);
}
}
}
}
unsigned int getWiiData(unsigned char *data, int dev)
{
int i=0;
unsigned char tmp[6];
i2c_smbus_write_byte(dev, 0);
usleep(3000);
for (i = 0; i <= 5; i++)
{
tmp[i] = (unsigned char) i2c_smbus_read_byte(dev);
usleep(3000);
if (tmp[i] > 253) {break;}
}
// nur kopieren, wenn Schleifenlauf erfolgreich:
if(i<6) return FALSE;
for (i = 0; i <= 5; i++) *(data+i)=tmp[i];
return TRUE;
}
Output:
WM+: 8054,7217,8021,SM:56
NC: 352,292,285
WM+: 8043,7213,8020,SM:56
NC: 352,292,284
WM+: 8052,7210,8022,SM:56
NC: 352,292,284
WM+: 8062,7207,8027,SM:56
NC: 352,292,284
WM+: 8047,7210,8024,SM:56
NC: 352,292,284
WM+: 8052,7216,8033,SM:56
NC: 352,292,284
WM+: 8049,7198,8022,SM:56
NC: 352,292,284
WM+: 8053,7210,8026,SM:56
NC: 352,292,284
WM+: 8041,7213,8021,SM:56
NC: 352,292,284
WM+: 8052,7205,8021,SM:56
NC: 352,292,284
WM+: 8054,7202,8022,SM:56
NC: 352,292,284
....
Grüsse
tuxrupert
Lesezeichen