Controlling the MOSFET Motor Driver

Microcontrollers by themselves don’t have enough power to drive most DC motors.  However, true to their name, they are good at controlling other components to do their heavy work.

In the case of the motor driver, the microcontroller essentially tells it which direction to go and at what speed all at lower logic-level voltages (0V to 5V).  The motor driver then takes these signals and translates them into higher voltage and current to the motor.  In the truest sense, motor drivers are like switches.  The microcontroller only needs enough power to flip the switch.

The H-Bridge Truth Table

The high power MOSFET motor driver that I use in my DIY segway project uses the following signals from the Atmega328P to drive the motors with 12V to 24V:

Pin A Pin B Result
HIGH LOW Rotate one direction
LOW HIGH Rotate the other direction
LOW LOW Coast
HIGH HIGH Electronic Braking

So essentially, two pins control the direction and braking/coasting of the motor. A third pin controls the motor speed by Pulse Width Modulation (PWM).

AVR Source Code for Driving the H-Bridge

Here are some code samples used to test the operation of the motor driver. The full AVR source code and MAKEFILE can be downloaded at the end of this post.

The PWM frequency is set to 15.625 Khz to minimize the motor whine that can be detected at lower frequencies.
void motorInit() {
// Set the pins to output.
set_output(DDRB, PB0); // Left
set_output(DDRB, PB3); // Right
set_output(DDRB, PB1); // Enable (PWM)
// Set Timer 1 to 15.625 Khz
TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10);
TCCR1B |= (1 << WGM12) | (1 << CS10);
}

The following are the functions described in the truth table above:
void motor_forward() {
output_low(PORTB, PB3);
output_high(PORTB, PB0);
}

void motor_reverse() {
output_low(PORTB, PB0);
output_high(PORTB, PB3);
}

void motor_coast() {
output_low(PORTB, PB0);
output_low(PORTB, PB3);
}

void motor_brake() {
output_high(PORTB, PB0);
output_high(PORTB, PB3);
}

And finally, this function sets the speed using a number between 9 and 1023, where 512 would be 50% speed and 1023 would be 100% speed.

void setSpeed(int speed)
{
OCR1A = speed;
}

Arduino Hookup and Testing Code

There are 5 connections needed in order to test this motor driver with an Arduino (8 if you want to connect 2 motors.

Arduino Motor Driver
5V +5V
GND GND
Digital 8 1A
Digital 11 1B
Digital 9 ENABLE1
There are 8 total connections needed for this driver (Other than the power source and motor leads).  Each motor is controlled by 2 direction pins (1A & 1B or 2A & 2B) and 1 PWM speed pin (ENABLE).
There are 8 total connections needed for this driver (Other than the power source and motor leads). Each motor is controlled by 2 direction pins (1A & 1B or 2A & 2B) and 1 PWM speed pin (ENABLE).

Here is the Arduino code.  Also available for download at the end of this article:

/*
Motor Test for High Power MOSFET Motor Driver.
Connections (1 motor test):
Arduino -> Driver
Digital 8 -> 1A
Digital 11 -> 1B
Digital 9 -> ENABLE1
*/
int i;
int dir_1A = 8; //PB0
int dir_1B = 11; //PB3
int enable_1 = 9; //PB1
void setup()
{
pinMode(dir_1A, OUTPUT);
pinMode(dir_1B, OUTPUT);
pinMode(enable_1, OUTPUT);
// Set Timer 1 to 15.625 Khz to keep frequency out of audible range.
TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10);
TCCR1B |= (1 << WGM12) | (1 << CS10);
}
void loop()
{
// Forward Test
motor_forward();
for(i=512;i<1023;i++) { setSpeed(i); delay(10); } delay(2000); for(i=1023;i>512;i--)
{
setSpeed(i);
delay(10);
}
motor_coast();
delay(6000);
// Reverse Test
motor_reverse();
for(i=512;i<1023;i++) { setSpeed(i); delay(10); } delay(2000); for(i=1023;i>512;i--)
{
setSpeed(i);
delay(10);
}
motor_coast();
delay(8000);
}
void setSpeed(int speed)
{
OCR1A = speed;
}
void motor_forward() {
digitalWrite(dir_1B, LOW);
digitalWrite(dir_1A, HIGH);
}
void motor_reverse() {
digitalWrite(dir_1A, LOW);
digitalWrite(dir_1B, HIGH);
}
void motor_coast() {
digitalWrite(dir_1A, LOW);
digitalWrite(dir_1B, LOW);
}
void motor_brake() {
digitalWrite(dir_1A, HIGH);
digitalWrite(dir_1B, HIGH);
}

For more discussion on motor drivers, feel free to join the forums or comment below.

Thanks, and happy building!

Comments are closed, but trackbacks and pingbacks are open.