DRV8871 motor driver on an Arduino Uno
An Adafruit DRV8871 on pins 9 and 10 runs a 12 V motor through its table: forward with PWM, brake, reverse and coast. The whole build, an Arduino Uno and 3 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Beginner About 20 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $34. On Mokxi they're free.
What you'll learn
- The four states of an H-bridge: forward, reverse, coast, brake
- Speed control with PWM using
analogWrite - Separating logic ground from motor power
- Brake and coast are not the same
- Difficulty: Beginner
- Time: About 20 minutes
- Board: Arduino Uno R3
- Parts: 4
How it works
A DRV8871 is a motor driver with two inputs, IN1 on pin 9 and IN2 on pin 10. The Uno cannot run a 12 V motor directly, so these two pins only tell the driver what to do, and the battery on VM supplies the power.
The pair of inputs follows a table. IN1 high with IN2 low is forward. IN1 low with IN2 high is reverse. Both low lets the motor coast, and both high brakes it. Speed comes from PWM on one input while the other stays low.
The sketch runs forward in five steps of increasing speed, brakes for a second, reverses for 1.5 seconds, then coasts for 1.5 seconds, and repeats.
Parts list
4 parts, plus the jumper wires. They retail for about $34; on Mokxi they're free.
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| DRV8871 motor driver pin GND | Arduino Uno R3 pin GND |
| DRV8871 motor driver pin IN2 | Arduino Uno R3 pin 10 |
| DRV8871 motor driver pin IN1 | Arduino Uno R3 pin 9 |
| Battery: AA, coin cell, LiPo pin V- | Arduino Uno R3 pin GND |
| Battery: AA, coin cell, LiPo pin V+ | DRV8871 motor driver pin VM |
| DC motor pin 2 | DRV8871 motor driver pin OUT2 |
| DC motor pin 1 | DRV8871 motor driver pin OUT1 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// A 12 V motor on an Adafruit DRV8871 breakout, from an Uno.
//
// DRV8871 IN1 -> pin 9 IN2 -> pin 10 GND -> GND
// DRV8871 VM / GND terminal -> 12 V, OUT1 / OUT2 -> the motor
//
// The DRV8871 has no enable and no logic supply. Its table:
// IN1 high, IN2 low: forward IN1 low, IN2 high: reverse
// both low: coast both high: brake
// So speed is PWM on one input with the other low (drive, then coast).
const int IN1 = 9;
const int IN2 = 10;
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
Serial.begin(9600);
Serial.println("Mokxi Uno: DRV8871 forward, brake, reverse, coast");
}
void loop() {
Serial.println("forward, speeding up");
digitalWrite(IN2, LOW);
for (int s = 0; s <= 255; s += 51) {
analogWrite(IN1, s);
delay(300);
}
Serial.println("brake");
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
delay(1000);
Serial.println("reverse");
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
delay(1500);
Serial.println("coast");
digitalWrite(IN2, LOW);
delay(1500);
}
Code walkthrough
The key functions of the sketch, and what each one does.
setup sketch.ino
Makes pins 9 and 10 outputs and starts the serial port. The DRV8871 has no enable pin and no logic supply, so there is nothing else to set up.
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
Serial.begin(9600);
Serial.println("Mokxi Uno: DRV8871 forward, brake, reverse, coast");
}loop sketch.ino
Walks through the table. A for loop raises analogWrite on IN1 from 0 to 255 in steps of 51 every 300 ms with IN2 low. Then it sets both pins HIGH to brake, IN1 LOW and IN2 HIGH to reverse, and both LOW to coast.
void loop() {
Serial.println("forward, speeding up");
digitalWrite(IN2, LOW);
for (int s = 0; s <= 255; s += 51) {
analogWrite(IN1, s);
delay(300);
}
Serial.println("brake");
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
delay(1000);
Serial.println("reverse");
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
delay(1500);
Serial.println("coast");
digitalWrite(IN2, LOW);
delay(1500);
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The motor never moves This project
Check that the battery is on VM and its negative joins the Uno GND and the driver GND. - It runs backward This project
Swap the two motor wires on OUT1 and OUT2. - The motor does not run or runs one way only. DRV8871 motor driver
Send PWM to IN1 for one direction and IN2 for the other, with the other input LOW. Both LOW lets the motor coast, and both HIGH brakes it. - The driver overheats, or the supply sags and resets the board. DRV8871 motor driver
Add a bulk capacitor (100 uF or more) near VM, share ground with the logic board, and set the current limit resistor on ILIM for your motor. VM can be 6.5 V to 45 V. - The motor does not spin, or the pin gets hot or the board resets when it is wired straight to a GPIO pin. DC motor
A pin gives about 20 mA and a motor needs far more. Drive it through a transistor or motor driver, with its own supply and a shared ground. - The transistor or pin is damaged by spikes when the motor stops. DC motor
Put a flyback diode across the motor, cathode to the positive side. A motor is a coil and kicks back voltage when switched off. Add a 0.1 uF capacitor across the motor terminals to cut noise. - The battery is wired backwards, or the voltage is too low or too high for the circuit. A fresh AA is about 1.5 V, a LiPo is 3.7 V nominal and 4.2 V full. Battery: AA
Match the plus and minus marks. Check the voltage your parts need. Two AAs make 3 V, four make 6 V. Never feed a LiPo to a 3.3 V chip directly at 4.2 V. - The circuit resets or browns out when a motor or servo starts. A battery has internal resistance, so the voltage sags under load. Battery: AA
Use a fresh pack with enough current rating. Add a 100 uF or larger capacitor near the load. Power motors from their own pack and join the grounds.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.