Wii Nunchuck and Arduino with 9v battery

Hi there,

I have a project where my wireless wii nunchuck sends data to the Arduino TX/RX. When I have the Arduino connected to the usb port of my computer the wii connects to the Arduino just fine, although when I operate the Arduino with a 9 volt battery the wii never connects, and when it connects the data gets all weird.

Am I doing any wrong on this set up?

/*
 * ArduinoNunchukDemo.ino
 *
 * Copyright 2011-2013 Gabriel Bianconi, http://www.gabrielbianconi.com/
 *
 * Project URL: http://www.gabrielbianconi.com/projects/arduinonunchuk/
 *
 */

#include <Wiichuck.h> // Library for reading data from Wii Nunchuck
#include <Wire.h>         // Library for I2C communication           
#include <Servo.h>                   // Library for controlling Servo or ESC
 

WiiChuck chuck = WiiChuck();
Servo myservo;

int speed_val;                      // Speed value
int speed_val_cur = 90;  // Current speed value
int y = 0;                                // Joystick value
int time = 200;                    // Delay timer
int speed_val_hold;         // speed value for the throttle hold feature
//int resetPin = 12; //set up reset pin

//led pin
int ledPin = 13;


//Lost connection variables
  int DuplicateCounter=0;
  int Previoussm=0;
  int DupplicateLimit=40;

// Setup.  This runs at startup, and initializes the nunchuck
void setup() {

  //Hold  pin 12 at high
  //digitalWrite(resetPin, HIGH);
  
  
  //Set pin mode
  //pinMode(resetPin, OUTPUT);  

//Serial.print("reset");

delay(10000);
  
//Serial.begin(115200);  // Begin serial communication with baud rate at 115200.  For debugging
Serial.begin(9600);  // Begin serial communication with baud rate at 115200.  For debugging
chuck.begin();               // Initialize nunchuck.  This function is located in the WiiChuck.h library
chuck.update();           // Read nunchuck.  This function is located in the WiiChuck.h library
myservo.attach(9);    // ESC attached to 9 pin of Arduino


//Set up LED
pinMode(ledPin, OUTPUT);



// Print to serial monitor.  This tells us that the setup ran once.  Again, for debugging
//Serial.println();
//Serial.print("Initialization Sequence Complete");
//Serial.println();
delay(1000);
}

// Main loop.  This is what actually does stuff.  The rest of the sketch is inside this
void loop() {

  //int plusminus = 0;
  
if  (chuck.buttonC == 1)
{
  digitalWrite(ledPin, HIGH);
  digitalWrite(ledPin, LOW);
}
  
//Check if Z or C button is pressed
if ((chuck.buttonZ)||(chuck.buttonC)) {
  
  // If you hold down Z, the throttle hold is enabled and speed adjustments occur slowly (think cruise control buttons in a car)
  if (chuck.buttonZ) {
    Serial.println("z");
    time = 50;
  }
  
  /*
  // If you press C, something will happen  -- NOTE: This feature is not yet implimented, so nothing will really happen
  if (chuck.buttonC) {
    do stuff
  }
  */
} 

// If no buttons are pressed, throttle response is set to maximum (think throttle/brake pedels in a car)
else {
  time = 5;
}

// Delay for the time amount specified above.  This determines how fast the throttle will react to input
delay(time);

// Request updated data from the nunchuck, and assign the Y axis position to variable y
chuck.update();
y = chuck.readJoyY();


// Map the joystick value onto the speed value (joystick at 0 = speed at 90.  This is neutral throttle)
speed_val = map(y, -128, 125, 30, 150);

// If the connection is lost, set all speeds to 90.  Remember, speed = 90 is neutral.  IE. the motor is stopped.
if ((y > 125) || (y < -129)) {
speed_val = 90;
speed_val_cur = 90;
speed_val_hold = 90;
setup();
}

if (chuck.buttonZ) {                         // If Z is pressed (throttle hold on):  
  
  if ((speed_val_hold < speed_val)           // Check if we are trying to accellerate:
    && (y > 5)) {
      
    speed_val_hold++;                        // If hold button is pressed and throttle stick moved up – increase speed
  }  
  if ((speed_val_hold > speed_val)           // Check if we are trying to decellerate:
    && (y < -5)) {
    
    speed_val_hold--;                        // If hold button is pressed and throttle stick moved down – decrease speed
  }    
  speed_val_cur = speed_val_hold;
}

else {                                  // If Z  is not pressed (throttle hold off):

  if (speed_val_cur < speed_val) {      // Check if we are trying to accellerate:
    speed_val_cur++;                    // If hold button is NOT pressed and throttle stick moved up – increase speed
  }
  if (speed_val_cur > speed_val) {      // Check if we are trying to decellerate:
    speed_val_cur--;                    // If hold button is NOT pressed and throttle stick moved down – decrease speed
  }
speed_val_hold = speed_val_cur;
}

  

// Write current speed value to the ESC
myservo.write(speed_val_cur);


Serial.println(speed_val_cur);
  

}

