Arduino/Nunchuck/Servo Project Problems

Hello All,

First time poster, so go easy on me XD

Here is what I am running:
Arduino Uno (running 0022)
Wii Nunchuck
2 Servo Tower Pro Motors
External Power
Windows 7

I am trying to do a simple servo pan/tilt nunchuck operated project. Pretty much, if I move the joystick up/down I want it to correspond to one servo and left/right to the second servo. My current problem is that at random times during the program, the servos will just stop responding. I then have to reset my Arduino and it again gives me a random amount of time to control the servos before they just stop responding. This continues until I want to throw myself against a wall. I thought maybe it was due to a power issue, so I am currently running off of external power with the same issues. I then thought it was due to both servos running at the same time and tried to remove one but continued with the same issues. Now I am thinking it has to be something wrong with my code.

So, here is my code:

#include <Wire.h>
#include <SoftwareServo.h> 

uint8_t buf[6];       // buffer for the six-bytes packet coming from Nunchuck
int cnt=0;            // count of bytes in the buffer
int readcnt=0;        // number of times we read a packet from Nunchuck
int ledPin=13;        // which pin will host the blinking LED
int x = 0;            // x for nunchuk
int y = 0;            // y for nunchuk

/** Adjust these values for your servo and setup, if necessary **/  

/* SERVO PIN */
int servoPinX    =  2;    // control pin for servo motor x  
int servoPinY    =  3;    // control pin for servo motor y

/* GUN PIN*/
int pinGun = 12;

/* SERVO X */
int minPulseX    =  600;  // minimum servo position  
int maxPulseX    =  2400; // maximum servo position  
int turnRateX    =  60;   // servo turn rate increment (larger value, faster rate)  

/* SERVO Y */
int minPulseY    =  600;  // minimum servo position  
int maxPulseY    =  2400; // maximum servo position  
int turnRateY    =  60;   // servo turn rate increment (larger value, faster rate)  

int refreshTime  =  20;   // time (ms) between pulses (50Hz)  

/** The Arduino will calculate these values for you **/  
int centerServoX;        // center servo position  
int pulseWidthX;         // servo pulse width  
int moveServoX;          // raw user input  

int centerServoY;        // center servo position  
int pulseWidthY;         // servo pulse width  
int moveServoY;          // raw user input 

long lastPulse = 0;      // recorded time (ms) of the last pulse 
int toleranceX  = 30;    // tolrance for servo X 
int toleranceY  = 30;    // tolrance for servo Y

SoftwareServo myservo;
SoftwareServo myservoY;

int val;
int valY;

uint8_t nunchuk_decode(uint8_t x)   // decode nunchuck data
{
  return (x^0x17)+0x17;             // not that an hard encryption...
}

void nunchuck_ack()                 // acknowledge a Nunchuck packet
{
  Wire.beginTransmission(0x52);     // send a zero to device 0x52
  Wire.send(0);
  Wire.endTransmission();
}

void init( int posX, int posY)
{
  myservo.attach(servoPinX);
  myservo.write(posX);
  myservoY.attach(servoPinY);
  myservoY.write(posY);
}

void setup()                        // initialization
{
  int n;
  digitalWrite(ledPin, HIGH);       // turn on LED
  for(n=0; n<6; n++) buf[n]=0;      // fill buffer with zero values
  Serial.begin(9600);               // console init
  Wire.begin();                     // TWI init
  Wire.beginTransmission(0x52);     // nunchuck init
  Wire.send(0x40);
  Wire.send(0);
  Wire.endTransmission();
  digitalWrite(ledPin, LOW);        // turn off LED
  
  centerServoX = maxPulseX - ((maxPulseX - minPulseX)/2);  
  pulseWidthX = centerServoX;        // Give the servo a starting point (or it floats)
  
  centerServoY = maxPulseY - ((maxPulseY - minPulseY)/2);  
  pulseWidthY = centerServoY;        // Give the servo a starting point (or it floats)
  
  init (centerServoX,centerServoY);
  pinMode(pinGun, OUTPUT); 
}


void loop()                         // main loop
{
  Wire.requestFrom(0x52, 6);        // request data from nunchuck
  while(Wire.available())           // read data and light the LED
  {
    buf[cnt++] = nunchuk_decode(Wire.receive());
    digitalWrite(ledPin, HIGH);
  }

  if(cnt>=6)                        // an entire Nunchuck packet was read?
  {
    cnt=0;                          // clear buffer counter
    nunchuck_ack();                 // acknowledge received packet
    digitalWrite(ledPin, LOW);      // turn off the LED
    delay(20);                      // wait 200msec before next loop
  }
   
   /* READ X and Y from nunchuck */   
   x = 0;
   x = ((int)buf[0])-124;
   y = 0;
   y = ((int)buf[1])-131;
   
   String bz = (String)(buf[5]&1 ? "\t- " : "\t[z] ");
   String bc = (String)(buf[5]&2 ? "-" : "[c]");
    
   /*MOVING SERVO X*/
   if (x>toleranceX or x<-toleranceX){
     pulseWidthX = pulseWidthX - x;
     if (pulseWidthX<minPulseX) pulseWidthX = minPulseX;
     if (pulseWidthX>maxPulseX) pulseWidthX = maxPulseX;
     if (pulseWidthX>minPulseX and pulseWidthX<maxPulseX){   
       val = map(pulseWidthX, 600, 2400, 0, 179);      // scale it to use it with the servo (value between 0 and 180) 
       myservo.write(val);                             // sets the servo position according to the scaled value 
       SoftwareServo::refresh();
     }
   }
   
   /*MOVING SERVO Y*/
   if (y>toleranceY or y<-toleranceY){
     pulseWidthY = pulseWidthY - y;
     if (pulseWidthY<minPulseY) pulseWidthY = minPulseY;
     if (pulseWidthY>maxPulseY) pulseWidthY = maxPulseY;
     if (pulseWidthY>minPulseY and pulseWidthY<maxPulseY){
       val = map(pulseWidthY, 600, 2400, 0, 179);       // scale it to use it with the servo (value between 0 and 180) 
       myservoY.write(val);                             // sets the servo position according to the scaled value 
       SoftwareServo::refresh();
     }
   }
   
   if ( bc.equals("[c]") ) {
     digitalWrite(pinGun, HIGH);   // set the LED on
     delay(10);                    // wait 
     digitalWrite(pinGun, LOW);    // set the LED off
   }
}

If there is anyone that shed some light on this problem it would be greatly appreciated. I am also pretty new to arduino so if you could give me the dummy version that would be even better!

Your buffer is 6 bytes long but you read data as long as there is some and then check to see if you got 6 OR MORE. You should stop at 6 so you don't overflow the buffer.

Why "SoftwareServo" and not "Servo"? If you use Servo you can write directly in microseconds (600 to 2400) rather than converting to degrees. You also don't need to 'refresh' the servos because one of the timers does that in the background.

When the servos "stop responding" are you still seeing the blinks on the LED that let you know that the nunchuk is sending data?