Nunchuck isn't working with arduino micro

Hello,

I'm trying to connect an official nunchuck to an arduino micro. I use this adapter http://www.seeedstudio.com/wiki/Grove_-_NunChuck (just the adapter, not the grove board or something). This is what I've tried so far:

  • Connecting the clock and data i2c pin from the nunchuck to the i2c pins on the arduino micro, ground pin to ground pin and the power pin directly to the 5v on the arduino. All the LEDs on the arduino went off and I directly disconneted the nunchuck. I figured out that the nunchuck can't be powered from the arduino on 5v. (I was using 5v because the page of the adapter said "Work Voltage: +5 V")

-After that, I connected the i2c pins to the arduino and the power and ground pin to an external power source of 5v. The arduino couldn't connect to the nunchuck. I used the code from this page: http://playground.arduino.cc/Main/WiiChuckClass and I used this i2c scanner http://www.gammon.com.au/i2c (in case the code for the nunchuck didn't work). It looks like both programs just stop when they have to connect to i2c when the nunchuck is plugged in. When the nunchuck is removed from the adapter, the code immediately runs and the output is send over the serial line. When you connect the nunchuck again, the program just hangs again. After a while a spot on the nunchuck just under the joystick became very hot. I think it has to do with the voltage of 5v, because the Wii remotes only have 2 batteries of 1.5v (=3.0v total). So nunchucks are supposed to work at only 3.0v. Because the nunchuck was very hot I tested it on our Wii and it worked perfectly fine, so as far as I know nothing in the nunchuck is damaged.

-The next step was to put the 3.3v of the arduino on the nunchuck. This resulted in the same hanging of the program as described above. The nunchuck luckily didn't get hot anymore.

-Then I found this page http://playground.arduino.cc/Main/I2CBi-directionalLevelShifter. I built the circuit as displayed in the image, with as the only change that the program hung also when I removed the nunchuck. The program would only move on when I disconnected the resistors.

-Figuring that the voltage on the i2c line might be too low to be recognized, I connected the nunchuck once again to an external power source of 4.3v. This also heated up the nunchuck (not as much as the first time). The programs still hang when the nunchuck is connected to the arduino micro...

It's getting a little frustrating, and I don't know any other solutions. I hope someone can help me out! Maybe a levelshifter will work? (Like the BSS138)

Already thanks for any solutions!

I don't think I tried the code you've used but when I initially tried to use a Nunchuck with an Arduino, the code I found did not work well.

I wrote my own demo code and posted it here.

I didn't use level shifters with my Nunchuck. I just powered it with 3.3V and used the Arduino's I2C pins to interface with it.

At first: thanks for the help!
I tried your code, unfortunately it didn’t work. I suspect that the code stops when it reaches Wire.endTransmission(); Here is the adjusted code I used to debug it: (it prints text on the serial line when it reaches a certain point in the script), (it prints in setup() and in nunchuck_init())

/*
 * Nunchuck or Nunchuk Demo Code
 * by Duane Degn
 * November 14, 2015
 *
 * Based on code found found:
 * http://www.instructables.com/id/Wii-Nunchuck-as-general-purpose-controller-via-Ard/
 * The original code has lots of problems.
 */
// 3.3V output on Arduino to Nunchuck
// GND
// SDA to analog pin 4
// SCK to analog pin 5
// the middle upper and middle lower contacts of nunchuck plug are not used

//Derived from code developed by Chad Phillips, see:  http://windmeadow.com/node/42
//   For info on wiring up the chuck to the Arduino, download Bionic Arduino Class 4 from TodBot blog:
//   http://todbot.com/blog/2007/11/24/bionic-arduino-class-notes-3-4/

// Notes on accelerometer output in six positions. When a value is listed as "500" this aproximate.
// Other values are not exact and will likely vary from Nunchuck to Nunchuck.
// output with Nunchuck in normal position =                500, 500, 734
// output with Nunchuck with port (left) side down =        260, 500, 500
// output with Nunchuck with starboard (right) side down =  755, 526, 488
// output with Nunchuck with front end down =               500, 762, 500
// output with Nunchuck with front end up =                 500, 279, 500
// output with Nunchuck upside down =                       500, 500, 255

#include <Wire.h>

const byte EXPECTED_BYTES = 6;
byte outbuf[EXPECTED_BYTES];    // array to store arduino output

int joy_x_axis = outbuf[0];
int joy_y_axis = outbuf[1];
int accel_x_axis = outbuf[2] << 2 | ((outbuf[5] >> 2) & 3);
int accel_y_axis = outbuf[3] << 2 | ((outbuf[5] >> 4) & 3);
int accel_z_axis = outbuf[4] << 2 | ((outbuf[5] >> 6) & 3);

