WiiNunchuck and two servos.

Hello everyone. I'm an amature props (Left 4 Dead pipe bomb--beeps and blinks like in game, replica ADAM extractor from BIOSHOCK) and costume builder (Darth Vader, Mortal Kombat-Scorpion & SubZero, Jason Vorhees, Predator). I'm pretty new to working with C++ Code in school, let alone Arduino Code. I'm working on a project and need some help (I'm using the Arduino Uno). I'm close but keep getting errors...not to mention they come out with Arduino 1.0.1.

A little about my project. I'm creating a Predator Costume and I'm using the WiiNunchuck with two servos to control the shoulder mounted laser cannon prop. Nothing would be neater than to have the shoulder laser follow the helmet...with the wiichuck set up..this would be very possible and sweet. The sensor would be mounted in the Helmet and the controller on my Arm and servos with Arduino on my shoulder.

I have run several codes that all work very well, but I'm trying to add additonal capabilites to the build from the Wii NunChuck.

  1. When the Z Button is held, I want the Joystick to control the servos (no input from sensor)...essentially a Manual Mode.
  2. When the C Button is pressed and released, It will flash a SuperBright LED on another pin (like 8 or so).

Attached is a "ino" copy of code I'm using (credit goes to those credited in it). Can anyone help modify this or modify what you may have. I promise to keep anyone's name attached in the code if you help. I will also share all my work on the project through my facebook account. Please Help.

I also don't mind learning how to do it if you can instruct me. I was thinking of "Case" scenerios for if z_button=1 then case_0 .....or just doing a "if / else" statement. Not sure which would be more accurate or easier to do?

PredatorV5.ino (4.78 KB)

I'm pretty new to working with C++ Code in school, let alone Arduino Code.

Arduino code IS C++.

I was thinking of "Case" scenerios for if z_button=1 then case_0 .....or just doing a "if / else" statement. Not sure which would be more accurate or easier to do?

