I'm using the Registers of the Arduino micro to get a signal for Electronic Speed Controllers (ESC) for brushless motors. As far as I read, ESCs interpret everything they can, while just ignoring too fast update rates. If somebody knows better, this would be a great time to yell.
The goal is to get a digital signal, where a timespan between 1 and 2 ms is HIGH and the rest low. Ideally I want this at 50-400Hz, since 488Hz is the fastest possible frequency, and 50 Hz the standard Servo frequency.
I try to use Phase Correct Mode to count up and down continuously. As the value in the counter reaches my set OCRnx on the way up, it sets the output pin LOW, as it reaches the same value on the way down, after reaching TOP(value), it sets the output HIGH. In ATmega documentation terms, this is NON-inverted Phase-Correct-PWM.
So I set the Registers DDR (to set the pin as output), TCCR1A and TCCR1B and ICR1 (TOPvalue = between 20000 and 2500).
Now using OCR1A = 1000 should give me a pulse width of 1000ms. This is the expected or target behaviour.
My testing code is:
// using a 16-bit timer to generate PWM signals for ESCs
// Phase Correct Mode counts from Bottom to Top and back to Bottom
// with a prescaler of 8
// motor signal (OCRnx) uses values of 1000 (idle) - 2000 (max)
// which directly corresponds to microseconds HIGH-time
// setting the range to (BOTTOM) 0 - TOPvalue sets the frequency
// two important formulas are:
// frequency(PWM) = F_CPU / (2*Prescalar*TOPvalue)
//
// PulseWidth [s] = High-tick-count / (F_CPU/Prescalar)
// High-tick-count = 2 * OCR-value
// n = number of timer (1,3)
// x = A,B,C
#include "Arduino.h"
// #include <Arduino.h>
// #define DEBUG
// #include <Moto.h>
#define PRESCALAR 8
#define PWM_FREQUENCY 50
#define TOP_VALUE F_CPU/(2*PRESCALAR*PWM_FREQUENCY)
uint16_t dutytime = 1000; // this gives idle throttle signal
void setup(void) {
Serial.begin(115200);
// moto.setup();
// TIMER 1
// TIMSK1 = 0; // disable Interrupts for timer1
DDRB |= (1<<DDB5); // D9 Output
DDRC |= (1<<DDC6); // D5 Output
// set 1000ms to start motors in idle mode
OCR1A = 1000L;
OCR3A = 1000L;
// bits 7,5,3 PWM Output on pins A,B,C respectively
// bits 1,0 WGM_1,0: phase correction mode
// TCCR1A |= B10000010; // in hex: 0xAA for all 3 = B 1010 1010
TCCR1A |= (1<<COM1A1)|(1<<WGM11);
// bit 4,3 WGM_3,2: phase correction mode
// bits 2,1,0 Prescalar: 8
// TCCR1B |= B00010010; // in hex: 0x12; B 0001 0010
TCCR1B |= (1<<WGM13)|(1<<CS11);
ICR1 = TOP_VALUE;
// TIMER 3
// TIMSK3 = 0; // disable Interrupts for timer3
// bit 7 PWM Output on pin A
// bits 1,0 WGM_1,0: phase correction mode
TCCR3A |= B10000010; // in hex: 0x82; // B 1000 0010
// bit 4,3 WGM_3,2: phase correction mode
// bits 2,1,0 Prescalar: 8
TCCR3B |= B00010010; // in hex: 0x12; B 0001 0010
ICR3 = TOP_VALUE; // TOPvalue = 2048
}//setup
void loop(void) {
// Serial.println(TOP_VALUE);
// delay(500);
while (dutytime < 2000) {
dutytime += 150;
OCR1A = dutytime;
OCR3A = dutytime;
Serial.println(dutytime);
delay(1500);
}
while (dutytime > 1000) {
dutytime -= 150;
OCR1A = dutytime;
OCR3A = dutytime;
Serial.println(dutytime);
delay(1500);
}
}//loop
I repeated the settings for timer3 to get something to compare to. Both do give the same: if i delete the loop and just write loop{}
nothing happens. The pins are high and seem to stay so. With the while loops activated, my multimeter gives me 1Hz (which are the changes of course) and between 99.9% duty cycle and 96%.
An led, which i connected to it blinks every second a very short time.
What am I doing wrong?
Pulse width of 1000ms at a sample rate of 488.28Hz
that seems contradictory, as the maximum pulse width can only be 2ms at 488Hz.