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();
// 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;
}
}
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.
More info here.