Do you mean you are connecting the 9V to the arduino external power jack ?

I have a project where my wireless wii nunchuck sends data to the Arduino TX/RX. When I have the Arduino connected to the usb port of my computer the wii connects to the Arduino just fine, although when I operate the Arduino with a 9 volt battery the wii never connects, and when it connects the data gets all weird.

What kind of serial connection is the WII ? (usb, TTL SERIAL ?)

Yes, I am powering the Arduino with a external power jack using the 7-12v DC input.

I believe it is the TLL Serial. It is definitely not a USB.

What does the WII normally interface with (for non-arduino users) a PC or what if it is not USB. ?

Non-Arduino users? This is a Arduino forum.

The Wii is NOT an ARDUINO product nor was it designed for interfacing with arduinos. It is a Nintendo product. So , since I am not a Nintendo owner/user, I ask you again. What does the Wii normally connect to ? I believe the answer I am waiting for is " It plugs into a Nintendo". Can you please answer the question so we can move on ?

The Wii Nunchuck uses I2C communication, and is powered by 3.3V

I see no reason for it not to work on 9V - apart from a 9V battery being the most non-suited battery for an Arduino setup (very few mAh and most of it's power is thrown away in the voltage regulator)

// Per.

Finally, someone who understand english. So Zapro, You seem to be a RSG (Army-speak for Real Smart Guy) In view of your last comment , what do you make of this post by the OP when he started this post ?

I have a project where my wireless wii nunchuck sends data to the Arduino TX/RX. When I have the Arduino connected to the usb port of my computer the wii connects to the Arduino just fine, although when I operate the Arduino with a 9 volt battery the wii never connects, and when it connects the data gets all weird.

Are you thinking what I'm thinking ?

raschemmel: Finally, someone who understand english. So Zapro, You seem to be a RSG (Army-speak for Real Smart Guy) In view of your last comment , what do you make of this post by the OP when he started this post ?

I have a project where my wireless wii nunchuck sends data to the Arduino TX/RX. When I have the Arduino connected to the usb port of my computer the wii connects to the Arduino just fine, although when I operate the Arduino with a 9 volt battery the wii never connects, and when it connects the data gets all weird.

Are you thinking what I'm thinking ?

It gives absolutely no sense or meaning to me - there is no way of attaching the Arduino to the Wii by means of it's USB-port in the back.

Normally the Wii Nunchuck is connected to the WiiMote, which in turns uses BlueTooth to connect to the Wii-console.

Maybe OP will describe a bit better what he is doing, because the stuff that has been written so far, gives no meaning at all.

// Per.

roger that.

Since my “English” is not good enough for you folks, I can post an image and that may speak for itself.

The 9v battery works fine, the problem is with the code (i believe). It don’t understand how Arduino would work with the USB plugged (right after the code is uploaded) in, and not when I unplug it and just let the Arduino be powered by the 9v battery.

I am not sure how to explain this in a better way.

Raschemmel, I think I misunderstood your question.
But I believe Zapro answered it: “Normally the Wii Nunchuck is connected to the WiiMote.” You will be able to see it on the picture.

Nunchuck 1

You will see the Nunchuck wiring here. I am using the 5v pin from the Arduino; I added some resistors to make sure the voltage output is only 3.3v.

Nunchuck 2.

This is just the Nunchuck itself. Not really important. The important thing is:
when you turn on the Arduino, the Nunchuck starts blinking; then you press the button on the wii remote and that is when the WiiMote connects to the remote, and the bluetooth connection starts.

If I have the USB plugged in it works just fine. If I don’t have it in (just battery), it does not work.

how Arduino would work with the USB plugged (right after the code is uploaded) in,

If you want us to understand what that means when you say the arduino works just fine you have to explain what it is doing that is working just fine. You gave us your code but since we are not Wii experts (at least not me) we don't know what is happening "just fine" . How about telling us what the arduino is doing : Do you see a void loop(); in your code ? I don't . You have a setup but you have no program (at least no main loop) so anything in setup is only executed once. Where is your program ? Are you saving that for last ? (when nothing else works?) I think that is the point we are at now.

 void setup() {
delay(200);
Serial.begin(9600);  
chuck.begin();            // 
chuck.update();          // 
myservo.attach(9);  // 
//Set up LED
pinMode(ledPin, OUTPUT); //
delay(1000);
}

The speed of my motor goes up and down. If the USP is plugged in, the readings show that the speed works responding to the remote.
If USB is not working, then the speed goes all the way up; in this case 180 which is the max speed (user PWM).

Code from: http://forum.arduino.cc/index.php?topic=226041.0

/*
 * ArduinoNunchukDemo.ino
 *
 * Copyright 2011-2013 Gabriel Bianconi, http://www.gabrielbianconi.com/
 *
 * Project URL: http://www.gabrielbianconi.com/projects/arduinonunchuk/
 *
 */

#include <Wiichuck.h> // Library for reading data from Wii Nunchuck
#include <Wire.h>         // Library for I2C communication           
#include <Servo.h>                   // Library for controlling Servo or ESC
 

WiiChuck chuck = WiiChuck();
Servo myservo;

int speed_val;                      // Speed value
int speed_val_cur = 90;  // Current speed value
int y = 0;                                // Joystick value
int time = 200;                    // Delay timer
int speed_val_hold;         // speed value for the throttle hold feature
//int resetPin = 12; //set up reset pin

//led pin
int ledPin = 13;


//Lost connection variables
  int DuplicateCounter=0;
  int Previoussm=0;
  int DupplicateLimit=40;

// Setup.  This runs at startup, and initializes the nunchuck
void setup() {

  //Hold  pin 12 at high
  //digitalWrite(resetPin, HIGH);
  
  
  //Set pin mode
  //pinMode(resetPin, OUTPUT);  

//Serial.print("reset");

delay(10000);
  
//Serial.begin(115200);  // Begin serial communication with baud rate at 115200.  For debugging
Serial.begin(9600);  // Begin serial communication with baud rate at 115200.  For debugging
chuck.begin();               // Initialize nunchuck.  This function is located in the WiiChuck.h library
chuck.update();           // Read nunchuck.  This function is located in the WiiChuck.h library
myservo.attach(9);    // ESC attached to 9 pin of Arduino


//Set up LED
pinMode(ledPin, OUTPUT);



// Print to serial monitor.  This tells us that the setup ran once.  Again, for debugging
//Serial.println();
//Serial.print("Initialization Sequence Complete");
//Serial.println();
delay(1000);
}

// Main loop.  This is what actually does stuff.  The rest of the sketch is inside this
void loop() {

  //int plusminus = 0;
  
if  (chuck.buttonC == 1)
{
  digitalWrite(ledPin, HIGH);
  digitalWrite(ledPin, LOW);
}
  
//Check if Z or C button is pressed
if ((chuck.buttonZ)||(chuck.buttonC)) {
  
  // If you hold down Z, the throttle hold is enabled and speed adjustments occur slowly (think cruise control buttons in a car)
  if (chuck.buttonZ) {
    Serial.println("z");
    time = 50;
  }
  
  /*
  // If you press C, something will happen  -- NOTE: This feature is not yet implimented, so nothing will really happen
  if (chuck.buttonC) {
    do stuff
  }
  */
} 

// If no buttons are pressed, throttle response is set to maximum (think throttle/brake pedels in a car)
else {
  time = 5;
}

// Delay for the time amount specified above.  This determines how fast the throttle will react to input
delay(time);

// Request updated data from the nunchuck, and assign the Y axis position to variable y
chuck.update();
y = chuck.readJoyY();


// Map the joystick value onto the speed value (joystick at 0 = speed at 90.  This is neutral throttle)
speed_val = map(y, -128, 125, 30, 150);

// If the connection is lost, set all speeds to 90.  Remember, speed = 90 is neutral.  IE. the motor is stopped.
if ((y > 125) || (y < -129)) {
speed_val = 90;
speed_val_cur = 90;
speed_val_hold = 90;
setup();
}

if (chuck.buttonZ) {                         // If Z is pressed (throttle hold on):  
  
  if ((speed_val_hold < speed_val)           // Check if we are trying to accellerate:
    && (y > 5)) {
      
    speed_val_hold++;                        // If hold button is pressed and throttle stick moved up – increase speed
  }  
  if ((speed_val_hold > speed_val)           // Check if we are trying to decellerate:
    && (y < -5)) {
    
    speed_val_hold--;                        // If hold button is pressed and throttle stick moved down – decrease speed
  }    
  speed_val_cur = speed_val_hold;
}

else {                                  // If Z  is not pressed (throttle hold off):

  if (speed_val_cur < speed_val) {      // Check if we are trying to accellerate:
    speed_val_cur++;                    // If hold button is NOT pressed and throttle stick moved up – increase speed
  }
  if (speed_val_cur > speed_val) {      // Check if we are trying to decellerate:
    speed_val_cur--;                    // If hold button is NOT pressed and throttle stick moved down – decrease speed
  }
speed_val_hold = speed_val_cur;
}

  

// Write current speed value to the ESC
myservo.write(speed_val_cur);


Serial.println(speed_val_cur);
  

}

Library:

/*
 * Nunchuck -- Use a Wii Nunchuck
 * Tim Hirzel http://www.growdown.com
 *
 notes on Wii Nunchuck Behavior.
 This library provides an improved derivation of rotation angles from the nunchuck accelerometer data.
 The biggest different over existing libraries (that I know of ) is the full 360 degrees of Roll data
 from teh combination of the x and z axis accelerometer data using the math library atan2.
 
 It is accurate with 360 degrees of roll (rotation around axis coming out of the c button, the front of the wii),
 and about 180 degrees of pitch (rotation about the axis coming out of the side of the wii).  (read more below)
 
 In terms of mapping the wii position to angles, its important to note that while the Nunchuck
 sense Pitch, and Roll, it does not sense Yaw, or the compass direction.  This creates an important
 disparity where the nunchuck only works within one hemisphere.  At a result, when the pitch values are
 less than about 10, and greater than about 170, the Roll data gets very unstable.  essentially, the roll
 data flips over 180 degrees very quickly.   To understand this property better, rotate the wii around the
 axis of the joystick.  You see the sensor data stays constant (with noise).  Because of this, it cant know
 the difference between arriving upside via 180 degree Roll, or 180 degree pitch.  It just assumes its always
 180 roll.
 
 
 *
 * This file is an adaptation of the code by these authors:
 * Tod E. Kurt, http://todbot.com/blog/
 *
 * The Wii Nunchuck reading code is taken from Windmeadow Labs
 * http://www.windmeadow.com/node/42
 */

#ifndef WiiChuck_h
#define WiiChuck_h

#include "WProgram.h"
#include <Wire.h>
#include <math.h>


// these may need to be adjusted for each nunchuck for calibration
#define ZEROX 510
#define ZEROY 490
#define ZEROZ 460
#define RADIUS 210  // probably pretty universal

#define DEFAULT_ZERO_JOY_X 124
#define DEFAULT_ZERO_JOY_Y 132



class WiiChuck {
private:
    byte cnt;
    uint8_t status[6];		// array to store wiichuck output
    byte averageCounter;
    //int accelArray[3][AVERAGE_N];  // X,Y,Z
    int i;
    int total;
    uint8_t zeroJoyX;   // these are about where mine are
    uint8_t zeroJoyY; // use calibrateJoy when the stick is at zero to correct
    int lastJoyX;
    int lastJoyY;
    int angles[3];
    
    boolean lastZ, lastC;
    
    
public:
    
    byte joyX;
    byte joyY;
    boolean buttonZ;
    boolean buttonC;
    void begin()
    {
        Wire.begin();
        cnt = 0;
        averageCounter = 0;
        // instead of the common 0x40 -> 0x00 initialization, we
        // use 0xF0 -> 0x55 followed by 0xFB -> 0x00.
        // this lets us use 3rd party nunchucks (like cheap $4 ebay ones)
        // while still letting us use official oness.
        // only side effect is that we no longer need to decode bytes in _nunchuk_decode_byte
        // see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264805255
        //
        Wire.beginTransmission(0x52);	// device address
        Wire.send(0xF0);
        Wire.send(0x55);
        Wire.endTransmission();
        delay(1);
        Wire.beginTransmission(0x52);
        Wire.send(0xFB);
        Wire.send(0x00);
        Wire.endTransmission();
        update();
        for (i = 0; i<3;i++) {
            angles[i] = 0;
        }
        zeroJoyX = DEFAULT_ZERO_JOY_X;
        zeroJoyY = DEFAULT_ZERO_JOY_Y;
    }
    
    
    void calibrateJoy() {
        zeroJoyX = joyX;
        zeroJoyY = joyY;
    }
    
    void update() {
        
        Wire.requestFrom (0x52, 6);	// request data from nunchuck
        while (Wire.available ()) {
            // receive byte as an integer
            status[cnt] = _nunchuk_decode_byte (Wire.receive()); //
            cnt++;
        }
        
    
        
        if (cnt > 5) {
            lastZ = buttonZ;
            lastC = buttonC;
            lastJoyX = readJoyX();
            lastJoyY = readJoyY();
            //averageCounter ++;
            //if (averageCounter >= AVERAGE_N)
            //    averageCounter = 0;
            
            cnt = 0;
            joyX = (status[0]);
            joyY = (status[1]);
            for (i = 0; i < 3; i++)
                //accelArray[i][averageCounter] = ((int)status[i+2] << 2) + ((status[5] & (B00000011 << ((i+1)*2) ) >> ((i+1)*2)));
                angles[i] = (status[i+2] << 2) + ((status[5] & (B00000011 << ((i+1)*2) ) >> ((i+1)*2)));
            
            //accelYArray[averageCounter] = ((int)status[3] << 2) + ((status[5] & B00110000) >> 4);
            //accelZArray[averageCounter] = ((int)status[4] << 2) + ((status[5] & B11000000) >> 6);
            
            buttonZ = !( status[5] & B00000001);
            buttonC = !((status[5] & B00000010) >> 1);
            _send_zero(); // send the request for next bytes
            
        }
    }
    
    
    // UNCOMMENT FOR DEBUGGING
    //byte * getStatus() {
    //    return status;
    //}
    
    float readAccelX() {
        // total = 0; // accelArray[xyz][averageCounter] * FAST_WEIGHT;
        return (float)angles[0] - ZEROX;
    }
    float readAccelY() {
        // total = 0; // accelArray[xyz][averageCounter] * FAST_WEIGHT;
        return (float)angles[1] - ZEROY;
    }
    float readAccelZ() {
        // total = 0; // accelArray[xyz][averageCounter] * FAST_WEIGHT;
        return (float)angles[2] - ZEROZ;
    }
    
    boolean zPressed() {
        return (buttonZ && ! lastZ);
    }
    boolean cPressed() {
        return (buttonC && ! lastC);
    }
    
    // for using the joystick like a directional button
    boolean rightJoy(int thresh=60) {
        return (readJoyX() > thresh and lastJoyX <= thresh);
    }
    
    // for using the joystick like a directional button
    boolean leftJoy(int thresh=60) {
        return (readJoyX() < -thresh and lastJoyX >= -thresh);
    }
    
    
    int readJoyX() {
        return (int) joyX - zeroJoyX;
    }
    
    int readJoyY() {
        return (int)joyY - zeroJoyY;
    }
    
    
    // R, the radius, generally hovers around 210 (at least it does with mine)
    // int R() {
    //     return sqrt(readAccelX() * readAccelX() +readAccelY() * readAccelY() + readAccelZ() * readAccelZ());
    // }
    
    
    // returns roll degrees
    int readRoll() {
        return (int)(atan2(readAccelX(),readAccelZ())/ M_PI * 180.0);
    }
    
    // returns pitch in degrees
    int readPitch() {
        return (int) (acos(readAccelY()/RADIUS)/ M_PI * 180.0);  // optionally swap 'RADIUS' for 'R()'
    }
    
private:
    byte _nunchuk_decode_byte (byte x)
    {
        //decode is only necessary with certain initializations
        //x = (x ^ 0x17) + 0x17;
        return x;
    }
    
    void _send_zero()
    {
        Wire.beginTransmission (0x52);	// transmit to device 0x52
        Wire.send (0x00);		// sends one byte
        Wire.endTransmission ();	// stop transmitting
    }
    
};


#endif

PLEASE resize and/or rotate your pictures! - Maximum 1000 pixels on the longest dimension. Thank you.

// Per.

I re-uploaded the pics with 1000 pixels.

rodrigodasilva:
I re-uploaded the pics with 1000 pixels.

Thank you. They are still over 1000 pixels on the longest dimension.

Anyhow, i see that you have a wireless Nunchuck (it’s not a Wiimote, so don’t call it that, it confuses us!)

You cannot power the receiver for the Wiimote via a voltage divider (resistors) - you need to power it from the 3.3V-pin on the Arduino.

Measure your voltages in the system with USB, and with battery, and see what changes.

// Per.

Silly question but did you ever breadboard any of this to test it before soldering everything together or was that impossible ?

The board and electronics works fine. I used the board last Spring. To make it work, I have to plug it into the computer and when the readings are working I can take it off. That way the battery works. But imagine having to do that every time.

I will try to upload a video later. The issue is the code.