ServoTimer2 - drives up to 8 servos

Mem, thanks for developing this library for us! I have a question about making the PWM frame rates faster.

In the code there is a define:
#define FRAME_SYNC_PERIOD 20000

If I wanted to shorten the frame rate from every 20ms to something like 5ms or 10ms, is this the only variable to change in the library?

I had changed this define from 20000 to 10000, but then my motors seemed to misfire, like its missing a PWM pulse (I'm controlling 4). Before I muck with the code anymore, is there anything else I should adjust?

I'm using this code in a 4 rotor helicopter (quadrocopter) application where updating the ESC's of our brushless motors as fast as possible would be ideal

Thanks!

Hi Mikro, I just noticed that the #define FRAME_SYNC_PERIOD is in both the .h file and the .cpp file. It's not something that should be casually changed so I will remove it from the .h file in the next version, you should remove one of the defines if you want to chagne it.

As you probably know, the refresh period must be longer than the sum of the longest durations for all of the servos. So 10000 should be ok for four channels if you change the #define NBR_CHANNELS to 4. But make sure your servos can handle that refresh rate.

i'd love to use this library for my current project, all the feed back seems to be good. but im having some trouble instaling it. i folowed the instructions but when i compiled the test code i get this error

47: error: ServoTimer2.h: No such file or directory In function 'void setup()':
In function 'void loop()':

please reply cos i kinda need this for my project.
lamens terms would be apriciated :stuck_out_tongue:

That message indicates that the ServoTimer2 library has not been found.

Navigate to the directory that contains the arduino libraries. This should be in a directory below the place you installed the arduino runtime code – something like: Arduino-0012/ hardware/libraries.

Below the libraries directory should be the libraries that come with the Arduino download, such as the wire library. You need to make a directory called ServoTimer2 beneath the libraries directory (parallel with the wire directory and other standard libraries).

In the ServoTimer2 directory should be at least the following files:
ServoTimer2.h
ServoTimer2.cpp

Once you have the files in the right place, the development environment should compile the library and create another file – ServoTimer2.o and link this with your sketch.

I hope that helps

how do you save .cpp and .h type files. kinda new to this sort of thing... can you tell :stuck_out_tongue:

Copy the text into into a text editor (notpad or similar) and save using the appropriate filename.

hummm well i did that and im still gettin the error

after several attempts i now get this when i open the arduino IDE:

In file included from ServoTimer2.cpp:9:
/ServoTimer2.h:3:1: warning: "/*" within comment
ServoTimer2.cpp: In constructor 'ServoTimer2::ServoTimer2()':
ServoTimer2.cpp:59: error: a function-definition is not allowed here before '{' token
ServoTimer2.cpp:132: error: expected `}' at end of input
ServoTimer2.cpp: At global scope:
ServoTimer2.cpp:10: warning: 'void initISR()' declared 'static' but never defined
ServoTimer2.cpp:11: warning: 'void writeChan(uint8_t, int)' declared 'static' but never defined
ServoTimer2.cpp:23: warning: 'isStarted' defined but not used

It looks like some text has been lost in copying the file.

I have put the Library files into a zip in the playground here:
http://www.arduino.cc/playground/uploads/Main/ServoTimer2.zip

Overwrite the current files in your ServoTimer2 directory with the ones in that zip.

Thanks! that works great:D

This library is awesome! Works great! :slight_smile:

I if need to drive a servo from one position to another, how can tell him to move at different speeds?

None of the servo libraries for the arduino have functions to instruct the servo to move at a particular speed. You would need to add that functionality yourself.

One way to do that is to write a function that takes parameters for the servo identifier, the desired position and the desired speed. The function would read the current servo position and if it was not at the desired position it would write a new value that moved the servo in the desired direction by an amount determined by the desired speed. This function would need to be called repeatedly to move the servo smoothly.

If this is beyond your programming skills you may want to consider an external hardware servo controller. For example, I think the pololu controller supports speed settings for each servo: Pololu Micro Serial Servo Controller (assembled)

I will try to build that function.. thanks mem!

If you get stuck or need assistance getting it working, post your code and I am sure someone here will help.

some tips: – try testing the routine by writing the state (current servo value, desired position, speed and new position) to the serial port so you can see if you r routine is doing what you expect. Remember that your routine needs to be called at regular intervals, in your test code try using an interval of 20ms. Also, keep the test sketch you use to develop and test the routine as simple as possible, its a lot harder to debug if the code is in the middle of a complex app.

that is what I am thinking, I will post the code as soon as I have some results.
thanks for your help mem!

This is what I came up with, and it works good.
Drives 3 servos at different speed rates.

I´m sure it is not the best way to do it, it is still a work in progress.
I hope someone more skilled can take this further. :slight_smile:

It would be cool to drive the servos in a way that they arrive all at the destination at the exactly same time.
Another cool feature could be to implement the Tween class, or something similar...

Updated Code:

  /*
  
  This sketch cycles three servos at different rates.  Still a work in progress.
  
  Sorry for my english  :-)
  
  www.guilhermemartins.net
  
  */


// ========================================================================  Servo library

#include <ServoTimer2.h>  // the servo library

// #define MIN_PULSE  750  // minimum range - 0
// #define MAX_PULSE  2250  // maximum range - 180

// define the pins for the 3 servos
// maximum is 8 servos
#define servo1Pin  2
#define servo2Pin  3
#define servo3Pin  4

// servo REAL names
ServoTimer2 servo1, servo2, servo3;    

// I use this variables to pass the servo names from one function to the other
ServoTimer2 servo1Name, servo2Name, servo3Name;

// actual positions
int actualPos1, actualPos2, actualPos3;

// destination positions
int dest1, dest2, dest3;

// speed
int inc;

// ========================================================================  Metro library
// http://www.arduino.cc/playground/Code/Metro
#include <Metro.h>

// this metro is just a way to have a continuos call of diferent positions for the servos
// it call the setupServoParams function every 4 seconds
int servo1_duration = 4000; 
Metro servo1_metro = Metro(servo1_duration); 
int servo1_control = 0;

// this metro is used to update servoControl function
int servoControl_duration = 99999;
Metro servoControl_ID = Metro(servoControl_duration); 

// ======================================================================== Setup()

void setup() {
  
  Serial.begin(9600);  
  
  // attach pins for each servo
  servo1.attach(servo1Pin);     
  servo2.attach(servo2Pin);
  servo3.attach(servo3Pin);
}

// ======================================================================== Loop()

void loop() {
  
  // this metro is activated when the actual position is diferent than the destination position 
  if (servoControl_ID.check() == 1) {
    servoControl(servo1Name, servo2Name, servo3Name, dest1, dest2, dest3, inc);  
  }
  
  // this is just a continuos call for the servoControl function
  // every 4 seconds the positions are changed and updated
  
  //servoControl(servo1, servo2, servo3, servo1position, servo2position, servo3position, speed);
  
  if (servo1_metro.check() == 1) {
    if (servo1_control == 0) {
      Serial.println("1");
      servoControl(servo1, servo2, servo3, 750, 750, 750, 10);
      servo1_control++;
    } 
    else if (servo1_control == 1) {
      Serial.println("2");
      servoControl(servo1, servo2, servo3, 1750, 1750, 1750, 20);
      servo1_control++;
    } 
    else {
      servoControl(servo1, servo2, servo3, 2250, 2250, 2250, 4);
      Serial.println("3");
      servo1_control = 0;
    }
  }

}

// ======================================================================== servoControl()

// this function makes the servos move
void servoControl (
                  ServoTimer2 _servo1Name,
                  ServoTimer2 _servo2Name,
                  ServoTimer2 _servo3Name,
                  int _dest1,
                  int _dest2,
                  int _dest3, 
                  int _inc
                  ) {
                    
  // activate the metro for position update                  
  servoIntervalReset(10);
  
  servo1Name = _servo1Name;
  servo2Name = _servo2Name;
  servo3Name = _servo3Name;
  
  dest1 = _dest1;
  dest2 = _dest2;
  dest3 = _dest3;
  
  inc = _inc;
  
  int val1 = servo1Name.read();
  int val2 = servo2Name.read();
  int val3 = servo3Name.read();
    
  int newPos1, newPos2, newPos3;
  
  if (val1 > dest1) {
    newPos1 = val1 - inc;
  } else {
    newPos1 = val1 + inc;
  } 
  
  if (val2 > dest2) {
    newPos2 = val2 - inc;
  } else {
    newPos2 = val2 + inc;
  }
  
  if (val3 > dest3) {
    newPos3 = val3 - inc;
  } else {
    newPos3 = val3 + inc;
  } 
  
  // check if values are all updated
  if (val1 == dest1 && val2 == dest2 && val3 == dest3) {
    servoIntervalReset(99999);
  }
  
  // write the new positions for the 3 servos
  servo1Name.write(newPos1);
  servo2Name.write(newPos2);
  servo3Name.write(newPos3);
}

// ======================================================================== servoIntervalReset()
// metro reset function
void servoIntervalReset(int duration) {
  servoControl_ID.interval(duration);
  servoControl_ID.reset();
}

Ok a few problems and all because I dont know what I'm doing. I'm trying to build an object avoiding robot using a ping sensor and 3 servos 2 for the wheels and 1 to rotate the ping sensor. I'm trying to get my servo to sweep so I can use the Ping sensor on it But I cant find any examples of how to set the servo to 90, 0, or 180 degrees.
Then From what I read in the example code seen in the top of the thread that increments the servo. It seems that if I Write to the servo 1000 it goes one way and If I Write 2000 to the servo it turns the other way how do I stop the servo? I'm so confused and I dont think I understand this library however I know its what I'm supposed to use to control the 3+ servos. Can someone please help?

I supposed you are using two servos for continuos rotation. This servos should be used only to move the robot.

The unmodified servo should be used for the ping.

If I Write 2000 to the servo it turns the other way how do I stop the servo?

I guess you are using one continuos rotation servo here, try to use the unmodified one.

quibot, good to hear you have that working. It looks more complicated than I expected but I have not used metro so I will need to find some time to look more closely at the code.

kennyj, here is an example sketch that moves three servos to 0, 90 and 180 degrees. The library expects servo values in microseconds but I have added a macro to demonstrate how you can use values in degrees if you want. I hope it helps clarify how to use the library to move servos

 // this sketch cycles three servos to 0, 90 and 180 degrees  

#include <ServoTimer2.h>  // the servo library

// define the pins for the servos
#define rollPin  2
#define pitchPin 3
#define yawPin   4

#define degreesToUS( _degrees) (_degrees * 6 + 900) // macro to convert degrees to microseconds

ServoTimer2 servoRoll;    // declare variables for up to eight servos
ServoTimer2 servoPitch; 
ServoTimer2 servoYaw; 
 
void setup() {
  servoRoll.attach(rollPin);     // attach a pin to the servos and they will start pulsing
  servoPitch.attach(pitchPin); 
  servoYaw.attach(yawPin); 
}

void loop()
{ 
   servoRoll.write(degreesToUS(0));
   servoPitch.write(degreesToUS(90));
   servoYaw.write(degreesToUS(180));
   delay(1000); 
   
   servoRoll.write(degreesToUS(90));
   servoPitch.write(degreesToUS(180));
   servoYaw.write(degreesToUS(0));
   delay(1000); 
   
   servoRoll.write(degreesToUS(180));
   servoPitch.write(degreesToUS(0));
   servoYaw.write(degreesToUS(90));
   delay(1000); 
}

I don't have servos connected up at the moment so haven't tested this, please post if there is a problem