6 servo's - timing problem?

Hi

I’m using the Servo library (http://www.arduino.cc/playground/ComponentLib/Servo).

I extended the above example for 6 servo’s (connected at digital pin 2 to 7). When I send serial commands manually: e.g. “135e” (135 degrees, fifth servo), “45a” (45 degrees, first servo), “90e” (90 degrees, fifth servo) every servo moves in the exact position. When I fire those 3 commands together: e.g. “135e45a90e”, only 45a is set. The same happens when I move 4 servo’s together: e.g.: “90c90b45d135a”…

I’m searching almost one day now and I’m getting more and more lost…

Could it be that all 3 commands together doesn’t work because the commands are send to close after each other? (I already tried to embed a delay (150ms → datasheet servo’s), but than my program ‘waits’ for 150ms while Servo::refresh() needs to be called at least every 50ms.

Maybe something wrong in my program?

Help help help… Almost lost :-?

Thanks in advance!

//' ADG 17/1/2008
//' S.P.I.D.E.R. BRAIN V 1.2.2
// lala

// 23/4/2008: verder aan werken: init commando's: afstellen
// 1/5/2008: probleem NEKservo opgelost (timing min en max pulse)
// 12/5/2008: STAARTservoe toegevoegd (6 servo's in totaal nu) + servo op nieuwe poorten (2-7 ipv analog 0 - analog 6)!

// The Software Servo Library can drive servos on all of your pins simultaneously. The API is patterned after the wiring.org servo library but the code is different. You are not limited to 8 servos, but you must call the Servo::refresh() method at least once every 50ms or so to keep your servos updating.

#include <Servo.h>

Servo servoA; 
Servo servoB;
Servo servoC;
Servo servoD;
Servo servoE;
Servo servoF;

static bool bStandardPattern = false;
static int iDelay = 20;
 
void setup() {
  
  pinMode (13, OUTPUT);
  
  // Timing diagram: http://www.robotstore.com/download/Servo_Motor_Timing_1.pdf
  int minPulse = 1000;  // Minimum servo position 700
  int maxPulse = 2000; // Maximum servo position 2000
  
  

  servoA.attach(2); // digital 2
  //servoA.setMinimumPulse(minPulse);
  servoA.setMaximumPulse(maxPulse);
  
  servoB.attach(3); // digital 3
  //servoB.setMinimumPulse(minPulse);
  servoB.setMaximumPulse(maxPulse);
  
  servoC.attach(4); // digital 4
  //servoC.setMinimumPulse(minPulse);
  servoC.setMaximumPulse(maxPulse);
  
  servoD.attach(5); // digital 5
  //servoD.setMinimumPulse(minPulse);
  servoD.setMaximumPulse(maxPulse);  
  
  servoE.attach(6); // digital 6
  //servoE.setMinimumPulse(minPulse);
  servoE.setMaximumPulse(maxPulse);
  
  servoF.attach(7); // digital 7
  //servoF.setMinimumPulse(minPulse);
  servoF.setMaximumPulse(maxPulse);
  
  Serial.begin(19200);
  Serial.print("I am ready!");
  
  for (int i = 0 ; i < 3 ; i++)
  {
  digitalWrite(13, HIGH);   // sets the LED on
  delay(500);               // waits for a second
  digitalWrite(13, LOW);    // sets the LED off
  delay(250); 
  }
   
}

void loop() {

  static int v = 0;

  // do some tricks ;-)
  if (bStandardPattern)
  {             
    pushUps();
    delay(iDelay);
    }

  if ( Serial.available()) {
    char ch = Serial.read(); // wacht tot waarde gelezen wordt!!!
    Serial.println(ch);
      
    switch(ch) {
      case '0'...'9':
        v = v * 10 + ch - '0';
        Serial.println(v, DEC);
        break;
      case 'a':      
        servoA.write(v);
        v = 0;
        break;
      case 'b':
        servoB.write(v);
        v = 0;
        break;
      case 'c':
        servoC.write(v);
        v = 0;
        break;
      case 'd':
        servoD.write(v);
        v = 0;
        break;
      case 'e':
        servoE.write(v);
        v = 0;
        break;
      case 'f':
        servoF.write(v);
        v = 0;
        break;  
      case 'l':
        pushUps();        
        break;              
      case 'L': // enable-disable standard loop pattern (for external powered use)
       bStandardPattern = !bStandardPattern; 
       break; 
      
      case 'r':
        servoA.write(90);
        servoB.write(90);
        servoC.write(90);
        servoD.write(90);
        servoE.write(90);
        servoF.write(90);
        break;   
     case 'w': AF(); delay(iDelay); break;
     case 'x': DF(); delay(iDelay); break;              
  }
}
  Servo::refresh();
  //delay(iDelay); // anders slaat servo E tilt
} 

void pushUps()
{
    static bool flag = true;
        static int x = 0;
        
        servoA.write(x);
        servoB.write(x);
        servoC.write(x);
        servoD.write(x);
        
        // 45° diff
        if(flag) { x+=45;}
        else { x-=45;}
        if(x>=180 or x<=0) { flag = !flag;}              
}

void AF() // move leg A (by lifting head = servo E, then moving leg A, putting head down)
{ 
  servoE.write(135); delayMicroseconds(iDelay);
  servoA.write(45);  delayMicroseconds(iDelay);
  servoE.write(90);  delayMicroseconds(iDelay);
}

void DF() // move leg D (by lifting back = servo F, then moving leg D, putting back down)
{
  servoF.write(135); delay(iDelay);
  servoD.write(135); delay(iDelay);
  servoF.write(90);  delay(iDelay);
}

If you are trying to power the servos from the Arduino's 5v supply, try connecting the servos to an external power 5v power supply. The built in regulator may not be able to handle the current from all the servos trying to move at once.

Hi mem,

I am already using external power for the servos. The Arduino board is powered by USB. (so that the power sources are also isolated and not interefering)

I would check to see if the correct values are written to all the servos. You could put the following code in one of the routines that is not working correctly to see if the correct values were written:

Serial.print(“val for servos A - F is “); Serial.print(servoA.read()); Serial.print(“, “); Serial.print(servoB.read()); Serial.print(“, “); Serial.print(servoC.read()); Serial.print(“, “); Serial.print(servoD.read()); Serial.print(“, “); Serial.print(servoE.read()); Serial.print(“, “); Serial.println(servoF.read());

Hi mem,

Thanks! I'll try that en I'll post my observation or with some luck conclusion ;-)

It looks like the values are not being written. Try sending an 'r', that should write 90 into all the servos. If it does, then the problem is probably in the code that is parsing the servo values.

Does the serial output of the digits match what you send? i.e. the output from these statements: v = v * 10 + ch - '0'; Serial.println(v, DEC);

Does the serial output of the digits match what you send? i.e. the output from these statements: v = v * 10 + ch - '0'; Serial.println(v, DEC);

Yes!

But... I detected something else:

I've also written a C#program that is able to send some "command string" en load/save them to file, together with a 'step' feature. By using your previous tip: servoX.read(), i've detected when I send the commands too fast through the serial port, they are messed up (don't know exactly why at this moment, maybe because I'm sending faster than the baud rate set for my COM-port). But that is why they are messed up at the end!

Thanks a lot for helping me out! :D