Making it move, and reading it when it does not · 08 of 11

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

AIN1AIN2AOUT1AOUT2What the motor does
00offoffCoast
01LHReverse
10HLForward
11LLBrake

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.

Two pins, four states, two ways to PWM
PWM / LOW
What the channel is doing
Speed (share of each period spent driving)60%
AIN1
PWM 60%
AIN2
LOW
Between pulses
coast
Fast decay: PWM on AIN1, AIN2 held low. Forward while AIN1 is high, coast in the gaps. For reverse, swap which pin carries the PWM.

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

drv8833_speed.ino

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

The motor hums but does not turn at low duty cycles

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.

Setting the speed to zero does not stop it quickly

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.

Slow decay runs the motor backwards from what I expected

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.

Where this goes next

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

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

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.

Browse Modules and blocks on the forum