const unsigned long NUNCHUCK_READ_INTERVAL = 20;
unsigned long lastNunchuckRead;
const boolean DEBUG_FLAG = 1;

byte c_button = (outbuf[5] >> 1) & 1;
byte z_button =  outbuf[5] & 1;

void setup()
{
  delay(5000);
  Serial.begin (115200);
  Wire.begin(0x52);   // join i2c bus with address 0x52
  Serial.println("step1");
  nunchuck_init(); // send the initialization handshake
  Serial.println("step4");
  if (DEBUG_FLAG)
  {
    getId();
    printHeading();
  }
  lastNunchuckRead = millis();
}

void loop()
{
  checkNunchuckTime(DEBUG_FLAG);
  // Control robot based on Nunchuck data.
}

void checkNunchuckTime(boolean debugFlag)
{

  if (millis() - lastNunchuckRead > NUNCHUCK_READ_INTERVAL)
  {
    lastNunchuckRead += NUNCHUCK_READ_INTERVAL;
    byte i = readNunchuck();

    if (i < EXPECTED_BYTES && debugFlag)
    {
      printError(EXPECTED_BYTES, i);
    }
    else if (debugFlag)
    {
      printData();
    }
  }
}

byte readNunchuck()
{
  byte i = 0;
  Wire.requestFrom (0x52, EXPECTED_BYTES);  // request data from nunchuck
  while (Wire.available())
  {
    outbuf[i++] = Wire.read();
  }

  if (i >= EXPECTED_BYTES)
  {
    joy_x_axis = outbuf[0];
    joy_y_axis = outbuf[1];
    accel_x_axis = outbuf[2] << 2 | ((outbuf[5] >> 2) & 3);
    accel_y_axis = outbuf[3] << 2 | ((outbuf[5] >> 4) & 3);
    accel_z_axis = outbuf[4] << 2 | ((outbuf[5] >> 6) & 3);
    c_button = (outbuf[5] >> 1) & 1;
    z_button =  outbuf[5] & 1;
  }
  send_zero(); // This appears to be required.

  return i;
}

void printData ()
{
  /*  Include these commands if you want to watch the data values streaming from chuck in the serial viewer window on your PC*/


  Serial.print(joy_x_axis, DEC);
  Serial.print("t");

  Serial.print(joy_y_axis, DEC);
  Serial.print("t");

  Serial.print(accel_x_axis, DEC);
  Serial.print("t");

  Serial.print(accel_y_axis, DEC);
  Serial.print("t");

  Serial.print(accel_z_axis, DEC);
  Serial.print("t");

  Serial.print(c_button, DEC);
  Serial.print("t");

  Serial.print(z_button, DEC);
  Serial.print("t");


  /* Uncomment this section for zero paded binary output of outbuf[5].
  byte testBit = 128;
  Serial.print("outbuf[5] = ");
  while (outbuf[5] < testBit && testBit > 1) // zero pad binary output
  {
    Serial.print("0");
    testBit = testBit >> 1;
  }
  Serial.print(outbuf[5], BIN); */
  Serial.println();
}

void printHeading()
{
  Serial.println();
  Serial.println(" Xt YtaXtaYtaZtCtZ");
}

void printError(byte bytesExpected, byte bytesReceived)
{
  Serial.print("Error. The program expected to receive ");
  Serial.print(bytesExpected, DEC);
  Serial.print(" bytes but instead received ");
  Serial.print(bytesExpected, DEC);
  Serial.println(" bytes.");
}

void nunchuck_init()
{

  Wire.beginTransmission(0x52);  // transmit to device 0x52
  //Wire.write (0x40);    // sends memory address
  //Wire.write (0x00);    // sends sent a zero.
  Wire.write (0xF0);
  Wire.write (0x55);
  Serial.println("step2");  
  Wire.endTransmission(); // stop transmitting
  Serial.println("step3");
  Wire.beginTransmission(0x52);  // transmit to device 0x52
  Wire.write (0xFB);
  Wire.write (0x00);
  Wire.endTransmission();  // stop transmitting
  delay(10);
}
void getId()
{
  Wire.beginTransmission(0x52);  // transmit to device 0x52
  Wire.write(0xFA);
  Wire.endTransmission();  // stop transmitting
  Serial.print("Nunchuck ID = ");
  Wire.requestFrom (0x52, EXPECTED_BYTES);
  while (Wire.available())
  {
    byte nunchuckByte = Wire.read();
    Serial.print(nunchuckByte, HEX);
    Serial.print(" ");
  }
  Serial.println();
  delay(10);
}

void send_zero()
{
  Wire.beginTransmission(0x52); // transmit to device 0x52
  Wire.write (0x00);    // sends one byte
  Wire.endTransmission(); // stop transmitting
}

The output is the following:

