Wii Nunchuck trouble

No rush, as long as I know itā€™s possible :slight_smile:

2 Likes

You can get around the problem already:

create nunchuck instance every time you talk to it.

i know it sounds weird / wasteful but believe me what actually happens is just a couple of IO port writes

The problem is the sound volume controller (which is also hooked to P0_4 and P0_5) grabs control and doesnā€™t give it back.

By reinitializing the nunchuck instance when you need it, you get back control of the I2C line

1 Like

Iā€™ll give that a try :slight_smile:

1 Like

hmmmmā€¦

Using the following to detect i2c devices, Iā€™m getting mixed results.
I have a wireless wii classic controller adapter (8bitdo) which will return the correct address (0xA4), but a real classic controller and two nunchucks that return 8 addresses from 0x00 to 0x0E.

game.display.clear(); I2C i2c(P0_5, P0_4); // sda, scl game.display.setCursor(0,0); game.display.print("Searching...\n"); int count = 0; for (int address=0; address<256; address+=2) { if (!i2c.write(address, NULL, 0)) { // 0 returned is ok sprintf(tempText,"I2C address 0x%02X\n", address); game.display.print(tempText); count++; } } sprintf(tempText,"%d devices found\n\n\n", count); game.display.print(tempText);

I wonder is this a quirk or Pokitto, or of the wii controllers?

@spinal I just hooked up a ADXL345 I2C 3-axis accelerometer. Worked immediately with no issues on hardware I2C when PROJ_ENABLE_SOUND = 0; (yes, accelerometer lib will be added to the repository)

So not sure about what the problems are that youā€™re facing with the nunchucks

Yes, we have a go for the ball in cup game !! :smile:

1 Like

Marble madness with accelerometer

3 Likes

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