Go Down

Topic: Trouble with Servo Jitter on the Mega (Read 14398 times) previous topic - next topic


Just had a quick look, and SoftwareSerial doesn't use interrupts at all. NewSoftSerial uses timer0 so you could almost certainly implement a precise servo controller using timer1.

If you are interested I could knock up some code.



Apr 17, 2010, 08:49 am Last Edit: Apr 17, 2010, 08:50 am by mem Reason: 1
Chris, note that the Servo library supplied with Arduino version 0016 does run one or two servos on timer1 without interrupts and its pretty well tested. So if you want to knock something up with microsecond precision  (it currently only has a method for input in degrees), perhaps you could add the writeMicroseconds function to that code.


Apr 19, 2010, 02:03 pm Last Edit: Apr 19, 2010, 02:09 pm by cjparish Reason: 1
Chris, note that the Servo library supplied with Arduino version 0016 does run one or two servos on timer1 without interrupts

I have had a look at the Servo.c file and it look to me like the servo library always uses interrupts to handle the servos, regardless of which timer it is using. If this is not the case, could you point me to the section of code that does this as I am interested in how it decides to use an intrrupt or not.

In the mean time I have knocked up some code that will position a servo using timer1 without any interrupts whatsoever.

Code: [Select]

* Precision servo positioning.
* Uses timer1 in phase and frequency correct PWM mode
* Doesn't use interrupts, so should be immune to interrupt issues.
* Chris Parish 2010

//The standard timings for servos are 1.5ms for center, 1ms and 2ms for the full extents of travel
//however, most modern servos can operate an extended range, this can be as wide as 0.5ms to 2.5ms
//Consult the documentation for your servo for further details
#define SERVO_LOWER_LIMIT  1000
#define SERVO_UPPER_LIMIT  2000
#define SERVO_CENTER       1500

//Set your servo travel here. In standard mode most servos travel approx 90 degrees (45 either side of center)
#define SERVO_ANGLE_LOWER  0    

const int servo = 9;
int angle;

void setup()
 //Set up the timer------------------------
 //TCCR1A register
 TCCR1A = 0; //clear the register completly
 TCCR1A |= _BV(COM1A1) | _BV(COM1B1);  //set the required bits

 //TCCR1B register
 TCCR1B = 0; //clear the register completley  
 TCCR1B |= _BV(WGM13) | _BV(CS11);  //set the required bits

 //TCCR1C register
 TCCR1C = 0; //clear the register completley

 //Set the top limit - Complete frame length
 ICR1 = 20000;  //In this mode (assuming that you are running at 16mhz) The values are set in microseconds.

 //Set the output compare registers which dictate the servo position
 OCR1A = SERVO_CENTER; //1.5ms pulse, center the servo
 OCR1B = SERVO_CENTER; //1.5ms pulse, center the servo

 //Set pins 9 and 10 to output the waveform to the servos
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);


void setServoAngle(int servo, int angle)
 //constrain the angle measurement
 angle = constrain(angle, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER);
 //convert the angle measurement into a pulse length

 //write the angle to the appropreate servo output (1 or 2  -aka- 9 or 10)
 if (servo == 1 || servo == 9)
   OCR1A = angle;
 else if (servo == 2 || servo == 10)
   OCR1B = angle;

int getServoAngle(int servo)
 int pulse;
 int angle;
   if (servo == 1 || servo == 9)
   pulse = OCR1A;
 else if (servo == 2 || servo == 10)
   pulse = OCR1B;


There is no loop() in the code above, feel free to out your own in!
It does work, I tried it.



it looks to me like the servo library always uses interrupts

Chris, perhaps you were not looking at the 0016 servo code.

I have uploaded the old servo library (from 0016) to the playground.

Its been renamed to Servo2 so the name won't conflict with the latest Servo library.
(its called Servo2 to remind users that it only supports two servos).

When this file is unzipped to the libraries directory it can be used by including "Servo2.h"

Note that Servo2 only works with pins 9 and 10 and does not work on the Mega.


You are quite right, I was not looking at the 0016 version. I only started with arduino at version 0017 and didn't realise that the servo library was different prior to that. Noobie mistake there on my part



you may want to read through the servo reference page: http://www.arduino.cc/en/Reference/Servo

have fun!


Ah yes, I see now.
Well that will teach me to open mouth before engaging brain won't it.

It states that Servo (the old one) won't work on the mega. I assume this is because of the different timers on the Mega. I would look at the datasheet, but I am at work and I don't think my iPhone will like a 25mb+ PDF!

Thanks for putting me right.


Apr 21, 2010, 06:11 am Last Edit: Apr 21, 2010, 06:16 am by mem Reason: 1
The old library was hard coded for pins 9 and 10 but the Mega does not use these pins. I have updated the Servo2 zip file linked above with code that should work on the Mega (pins 11 and 12) as well as on a standard board using pins 9 and 10.

The build will automatically using the correct pins based on the board selected in the IDE. ( will add support for Sanguino and Teensy if anyone needs it)

I am traveling and without Mega board or servos to test this, so please let me know if there are any problems.

Go Up