variables change value with SoftwareServo.write()

I’m trying to write a simple serial controller 8-servo controller using SoftwareServo. I have an array of integers called servoPositions, into which I’m placing the values to be sent to the servos. If I use Serial.print to print the array before I call SoftwareServo::write() with each value, they read out correctly. If I print them after the write() call, some (not all) of them print out as different values. I can even make copies in global ints, and before the write() call they are normal, after the write() call they are mangled. WTF. I’m beginning to suspect it’s the Serial.print that’s the problem, not the values themselves. If I comment out the follwing lines:

195 for(int i = 0; i < SERVO_COUNT;i++){
196 servos[servoPins_].write(servoPositions*);_
197 }[/font]
the problem disappears. I use the serial monitor to send the string: [1,2,3,4,5,6,7,8] The output looks like this:
Ready
Received: 1,2,3,4,5,6,7,8]
4 : [1,2,3,4,5,6,7,8]
_
[1,2,3,4,5,6,7,8]_
4 : [1025,11,3,4,1285,27,7,8]
_
[1,2050,15,4,5,6,7,8]_
The last two lines are after the serial.write() call. If I comment out the serial.write() call, then it looks like this:
Ready
Received: 1,2,3,4,5,6,7,8]
3 : [1,2,3,4,5,6,7,8]
_
[1,2,3,4,5,6,7,8]_
3 : [1,2,3,4,5,6,7,8]
_
[1,2,3,4,5,6,7,8]_
Can anyone shed some light on this? It’s driving me nuts.
Thanks,
T.
Here’s the full Code:
_
```_
#include <SoftwareServo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SERVO_COUNT 8
#define BUFFER_SIZE 256

int servoPins[SERVO_COUNT] = {
 5,6,7,8,9,10,11,12};
SoftwareServo servos[SERVO_COUNT];  //create servo objects to control servos

//storage for the servo positions
int servoPositions[SERVO_COUNT];

//flag to determine if the servo positions have changed
int updated = 0;

double t = 0;

long startTime = 0;
long currTime = 0;

int t1,t2,t3,t4,t5,t6,t7,t8;

//message character delimiters
char delims[8] = “,”;

//message buffers
char msgBuffer[BUFFER_SIZE];
int msgBufferCount = 0;

//take a message string (delimited by brackets, comma-separated ints) and
//extract the expected 8 integers, storing them in the provided int array
int cvtMsg2Ints(char* msg, int* values){
 int count = 0;
 char* buffer = NULL;

//pull out the first token
 buffer = strtok(msg, delims);

while(buffer != NULL){
   //process the token, converting to an int and outputting it
   values[count] = atoi(buffer);

//Serial.print("Buffer = “);
   //Serial.print(buffer);
   //Serial.print(” → ");
   //Serial.print("values “);
   //Serial.print(count);
   //Serial.print(” = ");
   //Serial.println(values[count]);

//increment the count
   count++;

//pull out the next token
   buffer = strtok(NULL,delims);
 }

//Serial.print("validcount = ");
 //Serial.println(count);

return count;
}

void setup()
{

for(int i = 0; i < SERVO_COUNT; i++){
   servos[i].attach(servoPins[i]);  // attaches the servo on pin 12 to the servo object
   servoPositions[i] = 200; //some approximately acceptable value
 }

Serial.begin(9600);
 Serial.println(“Ready”);

startTime = millis();
}

void loop()
{

currTime = millis();
 t = (double) (currTime - startTime) / 1000.0;

//if there are bytes available
 if(Serial.available() > 0){
   //pull one off
   char msgChar = (char) Serial.read();

//if this is the beginning of a new message, reset the buffer
   //if we’ve overflowed the buffer, reset the buffer
   if(msgChar == ‘[’ || msgBufferCount >= BUFFER_SIZE - 2){
     //Serial.println(“saw [”);
     msgBufferCount = 0;
     msgBuffer[msgBufferCount] = msgChar;
   }

//if this is the end of a message, execute the values and reset the buffer
   //note: 16 is the minimum number of characters in a valid message
   else if(msgChar == ‘]’){
     //Serial.println(“saw ]”);
     msgBuffer[msgBufferCount] = msgChar;

//add a NULL character to mark the string termination
     msgBuffer[msgBufferCount+1] = ‘\0’;

//increment the counter
     msgBufferCount++;

//process the message
     int msgValues[SERVO_COUNT];

Serial.print("Received: ");
     Serial.println(msgBuffer);

//parse the message
     int validCount = cvtMsg2Ints(msgBuffer,msgValues);

//if the message is valid, set the servo values
     if(validCount == SERVO_COUNT){
       for(int i = 0; i < validCount; i++){
         servoPositions[i] = msgValues[i];
       }

updated = 1;
     }
   }

//otherwise, just populate the buffer as normal
   else{
     //Serial.println(“saw char”);
     //store the character
     msgBuffer[msgBufferCount] = msgChar;

//add a NULL character to mark the string termination
     msgBuffer[msgBufferCount+1] = ‘\0’;

//increment the counter
     msgBufferCount++;
   }

}

t1 = servoPositions[0];
 t2 = servoPositions[1];
 t3 = servoPositions[2];
 t4 = servoPositions[3];
 t5 = servoPositions[4];
 t6 = servoPositions[5];
 t7 = servoPositions[6];
 t8 = servoPositions[7];

if(updated != 0){

Serial.print((int) t);
   Serial.print(" : [");
   for(int i = 0; i < SERVO_COUNT;i++){
     Serial.print(servoPositions[i]);
     i == SERVO_COUNT - 1 ? Serial.println("]") : Serial.print(",");  
   }
   
   Serial.print("[");
   Serial.print(t1);
   Serial.print(",");
   Serial.print(t2);
   Serial.print(",");
   Serial.print(t3);
   Serial.print(",");
   Serial.print(t4);
   Serial.print(",");
   Serial.print(t5);
   Serial.print(",");
   Serial.print(t6);
   Serial.print(",");
   Serial.print(t7);
   Serial.print(",");
   Serial.print(t8);
   Serial.println("]");
   
 }

//if the servo values have changed, update the servos
 if(updated != 0){
   for(int i = 0; i < SERVO_COUNT;i++){
    servos[servoPins[i]].write(servoPositions[i]); // sets the servo position
   }
   updated = 0;

Serial.print((int) t);
   Serial.print(" : [");
   for(int i = 0; i < SERVO_COUNT;i++){
     Serial.print(servoPositions[i]);
     i == SERVO_COUNT - 1 ? Serial.println("]") : Serial.print(",");  
   }

Serial.print("[");
   Serial.print(t1);
   Serial.print(",");
   Serial.print(t2);
   Serial.print(",");
   Serial.print(t3);
   Serial.print(",");
   Serial.print(t4);
   Serial.print(",");
   Serial.print(t5);
   Serial.print(",");
   Serial.print(t6);
   Serial.print(",");
   Serial.print(t7);
   Serial.print(",");
   Serial.print(t8);
   Serial.println("]");

}
 delay(15);                           // waits for the servo to get there

SoftwareServo::refresh();
}
_
```*_

