Wii Nunchuck trouble

Reducing the speed to 4000 managed to communicate with an official nunchuck. However I don’t seem to be getting the expected data back. I’m probably mistranslating my Arduino code.

Is it possible that the Pokitto being 3.3V instead of 5V (which most Arduino boards are) is affecting your data?

I might be a noob when it comes to circuitry but I have a good memory and I remember reading that the voltage affects the data range when working with certain analogue stuff.

I don’t think so, but it’s possible. i2c is entirely digital though.
I’m getting data back from an official nunchuck, but it doesn’t seem to be initializing properly. Which is odd. However I’m am getting only 0xFF back from an official classic controller, which should be responding exactly the same ways as a nunchuck.

I was controlling Minecraft with Pokitto today. It made a very nice demo, flying around in creative mode.

1 Like

Good point, shows I haven’t been paying attention :P

That implies to me that at least one of the devices is either faulty or a knock-off (but I wouldn’t bet anything I’d care to loose on it :P).

Nope, I’m using 2 official nunchucks, 1 official classic controller, 1 official snes controller (from the snes mini) 1 official snes controller (from the wii) and 1 8bitdo wireless adapter + nes style controller.
Only the nunchucks and 8bitdo adapter are working. Although I think that the init code isn’t working correctly and the nunchucks are just sending data without being init’d correctly.

I’m going to try converting the arduino code I used for this – http://socoder.net/?Blogs=59382, which I wrote a little about here - http://socoder.net/?Topic=6119 - while I was trying to figure it out.

OK, I hooked up my logic analyser and it seems that the pokitto is only writing zeros instead of wheat I’m actually writing. I don’t suppose can think of a reason why?

i2c.write(ADDRESS, (const char*)0xF0, 1);

Nothing comes immediately to mind. I am interfacing succesfully via the hardware I2C to the ADXL345 accelerometer, so I think there is no underlying big issue at play.

Could you

  • share more of the program code here
  • make sure you have PROJ_ENABLE_SOUND as 0 ?

I’m slowly getting somewhere…
I think part of the issue is my own confusion over variable types, for example the following seems to work…

    char dat[] = {0xF0,0x55,0xFB,0x00,0xFE,0x03};
    i2c.write(ADDRESS, dat, sizeof(dat));

However this does not…

i2c.write(ADDRESS, (const char*)0xF0, 1);
i2c.write(ADDRESS, (const char*)0x55, 1);
i2c.write(ADDRESS, (const char*)0xFB, 1);
i2c.write(ADDRESS, (const char*)0x00, 1);
i2c.write(ADDRESS, (const char*)0xFE, 1);
i2c.write(ADDRESS, (const char*)0x03, 1);

-edit-
I got a little further, I can (apparently) successfully send the init code to the nunchuck/classic controller, however, the data does not seem to be fully accepted. One of the main things my code does, is select a different data format from the controller (the 0xFE,0x03 part) however, when requesting the id back from the nunchuck, the data format indicator hasn’t changed. I’ll have to look into this some more.

-another edit-
Got it all mostly working. Having trouble detecting controllers being un/re-plugged, then I just need to tidy the code up a bit and make a demo.
I’m hoping to have the one library support nunchuck, classic controller and motion+ seamlessly using both known data formats.

In the second code youre sending contents of memory addresses 0x000000F0 then 0x00000055 etc. Not the value 0xF0,0x55… I think that is not your intention

1 Like

i2c.write(ADDRESS, (const char*)0xF0, 1);

*cries internally*


Seriously though, @jonne’s right.

Here i2c.write's second argument is supposed to be the address of a block of bytes it’s due to transmit.
What you’re doing is passing it hex values as if they were addresses, so the i2c library is looking at the RAM at address 0x000000F0, 0x00000055 etc, reading whatever data is there (i.e. taken out of context it’ll be gibberish) and passing that down the i2c connection.

If you point me to which i2c library you’re using I could check the docs to see if there’s a better answer, but based on the code you’ve got you should either be using your first example where all the data is in an array or (if you really must transmit one byte at a time for some reason) you need to be storing your values in a variable, like so:

char temp = 0;

temp = 0xF0;
i2c.write(ADDRESS, &temp, 1);
temp = 0x55;
i2c.write(ADDRESS, &temp, 1);
temp = 0xFB;
i2c.write(ADDRESS, &temp, 1);
temp = 0x00;
i2c.write(ADDRESS, &temp, 1);
temp = 0xFE;
i2c.write(ADDRESS, &temp, 1);
temp = 0x03;
i2c.write(ADDRESS, &temp, 1);

Note that this is horribly innefficient though.
If I had more context I could write something better.


The moral of the story is that if you ever see someone casting a constant to a pointer, ask them why, because generally it’s a bad idea :P.
(There are legitimate reasons for doing so like working on a system where certain bits of hardware are mapped to specific RAM addresses (e.g. the GBA), but those are few and far between.)

1 Like

I’m using mostly the same as the first example, however it seems I need to send one command at a time and add a delay because Nintendo decided that they didn’t want to be 100% i2c compliant (apparently, I don’t know much about i2c, just what I’ve read about other people’s nunchuck trouble)

Fyi, Lego mindstorms has the same issue: “almost” i2c

In that case your best bet is something like:

const char commandData[] = { 0xF0, 0x55, 0xFB, 0x00, 0xFE, 0x03 };

void slowI2CTransmit(int delayValue)
{
    for(int index = 0; index < sizeof(commandData); ++i)
    {
        i2c.write(ADDRESS, &commandData[index], sizeof(char));
        delay(delayValue); // Replace with whatever Pokitto's delay function is
    }
}

Unless the I2C class has a built in delay setting that’ll do the same.
Also that code could be made a lot more robust (e.g. running it over multiple frame updates), but I’ve vastly simiplified it so I’m not sat here typing for the next 10 minutes :P.

I’m using the following…

    char dat[] = {0xF0,0x55,0xFB,0x00,0xFE,0x03};
    i2c.write(ADDRESS, dat, 2);
    i2c.stop();
    wait_ms(1);
    i2c.write(ADDRESS, &dat[2], 2);
    i2c.stop();
    wait_ms(1);
    i2c.write(ADDRESS, &dat[4], 2);
    i2c.stop();
    wait_ms(1);

How does it seem for ‘correctness’?

No idea if the stops are needed (i2c is something I haven’t looked into much beyond ‘difference between i2c and spi’) but that should work if the delay is long enough, the stop is necessary and it’ll accept two bytes at a time.

Personally I’d change i2c.write(ADDRESS, dat, 2); to i2c.write(ADDRESS, &dat[0], 2); just to be explicit and/or make the lines match up.
I’d also put it in a loop first and only unroll it if you know unrolling is providing a tangible benefit.

(Also remember since this is for the Pokitto you have to be careful about how much frame time you hog, so if it ends up hogging too much time then you might have to split it over several frames if possible.)

Syntactically it all seems correct.

Getting there!

3 Likes

What was the magic ingredient?

Had to send one address+byte at a time with a delay after. It seems that Wii controllers don’t respond straight away.

2 Likes