A switch statement with two cases is functionally equivalent to an if/else statement. Neither is more accurate or easier. The if/else is more logical when the value (z_button's state) can only take on two values.

Can anyone help modify this

Anyone could, once you identify your requirements and explain how the current code does not meet those requirements.

PaulS,
I attached the "ino" file I'm currently using. If you can't download it, I can post the entire thing.

This is what it is not doing and what I want it to do.

  1. When the "z_button" is pressed and held, the analog stick of the Wii Nunchuck (Joystick) takes command of the servos. This would be a Manual Mode Override type set up. When "z_button" is released, the servos again use the Wii NunChuck tilt sensors for command.

  2. When the "c_button" is pressed, an LED attached to pin 9 is flashed (blinked).

Below is what I have for #2 so far, but stops the servos from moving for some reason. How do I add this to happen even whe the servos are always reading from the tilt servos?

if (z_button = 1);
digitalWrite(ledPin, HIGH); // sets the LED on
delay(100); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a long time to flash again second

Predator_v1works.ino (4.84 KB)

f (z_button = 1);

BZZZZT!
Two bugs in one line!

Have you got a really good reason for not using the servo library?

Servo library?

You mean just use the functions in "servo.h" ?

Does it have control structures with using the Wii NunChuck's joyStick_x and joyStick_y functions? I found something that might help.

Here is my entire code so far. My LED with continuosly flash when the C Button is pressed, but it pauses the servos from still following my movement until I release:

// This code has the servos pause when the LED is flashed or Z button is pressed//
#include <Wire.h>
#include <string.h>
#include "Arduino.h"

uint8_t outbuf[6];

int cnt = 0;
int ledPin = 9;    //pin #9 is LED+
int ledPin2 = 13;  //pin #13 is onboard LED

int servoPin = 6;  //pin #6 is top servo or elevation
int servoPin2 = 5;  //pin #5 is bottom servo or azimuth

int pulseWidth = 0;
int pulseWidth2 = 0;

long lastPulse = 0;
long lastPulse2 = 0;

int z_button = 0;   // initializes the z button as LOW or not pressed.
int c_button = 0;   // initializes the c button as LOW or not pressed.

int refreshTime = 20; 
int minPulse = 1000;
int minPulse2 = 500;

int dtime=10;

#define pwbuffsize 10
long pwbuff[pwbuffsize];
long pwbuffpos = 0;
long pwbuff2[pwbuffsize];
long pwbuffpos2 = 0;

void setup()
{
    Serial.begin (19200);
    Wire.begin ();
    nunchuck_init ();
    pinMode(servoPin, OUTPUT);
    pinMode(servoPin2, OUTPUT);
    pinMode(ledPin, OUTPUT);      // sets the digital pin as output
    pinMode(ledPin2, OUTPUT);
    
    pulseWidth = minPulse;
    pulseWidth2 = minPulse2;
    Serial.print ("Finished setup\n");
}

void nunchuck_init()
{
    Wire.beginTransmission (0x52);
    Wire.write ((byte)0x40);
    Wire.write ((byte)0x00);  
    Wire.endTransmission ();
}

void send_zero()
{
    Wire.beginTransmission (0x52);
    Wire.write ((byte)0x00);
    Wire.endTransmission ();
}

int t = 0;

void loop()
{
    t++;
    long last = millis();

    if( t == 1) {

        t = 0;

        Wire.requestFrom (0x52, 6);

        while (Wire.available ()) {
            outbuf[cnt] = nunchuk_decode_byte (Wire.read ());
            digitalWrite (ledPin2, HIGH);
            cnt++;
        }

        if (cnt >= 5) {

            //            printNunchuckData();

            int z_button = 0;
            int c_button = 0;

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

            switch (c_button) {
            case 1:
                switch (z_button) {
                case 0:
                    break;
                case 1:
                    muovi();
                    break;
                }
                break;
            case 0:
                switch (z_button) {
                case 0:
                    break;
                case 1:
                     digitalWrite(ledPin, HIGH);   // sets the LED on
                     delay(50);                  // waits for a second
                     digitalWrite(ledPin, LOW);    // sets the LED off
                

  break;
                }
                break;
            }
        }

        cnt = 0;
        send_zero();

    } // if(t==)

    updateServo();

    delay(dtime);
}


void updateServo() {

    if (millis() - lastPulse >= refreshTime) {

        digitalWrite(servoPin, HIGH);
        delayMicroseconds(pulseWidth);
        digitalWrite(servoPin, LOW);

        digitalWrite(servoPin2, HIGH);
        delayMicroseconds(pulseWidth2);
        digitalWrite(servoPin2, LOW);

        lastPulse = millis();
    }
}

int i=0;
void printNunchuckData()
{
    int joy_x_axis = outbuf[0];
    int joy_y_axis = outbuf[1];
    int accel_x_axis = outbuf[2]; // * 2 * 2; 
    int accel_y_axis = outbuf[3]; // * 2 * 2;
    int accel_z_axis = outbuf[4]; // * 2 * 2;

    int z_button = 0;
    int c_button = 0;

    if ((outbuf[5] >> 0) & 1) 
        z_button = 1;
    if ((outbuf[5] >> 1) & 1)
        c_button = 1;
    if ((outbuf[5] >> 2) & 1) 
        accel_x_axis += 2;
    if ((outbuf[5] >> 3) & 1)
        accel_x_axis += 1;

    if ((outbuf[5] >> 4) & 1)
        accel_y_axis += 2;
    if ((outbuf[5] >> 5) & 1)
        accel_y_axis += 1;

    if ((outbuf[5] >> 6) & 1)
        accel_z_axis += 2;
    if ((outbuf[5] >> 7) & 1)
        accel_z_axis += 1;

    Serial.print (i,DEC);
    Serial.print ("\t");

    Serial.print ("X: ");
    Serial.print (joy_x_axis, DEC);
    Serial.print ("\t");

    Serial.print ("Y: ");
    Serial.print (joy_y_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccX: ");
    Serial.print (accel_x_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccY: ");
    Serial.print (accel_y_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccZ: ");
    Serial.print (accel_z_axis, DEC);
    Serial.print ("\t");

    Serial.print (z_button, DEC);
    Serial.print (" ");
    Serial.print (c_button, DEC);
    Serial.print ("\r\n");
    i++;
}

char nunchuk_decode_byte (char x)
{
    x = (x ^ 0x17) + 0x17;
    return x;
}

void muovi (){
    float tilt = (700 - outbuf[3]*2*2);
    float tilt2 = outbuf[2]*2*2;

    tilt = (tilt);
    pulseWidth = (tilt * 5) + minPulse;

    tilt2 = (tilt2-288);
    pulseWidth2 = (tilt2 * 5) + minPulse2;

    pwbuff[pwbuffpos] = pulseWidth;
    pwbuff2[pwbuffpos2] = pulseWidth2;
    
    if( ++pwbuffpos == pwbuffsize ) pwbuffpos = 0;
    if( ++pwbuffpos2 == pwbuffsize ) pwbuffpos2 = 0;


    pulseWidth=0;
    pulseWidth2=0;

    for( int p=0; p<pwbuffsize; p++ ){
        pulseWidth += pwbuff[p];
        pulseWidth2 += pwbuff2[p];
    }

    pulseWidth /= pwbuffsize;
    pulseWidth2 /= pwbuffsize;

}

You mean just use the functions in "servo.h" ?

Does it have control structures with using the Wii NunChuck's joyStick_x and joyStick_y functions?

No, of course it doesn't, but developing your own driver for servos when one already exists is silly.

Please use code tags when posting code.

I modified my last post for code tag....sorry about that.

So I can use the pre-existing drivers and decide how to add the Joystick operations? Basically I want to monitor the Joystick for X and Y movement and move accordingly in the + or - direction based on my the Joysticks output, but only when the Z Button is pressed.