Quadcopter: problems using VirtualWire library and analogWrite

Hello everybody,
I'm trying to build a quadcopter based on Arduino Pro Mini with atmega328p using the popular RF module based on VirtualWire library. For this project I need to control 4 motors by 4 PWM pins.

I have 2 problems:

  • Searching on Google and Arduino forum I found that VirtualWire library uses a Timer, hindering the correct use of pins 9 and 10 with analogWrite function, because the same timer is used to set the PWM on these two pins.
  • PWM on pins 5 and 6 uses a frequency which is greater than the one used in other pins. This seems to make the motors on these pins go slower somehow.
    Which solution would you suggest?

I could control the four motors by pins 3, 5, 6, 11 but first I should make pins 5 and 6 work at the same frequency of other pins. Searching on Google it doesn't seem possible, is it?
Otherwise I could hack the VirtualWire library to use the timer needed for PWM on pins 5 and 6, instead of the one needed for pin 9 and 10, so i could use them for controlling motors. Is it possible without compromising the VirtualWire library operations?

Thanks a lot to whoever will give me any good suggestion :slight_smile:

Timer0 controls Pins 5 and 6.
Timer1 controls Pins 9 and 10.
Timer2 controls Pins 3 and 11.

All of the timers use the same pre-scale (64) but Timer0 uses Fast PWM (Mode 3) and the other two timers use Phase-Correct PWM (Mode 1) so they run at half the speed. Timer0 is also used with the millis() timer so you shouldn't mess with it. You can change Timer2 to use Fast PWM (Mode 3) to have it run at the same rate as Timer0. Do that by setting the WGM21 bit of TCCR2A:

sbi(TCCR2A, WGM21);  // Change from Phase-Correct PWM to Fast PWM

Thank you, now I really understand what is the problem.
I have a question: do you think is possible for the VirtualWire procedures to get time from millis() function instead of TImer1? Of course performance would be way less efficient, but is it technically possible to do this?

Tricka90:
do you think is possible for the VirtualWire procedures to get time from millis() function instead of TImer1?

I would guess 'no'.

Thank you.
Can I ask you what are the main reasons I won't be able to do it?

Tricka90:
Can I ask you what are the main reasons I won't be able to do it?

  1. Timer1 is a 16-bit timer. Timer0 and Timer2 are 8-bit timers
  2. You can't change Timer0 to generate the necessary interrupts without totally screwing over the millis() clock.
    VirtualWire uses timer interrupts so it can do sending and receiving in the background.
    Maybe you should add a second Arduino to act as the radio and have that communicate with your flight controller over SPI or I2C. Or you could use an Arduino Mega which has more timers and PWM pins.