The four states
Each channel reads its two inputs as a pair. Both low coasts, both high brakes, one high turns the motor — and PWM goes on with the other input held low or held high, which are two different ways to drive and both are available on this board.
Two inputs, read as a pair
| AIN1 | AIN2 | AOUT1 | AOUT2 | What the motor does |
|---|---|---|---|---|
| 0 | 0 | off | off | Coast |
| 0 | 1 | L | H | Reverse |
| 1 | 0 | H | L | Forward |
| 1 | 1 | L | L | Brake |
Both low is coast. All four switches are off, the two outputs float, and the motor freewheels down under its own friction.
Both high is brake. The two low-side switches are on, the winding is shorted through them, and a motor still spinning drives current round that loop against itself, which stops it fast.
One high and one low turns the motor, and which of the two is high decides the direction. The same table holds for BIN1, BIN2, BOUT1 and BOUT2.
Two ways to put PWM on it
A PWM'd channel spends part of each period driving and the rest in one of the two stopped states. Which one is the choice of decay mode.
Fast decay: PWM on AIN1, AIN2 held low. Between pulses both inputs are low,
so the channel coasts, and the motor's current dies away quickly through the
switches' built-in diodes. This is what analogWrite(AIN1, speed) with AIN2 low
does, and it is what most examples do.
Slow decay: AIN1 held high, PWM on AIN2. Between drive pulses both inputs are
high, so the channel brakes, and the current circulates through the shorted
winding and dies away slowly. The motor is driven while AIN2 is low, so the
duty cycle is inverted: analogWrite(AIN2, 255 - speed) for forward.
Both work on this board. The 0 Ω sense resistors switch off the chip's own current regulation; they do not remove either decay mode. Slow decay usually gives speed that follows duty cycle more evenly at the low end, and fast decay lets the motor freewheel between pulses. The sketch above uses fast decay.
Stopping is a choice
A motor commanded to zero in fast decay coasts. A motor commanded to brake stops much faster, and the current it generates flows through the driver while it does. Braking a heavy load hard from speed is a way to find the 2 to 3.3 A overcurrent trip.
Neither holds a position. Braking resists a turn; it does not hold a shaft still against a load. For that you want the stepper article.
The code
Ramps Motor A up in one direction, coasts, ramps up in the other, then brakes. One function takes a signed speed and decides which pin gets the duty cycle; the other pin is held low, so this is fast decay.
// DRV8833 wiring for this sketch (ESP32-S3).
//
// GND -> GND common with the motor supply's ground
// VM -> 2.7-10.8 V motor supply. There is no logic supply pin.
// SLP -> GPIO 4 high to run; pulled low in the chip, so not optional
// AIN1 -> GPIO 5 channel A
// AIN2 -> GPIO 6 channel A
// Motor A across AOUT1 and AOUT2.
//
// Arduino IDE, Tools menu (esp32 core 3.x):
// Board ESP32S3 Dev Module
// USB CDC On Boot Enabled (Disabled if your USB goes through a
// USB-serial chip)
// Flash Size 16MB (128Mb)
// PSRAM OPI PSRAM
// No library needed.
//
// AIN1 and AIN2 are only ever written with analogWrite: 0 for LOW, 255 for
// HIGH. On esp32 core 3.x, digitalWrite on a pin analogWrite has taken is
// refused. On an Uno the same calls are plain LOW and HIGH.
const int SLP = 4;
const int AIN1 = 5;
const int AIN2 = 6;
// speed is -255..255. The sign picks which pin carries the duty cycle and
// the other is held low, so between pulses the channel coasts: fast decay.
void driveA(int speed) {
if (speed >= 0) {
analogWrite(AIN2, 0);
analogWrite(AIN1, speed);
} else {
analogWrite(AIN1, 0);
analogWrite(AIN2, -speed);
}
}
// Both high: both low-side switches on, the winding shorted.
void brakeA() {
analogWrite(AIN1, 255);
analogWrite(AIN2, 255);
}
void setup() {
pinMode(SLP, OUTPUT);
driveA(0);
digitalWrite(SLP, HIGH);
delay(1); // up to 1 ms to wake
}
void loop() {
for (int s = 0; s <= 255; s += 5) { driveA(s); delay(20); }
driveA(0); // coast, not brake
delay(1000);
for (int s = 0; s >= -255; s -= 5) { driveA(s); delay(20); }
brakeA();
delay(1000);
}The motor pins are only ever written with analogWrite: 0 is LOW and 255 is HIGH. On esp32 core 3.x a digitalWrite on a pin analogWrite has taken is refused, so a brake written with digitalWrite would leave the pin still pulsing. analogWrite uses the core's default PWM frequency, which is fine for a DC motor. Nothing here limits current; the duty cycle only switches it.
When it does not work
Below the duty cycle that produces enough torque to overcome static friction, the motor buzzes at the PWM frequency and stays put. Find that floor for your motor and start ramps above it rather than from zero.
With the other input held low, a duty cycle of zero is coast: all four switches off, and the motor winds down under its own friction. To stop it, drive both inputs high, which turns on both low-side switches and shorts the winding.
With AIN1 held high and PWM on AIN2, the motor is driven while AIN2 is low and braked while it is high, so the duty cycle is inverted. For forward at speed s, write analogWrite(AIN2, 255 - s). A duty of 255 on AIN2 is brake, not full speed.
Overcurrent does not latch the driver off. It holds FLT low for 1.35 ms, retries, and carries on as if nothing happened, which a slow loop never sees.
Reading the fault pin →Edit this page — content/books/drv8833/the-four-states.mdx
Questions about this product
See what other owners have asked, and read their solutions.
DRV8833 Dual Motor Driver
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.