Motor Speed Control Hook

Aeroquad comes preconfigured with a variety of different motor controller libraries.  The latest version at the time of writing contains a library that takes advantage of the Uno’s ATMega 328p onboard Fast PWM mode to send signals to each electronic speed controller (ESC).  Unfortunately after much trial and error, we determined that our configuration did not allow our quadcopter to use this efficient PWM control, requiring us to write a new motor controller library using Arduino’s Servo.h API.

ATMega 328p Timers & PWM

Aeroquad’s motor controller library efficiently uses the Fast PWM.  The ATMega 328p has 3 timers: timer0, timer1, and timer 2.  Rather than using a software PWM, timer1 and timer2 can be used to control all four motors.  This section will briefly explain how Aeroquad’s Fast PWM control works.

First, each pin connected to an ESC must be set to output mode. This is done by either using the pinMode() function in Arduino or by modifying the DDRB and DDRD registers as shown below:

    DDRB = DDRB | B00001110;                                  // Set ports to output PB1-3
    DDRD = DDRD | B00001000;                                  // Set port to output PD3

The AVR pins are labelled PB0-PB7 (Arduino Pins 0-7) and PD0-PD5 (Arduino Pins 8-13).

Next, timer prescalers must be adjust so that the timers count at a manageable rate for PWM. Aeroquad initializes these timers using the code shown below:

// Init PWM Timer 1  16 bit
    TCCR1A = (1<

TCCR1A and TCCR1B are register that can be set according to how timer 1 should function. This configuration causes the timer to use Fast PWM mode and sets a prescaler of 8, meaning that the timer counts up once every 8 ticks of the clock. Timer 1 is also a 16 bit timer, meaning that it can count up to a maximum of 2^16 – 1. This value, however, is set lower by modifying the ICR1 register.

Similarly, timer 2 is also set to Fast PWM mode. Since it is only an 8-bit timer, it has a maximum value of 255 and, therefore, must count much up much slower. Therefore, timer 2’s prescaler is set to 256. For more details, read the ATMega328 data sheet.

To adjust the PWM frequency using the timers, additional registers must be set. Fast PWM works by setting the pin output to HIGH when the timer begins/overflows at 0 and LOW when it reaches a value set by the OCR registers. This graph demonstrates how this works over time to create a PWM signal.

Fast PWM. Credit: http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html

This code shows how AeroQuad sets the OCR registers. Each register corresponds to one of the PWM pins on the Arduino board.

void commandAllMotors(int command) {
    OCR2B = command / 16 ;
    OCR1A = command * 2 ;
    OCR1B = command * 2 ;
    OCR2A = command / 16 ;
}
Arduino Pins for each timer
Timer output	Arduino output	AVR Chip pin	Pin name
OC0A		6		12		PD6
OC0B		5		11		PD5
OC1A		9		15		PB1
OC1B		10		16		PB2
OC2A		11		17		PB3
OC2B		3		5		PD3

For a more in depth explanation of Fast PWM and how to configure it on the Arduino Uno’s AT Mega 328p processor, read Ken Shirriff’s blog post on Arduino PWM and skim through sections about each timer in the ATMega328 data sheet.

Radio and Fast PWM Conflict

Although much less efficient than using Fast PWM, we needed to use a software generated PWM to control the ESCs.  Unfortunately, the nRF24l01 Wireless Radio used for our copter control requires SPI to communicate with the board, which meant the MOSI pin number 11 was taken.  Since pin 11 is one of the six fast PWM pins available on the Uno, that leaves only fast PWM pins 3, 5, 6, 9, 10 available. Therefore at least one of pins 5 and 6 must be used to accomodate four motors.  This is problematic since the ATMega328 timer0 handles pins 5 and 6, but timer0 is also used for Arduino delay() and millis() functions and Serial communication.  By changing the prescaler of timer0 to slow down the Hertz for fast PWM, serial communication and timing functions used in the Aeroquad software malfunction.

This problem could easily be avoided by using a different Arduino board such as the Seeeduino Mega available in the lab, which has more than three timers.  However, the prototyping shield was already designed to attach to an Arduino Uno.

 Software PWM Aeroquad Hook

An easy work around to enable other pins for PWM and motor control is to write a software PWM.  From previous projects, we knew that the Arduino Servo library controls some ESCs and brushless motors very well.  Hence, a motor control library using the Servo library replaced the fast PWM motor controller in our software.  This new motor control hook turned out to be quite trivial.  The code for this software hook is shown below.

/*
  Motors_Servo.h
  AeroQuad motor control using the Arduino Servo library.

  Author: Garrett Owen
 */

#ifndef _AEROQUAD_MOTORS_SERVO_H_
#define _AEROQUAD_MOTORS_SERVO_H_

#include "Arduino.h"
#include "Motors.h"
#include "Servo.h"

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

void initializeMotors(NB_Motors numbers) {
	numberOfMotors = numbers;

	motor1.attach(3);
	motor2.attach(5);
	motor3.attach(6);
	motor4.attach(10);

	commandAllMotors(1000);  // Initialise motors to 1000us (stopped)
}

void writeMotors() {
	motor1.writeMicroseconds(motorCommand[MOTOR1]);
	motor2.writeMicroseconds(motorCommand[MOTOR2]);
	motor3.writeMicroseconds(motorCommand[MOTOR3]);
	motor4.writeMicroseconds(motorCommand[MOTOR4]);
}

void commandAllMotors(int command) {
	motor1.writeMicroseconds(command);
	motor2.writeMicroseconds(command);
	motor3.writeMicroseconds(command);
	motor4.writeMicroseconds(command);
}

#endif

The basic structure of this library implements the Aeroquad Motors.h prototyped functions. The initializeMotors() function is run at startup, and writeMotors() is used to issue commands to each individual motor. Motor commands are stored in a global array called motorCommand[], which is modified by other AeroQuad libraries.

Since Aeroquad uses a minimum PWM signal of 1000 microseconds and a maximum of 2000 microseconds, the ESCs needed to be re-calibrated to these values. For instructions on how to do this, visit the ESC calibration page.

5 thoughts on “Motor Speed Control Hook

  1. hello guys,
    I need your help, I’m working at a project with an octocopter that use parts from Aeroquad. What I have to do is to modify the source code in such way that if a motor fail the octocopter will be able to stay in air without falling or rolling. What file from the source code I have to modify? I’m kind of new in this Aeroquad software and everything, maybe you can help me.

    Thank you

    • Hi Victor,
      It depends on what kind of Microcontroller you are using (for how to control timers). For Aeroquad the speed of the PWM signal sent to the electronic speed controllers is managed in Libraries/AQ_Motors/Motors_PWM_Timer.h for newer configurations.

      However, you will probably want to modify the Libraries/AQ_FlightControlProcessor/FlightControlOctoX.h file to account for a motor loss. This sounds like a pretty difficult task. You’ll need to find a way to detect a motor failure, and then modify the flight processor calculations to account for the motor failure. The math behind that is beyond me, but try asking in the forums at aeroquad.com. Good luck!

  2. hi i am using Speed Controller for Brushless Motor for my quad copter the problem is 3 of them are starting at 60 % and one at 80 % and you know that it must start in the exact time and with the exact speed i need your help in that . thanks.

  3. Hello guys!
    I have a BLDC motor equiped with an ESC. There is also an arduino Atmega 328 which I use to generate the pwm signal. I need to feed the ESC with a pwm of a 50 Hz frequency. I don’t know how could I set the exactly 50 Hz frequency. Any ideas? I was searching for two days and…nothing.

Comments are closed.