Hello,
This is my first post on this forum, maybe you will help me on that! Sorry for my english...
I did a software PMW using the 16bits timer1 to control 4 brushless motors, which works very well. Here is "a part" of the code I use:
volatile unsigned int servo[4] = {700, 700, 700, 700}; //Initial speed in microseconds volatile int8_t channel = 1; //1, 2, 3 or 4 : the motor id to control int main(void){ TCCR1B |= 1<<CS11; //Prescaler of 8 because 8MHz clock source TIMSK1 |= (1<<OCIE1A); //Interrupt on OCR1A DDRD |= 1<<DDD1 | 1<<DDD2 | 1<<DDD3 | 1<<DDD4; //motor's ESC as output PORTD = 1<<channel; //Set first servo pin high sei(); //Enable global interrupts while(1){ servo[0] = 1200; //Time that PMW signal need to be high (between 700 and 2300us) servo[1] = 1200; servo[2] = 1200; servo[3] = 1200; } } //PMW ISR ISR(TIMER1_COMPA_vect) { uint16_t timerValue = TCNT1; if(channel < 0){ //Every motors was pulsed, waiting for the next period if(timerValue >= usToTicks(20000)){ TCNT1 = 0; channel = 1; PORTD |= 1<<channel; OCR1A = servo[0]; } else{ OCR1A = usToTicks(20000); } } else{ if(channel < 4){ OCR1A = timerValue + servo[channel]; PORTD &= ~(1<<channel); //Clear actual motor pin PORTD |= 1<<(channel + 1); //Set the next one channel++; } else{ PORTD &= ~(1<<channel); //Clear the last motor pin OCR1A = usToTicks(20000); channel = -1; //Wait for the next period } } }
I also receive from a RC command a 50Hz PMW signal on my PCINT3 port. I calculated the time of the PMW signal with this code, which works well too :
int main(void){ PCICR |= 1<<PCIE0; //Enable interrupt of PCINT7:0 PCMSK0 |= 1<<PCINT3; //Enable PCINT3 } //PCINT interrupt ISR(PCINT0_vect, ISR_NOBLOCK){ uint16_t timerValue = TCNT1; uint8_t changedbits = PINB ^ portbhistory; portbhistory = PINB; //If interrupt is on PCINT3 if( (changedbits & (1 << PB3)) ) { //If PORTB3 is high, get the timerValue if(PINB & 1<<PORTB3){ previousThrottle = timerValue; } //If PORTB3 is low, calculate the time it was high else{ if(timerValue > previousThrottle){ throttle = ticksToUs(timerValue - previousThrottle); } else{ throttle = ticksToUs((usToTicks(20000) - previousThrottle) + timerValue); } } } }
Now here is my problem.
If I only use the PMW part of code, I can run my 4 motors very well, without any issue.
If I only use PCINT part of code, I can read the exact time my RC Command generates a high PMW signal.
BUT : if I use both part of code to read the RC signal and command my motor depending on the RC signal, then my motors act weirdly. 80% of time they run well, but sometime (like once every second) the motor accelerated to maximal speed, or completely stop for a few millisecond.
I conclude that I certainly miss a PMW interrupt and so the timing is not respected anymore... but I am not sure and dont really know how to solve it. Maybe you can see something in my code that is wrong that I don't see...
Thanks!