devkitPro/libogc

WPAD: Unable to read any Motion Plus data from the Wiimote

TheSunCat opened this issue · 3 comments

I seem to be unable to get any data from the MotionPlus extension on my Wiimote, or from the integrated MotionPlus on another Wiimote.

Unfortunately my Wii is not usable atm so I am running my code on Dolphin, but I doubt it would make much of a difference.

It's likely this is an error on my part, but I have not had much luck finding examples of reading the Motion Plus sensors using WPAD, and the code seems correct to me.

Here is my current setup:

u32 type;
WPADData* wd;

PAD_Init();
WPAD_Init();

WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);

while(1) {
WPAD_ReadPending(WPAD_CHAN_ALL, countevs);

int err = WPAD_Probe(0, &type);
switch(err) {
    case WPAD_ERR_NO_CONTROLLER:
        print("WIIMOTE NOT CONNECTED");
        break;
    case WPAD_ERR_NOT_READY:
        print("WIIMOTE NOT READY");
        break;
    case WPAD_ERR_NONE:
        print("WIIMOTE READY");
        break;
    default:
        print("UNK WIIMOTE STATE %d", err);
}
print("EVENT COUNT: %d", evctr);

if(err == WPAD_ERR_NONE) {
    wd = WPAD_Data(0);
    print("DATA ERR: %d",wd->err);
    
    print("\n");
    print("ACCEL:");
    print("X: %3d", wd->accel.x);
    print("Y: %3d", wd->accel.y);
    print("Z: %3d", wd->accel.z);

    print("\n");
    print("ORIENT:");
    print("PITCH: %.02f",wd->orient.pitch);
    print("YAW: %.02f",wd->orient.yaw); // frozen at 0.00
    print("ROLL: %.02f",wd->orient.roll);

    print("\n");
    print("MP:");
    print("PITCH: %.02f",wd->exp.mp.rx); // frozen at 0.00
    print("YAW: %.02f",wd->exp.mp.ry); // frozen at 0.00
    print("ROLL: %.02f",wd->exp.mp.rz); // frozen at 0.00

    print("\n");
    print("GFORCE:");
    print("X: %.02f",wd->gforce.x);
    print("Y: %.02f",wd->gforce.y);
    print("Z: %.02f",wd->gforce.z);
}

Here is the data I am seeing (what isn't 0 does change when I move the wiimote):
image

Hey, sorry for the late reply!

this seems to be an issue to both your code and wiiuse.
in your code im not seeing any call to WPAD_SetMotionPlus, which either enables or disables the motion plus.
however, there is also a bug in wiiuse that doesn't read the motion plus data unless another expansion is inserted.

as soon as i inserted a nunchuck in my wiimote and moved it around, motion plus data seemed to be streaming in and the expansion type i got from WPAD_Expansion was 5 ( EXP_MOTION_PLUS ).

ill see if i can figure out why this is the case.

used code :

WPAD_Init();
//loop so i can connect the wiimote before calling SetMotionPlus to enabled.
//this needs to be called after the wiimote connected
while(1)
{
	PAD_ScanPads();
	u32 gcPressed = PAD_ButtonsDown(0);
	if ( gcPressed & PAD_BUTTON_A) break;
}

printf("set motion plus on all wiimotes : %d\n", WPAD_SetMotionPlus(-1, 1));

...the rest of your code here ... 

(run on actual hardware)
image_20-11-2021-15-23

ok, so im not sure 100% whats going on, but it seems the first few wiimote events are without the motion plus data, but after a while (few ms) it constantly reports with the motion plus data.

@RealTheSunCat : could you verify that just adding the WPAD_SetMotionPlus wiimotes' motion plus works?

Hi! Thanks for the response :)
Adding WPAD_SetMotionPlus seems to have fixed it!

This is my final code:

// loop so i can connect the wiimote before calling SetMotionPlus to enabled.
// this needs to be called after the wiimote connected
while(1)
{
    WPAD_ScanPads();
    u32 gcPressed = WPAD_ButtonsDown(0);
    if (gcPressed & WPAD_BUTTON_A) break;

    printf("Scanning pads... %i", gcPressed);
}

WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);

printf("set motion plus on all wiimotes : %d\n", WPAD_SetMotionPlus(-1, 1));

WPADData* wd;

while(1) {

    // Call WPAD_ScanPads each loop, this reads the latest controller states
    WPAD_ScanPads();

    int err = WPAD_Probe(0, &type);
    switch(err) {
        case WPAD_ERR_NO_CONTROLLER:
            printf("WIIMOTE NOT CONNECTED\n");
            break;
        case WPAD_ERR_NOT_READY:
            printf("WIIMOTE NOT READY\n");
            break;
        case WPAD_ERR_NONE:
            printf("WIIMOTE READY\n");
            break;
        default:
            printf("UNK WIIMOTE STATE %d\n", err);
    }

    if(err == WPAD_ERR_NONE) {
        wd = WPAD_Data(0);
        // print everything
    }

    // Wait for the next frame
    VIDEO_WaitVSync();
}