Hi, i've built a micro quadcopter drone and i'm trying to make it run smoother with timer interrupts. I'm using RemoteXY lib to communicate with HM-10 module. I2C devlibs is used for MPU6050 communication.
I need help with combining timer interrupt (ISR) and faster PWM frequency on pins 3, 9, 10 and 11.
I figured out that my brushed DC motors work very good when timer 1 and timer 2 are setup for 31.4 kHz PWM frequency. I found instructions here https://nerdytechy.com/how-to-change-the-pwm-frequency-of-arduino/
When i uncomment interrupt code, UART communication stopps working properly. I recon i'm doing something wrong. Interrupt this short shouldn't completely mess up the UART, would it?
Code from the setup:
ISR(TIMER1_COMPA_vect) {
pidCompute = 1;
}
/////
void setup() {
RemoteXY_Init();
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// Setup motor PWM frequency setup to 31.4 kHz
TCCR1A = 0b00000001; // Pins D9, D10 to 8bit
TCCR1B = 0b00000001; // x1 phase correct
TCCR2B = 0b00000001; // Pins D3, D11 to 8bit
TCCR2A = 0b00000001; // 1x phase correct
// Motor pins setup to output
DDRD |= B00001000;
DDRB |= B00001110;
// commented out TCCR1A = 0; // set entire TCCR1A register to 0
// commented out TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 2499; // Set compare match register for 10 ms interrupt interval
// turn on CTC mode (Clear Timer on Compare Match)
TCCR1B |= (1 << WGM12);
// Set CS11 and CS10 bits for 64 prescaler
TCCR1B |= (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
Thank you for your feedback guys. So it's best that i don't use interrupts in this case and simply rely on the millis() or micros() functions.
Just to be sure that i understand this correctly. Upper code that sets up the PWM frequency sets up TCCRAx register to 8-bit phase correct WGM setting and TCCRBx register to "no prescaling" setting.
That gives us desired PWM output, which is probably calculated like this:
16 MHz / 2^n, where n would be the number of bits.
Does this mean that this code actually gives us 65,5 kHz PWM and not 31.25 kHz?
Whouldn't 9 bit phase correct setting give us around 31 kHz?
16 MHz / 2^9 = 31.25
The low-order bit of TCCR1A is "WGM10". Setting only that bit sets Timer1 to Waveform Generation Mode 1: PWM, Phase Correct, 8-bit.
The frequency formula for a phase-correct PWM mode is 16 MHz / (2 * prescale * TOP). For 8-bit PWM, TOP is 255. Your prescale is 1 so 31372.55 Hz.
If you want 62 kHz you could switch to a Fast PWM mode (like Mode 5). The frequency formula for that is 16 MHz / (prescale * (TOP+1)). TOP is still 255 and prescale is still 1 so 62500 Hz.
That would be:
If you use one of the TImer0 compare interrupts (without actually changing anything else about timer0), you'd get the ISR called every 1024us (it doesn't matter what the compare value is set to, since timer0 is set to wrap around continuously, generating the interrupt that millis() uses on overflow. but if you set the the compare register to 128, it would occur mid-way between the millis() interrupts.)
Thank you for suggestions, much appreciated.
Now i have a weird problem. I think that i've accidentally turned on a timer interrupt that i'm unaware of. Arduino keeps rebooting midway setup.
Is there a way to force set default values to all interrupt and timer registers? I'm not sure about default values of these registers. Thank you in advance
I think i figured it out. Now the system is stable again. Before that, nomatter what i uploaded, UART didn't work as it should have. I figured that it's probably an interrupt kicking in and interrupting the timing.