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;

  pinMode(9, OUTPUT);    
  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();

    // receive data as angle
    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;


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.

More info here.

  • 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, 2015 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, 2015 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, 2015 at 15:17
  • 1
    I found that it has a dead band of 5us. So it won't move until the width changes by 5us. Apr 15, 2015 at 16:10

1 Answer 1


The best is to use 10us Period, instead of 50us.
That precision will be close to 1°

  • Thanks, @Mathsman, I got it working, you were right! Just created a timer1 interrupt using CTC mode and then generated an output signal with a frequency of 100kHz that I could increment the angle by approximately 1 degree. Apr 28, 2015 at 1:48
  • Your welcome. I recommended this as I have already tried it. May 1, 2015 at 8:46
  • It has precision of 1.1to 1.2 degrees. May 1, 2015 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.