step1
step2
//it stops here, it starts printing again when the nunchuck is removed
step3
step4
Nunchuck ID = 

 X Y aX aY aZ C Z
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
Error. The program expected to receive 6 bytes but instead received 6 bytes.
//When the nunchuck is plugged in again, the program stops to print again

This page warns for the 3.3v on i2c with a arduino micro:

Even the Arduino Leonardo and Arduino Micro (both of which use the ATmega32U4) require 0.7 * Vcc for ‘high’ level of the I2C bus, although their normal digital inputs are LVTTL and require only 1.9V. For 5V powered micros, the I2C high level should be at least 3.5V to meet specification; using the 3.3V I2C-bus for a 5V Arduino is living on the edge, hoping that the 3.3V will be recognized as a digital high.

Is the arduino micro on this point different form the arduino uno?

svenvdvoort: This page warns for the 3.3v on i2c with a arduino micro:Is the arduino micro on this point different form the arduino uno?

The I2C line is being pulled high from the Arduino so it's pulled to 5V. Technically (and likely in actuality) this can harm 3.3V devices. Ideally you'd want to use a level shifter between the 5V device and the 3.3V device if the 3.3V device isn't 5V tolerant. Depending on the 3.3V device, the 5V line might not be pulled all the way to 5V. It's possible for the 3.3V device to pull the line a bit lower through clamping diodes (if the device has them). 4.1V seems like a common value (at least with the circuits I've used) when a 5V I2C line is connected to a 3.3V device.

I don't know if the Nunchuck I'm using is 5V tolerant or not but I'm not worried about the device enough to bother with a level shifter. I would certainly use a level shifter is I were designing a product to be used by others.

I don't know what to suggest if the code I wrote doesn't work with your Nunchuck. It would be interesting to see logic analyzer traces of the I2C communication between the Nunchuck and the Wii Mote. Perhaps there some sort of timing difference in how the Wii Mote communicating with the Nunchuck and the way the Arduino is communicating with the Nunchuck.

In the arduino, after Wire.begin(), I think y ou can add digitalWrite (SCL, LOW); dititalWrite (SDA, LOW); to turn off the internal pullup resistors so external pullups to 3.3V can be used.

I think.

CrossRoads: In the arduino, after Wire.begin(), I think y ou can add digitalWrite (SCL, LOW); dititalWrite (SDA, LOW); to turn off the internal pullup resistors so external pullups to 3.3V can be used.

I think.

I just tried it on my Uno and it worked.

I believe the Mega has external pull-ups to 5V so it wouldn't work on a Mega.

I had often wondered if the internal 5V pull-ups could be disabled for I2C communication. I didn't realize it would be so easy. Thanks for the tip.

I just tried the bi-directional level shifter with: digitalWrite (SCL, LOW); dititalWrite (SDA, LOW); That didn't work either... (The problem of the stopping script is still there) I'm lost now on the cause of this problem. Do you have any other ideas for my circuit?

Thanks!

svenvdvoort:
I’m lost now on the cause of this problem.
Do you have any other ideas for my circuit?

DuaneDegn:
I don’t know what to suggest if the code I wrote doesn’t work with your Nunchuck. It would be interesting to see logic analyzer traces of the I2C communication between the Nunchuck and the Wii Mote. Perhaps there some sort of timing difference in how the Wii Mote communicating with the Nunchuck and the way the Arduino is communicating with the Nunchuck.

You can get logic analyzers for about $15. With a LA you could monitor the exact communication used between the WiiMote and the Nunchuck.

Another alternative is to use a different Nunchuck. As I mentioned in the other thread, the code I wrote works with my wireless Nyko Nunchuck.

That didn't work either... (The problem of the stopping script is still there)

I suspect that all that misuse has fried your Nunchuck so now it will not work.

Grumpy_Mike: I suspect that all that misuse has fried your Nunchuck so now it will not work.

This was my initial thought but the Nunchuck apparently still works with the WiiMote.

svenvdvoort: I tested it on our Wii and it worked perfectly fine, so as far as I know nothing in the nunchuck is damaged.

I always find it odd when things are described as working "perfectly" or being sure nothing was damaged since the device still works. It's very possible for a damaged component to behave normally for a while.

This happened recently when I mistakenly reversed the polarity on a sensor's power lines. I was initially relieved to see my sensor was still working but this relief didn't last long because the sensor soon died while properly wired.

Merry X-mas!!!

DuaneDegn: I always find it odd when things are described as working "perfectly" or being sure nothing was damaged since the device still works. It's very possible for a damaged component to behave normally for a while.

I agree with you on this point, however I tested it with another nunchuck which I didn't connect to 5v or something. The chance that this nunchuck (also) doesn't work is very low. (there is of course always a chance)

I will make a call to my electronics (web)shop after Christmas and take a look at a level shifter.