My guess is that you are running out of RAM, not helped by that big message buffer.

Here is some code for 8 servos driven from commands received on the serial port that you may be able to adapt to do what you want. It uses the MegaServo library here:
http://www.arduino.cc/playground/Code/MegaServo

#include <MegaServo.h>

#define NBR_SERVOS     8        // the number of servos, up to 48 for Mega, 12 for other boards
#define FIRST_SERVO_PIN 5

MegaServo myServos[NBR_SERVOS] ; // max servos is 48 for mega, 12 for other boards

void setup()
{
  Serial.begin(9600);
  for(int i=0; i < NBR_SERVOS; i++)
    myServos[i].attach(FIRST_SERVO_PIN +i);  
}


void loop()
{
  static int pos = 0;

  if ( Serial.available())
  {
    char ch = Serial.read();

    if(ch >= '0' && ch <= '9')              // is ch a number?  
      pos = pos * 10 + ch - '0';           // yes, accumulate the value
    else if(ch >= 'a' && ch <= 'a'+  NBR_SERVOS) // is ch a letter for one of our servos?
    {
      myServos[ch - 'a'].write(pos);         // yes, save the position in the position array  
      pos = 0;
      int channel =  ch - 'a';
      int  angle = myServos[channel].read();
      int pulseWidth = myServos[channel].readMicroseconds();
      Serial.print("Servo on pin ");
      Serial.print(FIRST_SERVO_PIN + channel, DEC);
      Serial.print(": angle = ");  
      Serial.print(angle,DEC),  Serial.print(", pulse = ");  
      Serial.println(pulseWidth,DEC);
    }
    else if (ch == '*')
    {
      // position all the servos
      for(int i=0; i < NBR_SERVOS; i++)
        myServos[i].write(pos);        
      pos = 0;
    }
    else if (ch == '+')
    {
      // sweep the servos from 0 to 180
      for(int angle = 0;angle < 180; )
      {
        for(int i=0; i < NBR_SERVOS; i++)
        {
          myServos[i].write(angle);
        }
        angle = myServos[0].read();    
        Serial.print("Angle = "); Serial.print(angle,DEC), Serial.print(", pulse = "); Serial.println(myServos[0].readMicroseconds(),DEC);
        ++angle;

        delay(20);
      }
      pos = 0;
    }
    else if (ch == '-')
    {
      // sweep the servos from 180 to 0
      for(int angle = 180;angle >= 0; )
      {
        for(int i=0; i < NBR_SERVOS; i++)
        {
          myServos[i].write(angle);                
        }
        angle = myServos[0].read();  
        Serial.print("Angle = "); Serial.print(angle,DEC), Serial.print(", pulse = "); Serial.println(myServos[0].readMicroseconds(),DEC);
        --angle;
        delay(20);
      }
      pos = 0;
    }
  }
}

the code expects a serial command consisting of a valid value (0 through 180) followed by a letter indicating the servo to write to. The letter ‘a’ is the first servo, ‘b’ the second and so on.

For example:
90a will write a value of 90 to the first servo
180b will write 180 to the second servo

note that numeric values that are 180 degrees or less are treated as angles in degrees, larger values are treated as pulse width in microseconds

A value followed by a * instead of a letter will be written to all servos
The single character + will sweep all the servos from 0 to 180
The single character – will sweep all the servos from 180 to 0