(if you know how an ESC / TIMER works, I guess you can jump to the code below.. in summary, I expected it to send a 1ms pulse, then wait for 16ms; but my guess is that it's sending more than 1ms)
--
I'm trying to make a program to control an ESC. I want to output to the ESC to be a pulse of
1000 microseconds + [0 - 1000 microseconds based on the speed]
and then a delay of 16ms.
I simulated this in a loop() and it works.
Now I'm trying to do this using TIMER2 (8 bits). The general idea is:
- Put the timer in comparator mode
- Set the timer clock divider to 64, which means it will be incremented each 4us;
- Set the ESC PIN to HIGH and the comparator to 250 (ie, interrupt after 1ms)
- Set the comparator to the desired "speed" (0 for 0, 125 for 50%, 250 for 100%), which will wait between 0-1ms (still high)
- Set the ESC PIN to LOW, the clock divider to 1024 and set the comparator to 255, so it will wait ~16ms
- Go to 2
But this is not working; I don't have an oscilloscope, but my best hypothesis is that when the speed=0 it's sending a pulse longer than 1ms, otherwise the ESC should at least be arming, and it isn't.
void setup() {
pinMode(6, OUTPUT);
TCCR2A = 0;
TCCR2B = 0;
TIMSK2 = (TIMSK2 & B11111000) | B00000010;
TCCR2B = (TCCR2B & B11111000) | 0x04;
TCNT2 = 0;
OCR1A = 100;
}
int speed = 0;
void loop() {
delay(20);
return;
}
ISR(TIMER2_COMPA_vect) {
static int state = 0;
state++;
switch(state) {
case 1:
TCCR2B = (TCCR2B & B11111000) | 0x04; // 4us
digitalWrite(6, HIGH);
OCR2A = 250; // count to 250*4us = 1ms
break;
case 2:
OCR2A = speed / 4; // count up to 250*4us = 1ms
break;
case 3:
digitalWrite(6, LOW);
TCCR2B = (TCCR2B & B11111000) | 0x07; // 64us
OCR2A = 255; // count to 64*256us ~= 16ms
state = 0;
break;
}
TCNT2 = 0;
}