How to precisely control servo motor by changing duty cycle?

I developed a PWM using timer1,using arduino uno and digital output, and identified that when I send a wave with duration of 0.6ms in High level, the motor goes to 0º. If I send 2.1ms, it goes to 180º. I tried to make a relationship between these scales to send the angle and change the time period in order to achieve that angle and it did not work.

I would like to move with a precision of 1 degree, is that possible? Just adjusting the time period.

The model of the motor is mg996r. Maybe I am missing something.

My code just generates an interrupt over 50 microsencods and I use this to set the frequency of 50Hz and the duty cycle in ms using digitalWrite associated with pin 9.

#include <TimerOne.h>

double t = 0.0;

double period = 0;

void setup()
{
t = 0;
Serial.begin(9600);

pinMode(9, OUTPUT);
Timer1.initialize(50);
Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}

void loop()
{
// Main code loop
// TODO: Put your regular (non-ISR) logic here
if (Serial.available() > 0) {
float grau = Serial.parseFloat();

if (grau > 180) grau = 180;
if (grau < 0) grau = 0;

// set period for that angle
// relationship developed between angle and period in ms
//set it to period
period = (0.00833*grau + 0.6)*1E-3;
}

}

/// --------------------------
/// Custom ISR Timer Routine
/// --------------------------
void timerIsr()
{
t += 50E-6;
if (t <= period) {
digitalWrite(9, HIGH);
}
else if (t < 20E-3) { // periodo max de 20ms -> 50Hz
digitalWrite(9, LOW);
}
else {
t = 0;
}
}

UPDATE:

I just got it working by creating a timer1 interrupt on CTC mode with a frequency of 100kHz and counting the necessary time to get increments (~ 10us each) of around 1 degree on my servo motor.

• The relationship is like a map between 0.6 ms -> 2.1ms and 0 -> 180 angle degrees. It works, but the problem is that it does not work for a precision of 1 angle degree as Arduino Servo Library does... Apr 14 '15 at 22:12
• For a precision of one degree, you need a minimum timer increment of 8.33us, which is optimistic. Your current 50us period gives you a resolution of ~6 degrees. Apr 15 '15 at 4:43
• I tried a resolution of 1us but it didn't work, the motor did not move. Can I achieve this using timer1? Apr 15 '15 at 15:17
• I found that it has a dead band of 5us. So it won't move until the width changes by 5us. Apr 15 '15 at 16:10