ESP32 MicroPython DRV8833 DC Motor Driver

This tutorial instructs you how to use the DRV8833 motor driver with the ESP32 and MicroPython. In detail, we will learn:

ESP32 MicroPython and DRV8833 DC motor driver

Hardware Preparation

1×38-pin ESP32 ESP-WROOM-32 Dev Module - Narrow
1×Alternatively, 38-pin ESP32 ESP-WROOM-32 Dev Module - Wide
1×Alternatively, 30-pin ESP32 ESP-WROOM-32 Dev Module - Wide
1×Alternatively, ESP32 Uno-form board
1×Alternatively, ESP32 S3 Uno-form board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×DRV8833 Motor Driver Module
2×5V DC Motor
1×5V Power Adapter
1×DC Power Jack
1×Breadboard
1×Jumper Wires
1×Recommended: Screw Terminal Expansion Board for ESP32
1×Recommended: Breakout Expansion Board for ESP32
1×Recommended: Power Splitter for ESP32

Or you can buy the following kits:

1×DIYables ESP32 Starter Kit (ESP32 included)
1×DIYables ESP32 S3 Starter Kit (ESP32 S3 included)
1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

For Part 1 you need only one motor. The second motor is for Part 2.

Overview of DRV8833 Motor Driver

A GPIO pin of the ESP32 gives only a few milliamps at 3.3 volts. A DC motor wants hundreds of milliamps, and it also wants the current to flip when you change direction. The DRV8833 does this job for you. It is a small chip from Texas Instruments with two H-bridges inside, so one module can run two brushed DC motors on its own (or one bipolar stepper motor, but that is not part of this guide).

Why pick it for an ESP32 project? Its outputs are MOSFETs with a low resistance (about 360 mΩ for the high side and low side together). Much less power turns into heat, and the motor gets almost the full battery voltage. This makes it a good fit for small robots that run on 3 volts to 9 volts batteries. The chip makes its own logic voltage inside, so the 3.3 volts signals from the ESP32 work directly. You do not need a level shifter or a second supply.

Item DRV8833 value
Motor supply (VCC pin) 2.7V to 10.8V
Number of channels 2 (motor A and motor B)
Current per channel about 1.5A RMS, 2A peak (with good cooling)
Two channels joined together about 3A (optional)
Control logic 3.3V and 5V both work
PWM frequency up to 50 kHz
Protection under-voltage lockout, over-current, thermal shutdown

The DRV8833 has no ENA/ENB pins like the L298N. To set the speed, you send PWM straight into the IN pins. Because of this, both IN pins of a channel must be on PWM-capable GPIOs. Nearly every output GPIO of the ESP32 can do PWM, so this is easy.

Pinout

DRV8833 motor driver module pinout

The pin labels are not the same on every board. Some modules print AIN1/AIN2/BIN1/BIN2, AOUT1/AOUT2/BOUT1/BOUT2, SLP and FLT instead of the names below. The job of each pin is the same.

  • IN1 and IN2 pins: control motor A. Connect to two PWM GPIO pins of the ESP32.
  • IN3 and IN4 pins: control motor B. Connect to two more PWM GPIO pins of the ESP32.
  • OUT1 and OUT2 pins: connect to the two wires of motor A.
  • OUT3 and OUT4 pins: connect to the two wires of motor B.
  • VCC pin: connect to the motor power supply (2.7 volts to 10.8 volts). It is not a logic supply pin.
  • GND pin: connect to GND (0 volts) of the motor supply AND to GND of the ESP32.
  • EEP pin (sleep, also called nSLEEP or SLP): connect to 3.3 volts of the ESP32 to keep the driver awake. If it is LOW, the chip sleeps and the motors do nothing.
  • ULT pin (fault, also called nFAULT or FLT): goes LOW when the chip finds a problem, such as overheating or too much current. You can leave it unconnected.

How the IN Pins Control a Motor

Each channel looks at its two IN pins. The table is for motor A. Motor B works the same way with IN3 and IN4.

IN1 IN2 What motor A does
LOW LOW Coast - the power is cut and the motor rolls slowly to a stop
PWM (or HIGH) LOW Forward - higher duty means faster
LOW PWM (or HIGH) Reverse - higher duty means faster
HIGH HIGH Brake - the motor stops quickly

In MicroPython, duty_u16() takes a value from 0 to 65535. So duty_u16(65535) means HIGH, duty_u16(0) means LOW, and a value in between sets the speed. The code in this tutorial uses a percent from -100 to 100 instead. A plus sign means forward, a minus sign means reverse, and the code turns the percent into a duty value for you.

Power rules to remember:

  • The motors take power from an external supply, such as a 5 volts adapter through a DC power jack, or a 4 x AA battery pack (about 6 volts). Never take motor power from the 3.3V or 5V pin of the ESP32.
  • The GND of the supply, the GND of the DRV8833 and the GND of the ESP32 must all be connected together. Without a common ground, the IN signals have no reference and the motor acts strangely.

Part 1 - Control One DC Motor with ESP32 MicroPython

We start with only motor A on channel A. Channel B stays empty for now.

Wiring Diagram

  • Option 1: wire the ESP32 to the DRV8833 directly with jumper wires
The wiring diagram between ESP32 MicroPython DRV8833 one DC motor

This image is created using Fritzing. Click to enlarge image

The wiring diagram between ESP32 MicroPython DRV8833 one DC motor screw terminal block

This image is created using Fritzing. Click to enlarge image

DRV8833 Pin Connect To
IN1 ESP32 GPIO27
IN2 ESP32 GPIO26
EEP ESP32 3.3V
GND ESP32 GND and 5V adapter − (through the DC power jack)
VCC 5V adapter + (through the DC power jack)
OUT1 Motor A wire 1
OUT2 Motor A wire 2
ULT not connected

If the motor turns the wrong way, swap the two motor wires on OUT1 and OUT2. You do not need to change the code.

ESP32 MicroPython Code - One DC Motor

No library is needed. The script uses machine.PWM, which is part of MicroPython. GPIO27 and GPIO26 both become 1 kHz PWM outputs. The motor_a() function takes a speed from -100 to 100 and sets the two IN pins as shown in the table above. The motor_a_brake() function sets both pins HIGH.

Each loop goes like this: the motor speeds up forward in 20% steps, runs at full speed for 2 seconds, coasts for 2 seconds, turns in reverse at 60% for 2 seconds, and then brakes hard. Every step is printed to the Shell.

""" This ESP32 MicroPython code was developed by newbiely.com This ESP32 MicroPython code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/esp32-micropython/esp32-micropython-drv8833-dc-motor-driver """ from machine import Pin, PWM import time # ESP32 pins connected to channel A of the DRV8833 module IN1_PIN = 27 # ESP32 GPIO27 connected to the IN1 pin of the DRV8833 IN2_PIN = 26 # ESP32 GPIO26 connected to the IN2 pin of the DRV8833 PWM_FREQ = 1000 # 1 kHz PWM, the DRV8833 accepts up to 50 kHz # Both IN pins use PWM, because the DRV8833 has no separate speed (enable) pin in1 = PWM(Pin(IN1_PIN), freq=PWM_FREQ) in2 = PWM(Pin(IN2_PIN), freq=PWM_FREQ) in1.duty_u16(0) # start with the motor stopped (coast) in2.duty_u16(0) FULL_DUTY = 65535 # duty_u16() range is 0 to 65535 def percent_to_duty(percent): return percent * FULL_DUTY // 100 # convert 0-100% to 0-65535 def motor_a(speed): # speed: -100 to 100 (%). Positive = forward, negative = reverse, 0 = coast speed = max(-100, min(100, speed)) if speed > 0: in1.duty_u16(percent_to_duty(speed)) # PWM on IN1 in2.duty_u16(0) # IN2 LOW elif speed < 0: in1.duty_u16(0) # IN1 LOW in2.duty_u16(percent_to_duty(-speed)) # PWM on IN2 else: in1.duty_u16(0) # IN1 LOW + IN2 LOW = coast (motor rolls to a stop) in2.duty_u16(0) def motor_a_brake(): in1.duty_u16(FULL_DUTY) # IN1 HIGH + IN2 HIGH = brake (fast stop) in2.duty_u16(FULL_DUTY) while True: # forward: raise the speed step by step print("Forward: speeding up") for speed in range(20, 101, 20): motor_a(speed) print(" speed = {}%".format(speed)) time.sleep(0.5) print("Forward: full speed for 2 seconds") time.sleep(2) print("Coast: motor rolls to a stop") motor_a(0) time.sleep(2) print("Reverse: 60% speed for 2 seconds") motor_a(-60) time.sleep(2) print("Brake: fast stop") motor_a_brake() time.sleep(1) motor_a(0) # release the brake before the next loop print("----") time.sleep(1)

Detailed Instructions

Here's instructions on how to set up and run your MicroPython code on the ESP32 using Thonny IDE:

  • Make sure Thonny IDE is installed on your computer.
  • Confirm that MicroPython firmware is loaded on your ESP32 board.
  • New to MicroPython on the ESP32? Read the ESP32 MicroPython Getting Started guide first.
  • Wire the ESP32, the DRV8833 module, the motor and the DC power jack as shown in the diagram. Keep the 5V adapter unplugged for now.
  • Connect the ESP32 board to your computer with a USB cable.
  • Open Thonny IDE on your computer.
  • In Thonny, go to Tools Options, open the Interpreter tab, and choose MicroPython (ESP32) from the dropdown.
  • Copy the provided MicroPython code and paste it into Thonny's editor.
  • Save the code to your ESP32 by:
    • Clicking the Save button or pressing Ctrl+S.
    • Choosing MicroPython device in the save dialog.
    • Typing main.py as the file name.
  • Plug the 5V adapter into the DC power jack.
  • Click the green Run button (or press F5) to execute the script.
  • Watch the motor. You can feel the difference between coast and brake: after coast the shaft keeps turning for a moment, after brake it stops almost at once.
  • Check out the message in the Shell at the bottom of Thonny.
Shell x
>>> %Run -c $EDITOR_CONTENT
MPY: soft reboot Forward: speeding up speed = 20% speed = 40% speed = 60% speed = 80% speed = 100% Forward: full speed for 2 seconds Coast: motor rolls to a stop Reverse: 60% speed for 2 seconds Brake: fast stop ---- Forward: speeding up speed = 20% speed = 40%
MicroPython (ESP32) • CP2102 USB To UART Bridge Controller @ COM12 ≡

A small motor may not move at 20%. That is normal: the duty is too low to beat the friction inside the motor. It starts to turn once the duty goes a bit higher.

Part 2 - Control Two DC Motors with ESP32 MicroPython

Now we use channel B too. Think of motor A as the left wheel and motor B as the right wheel of a small robot car. To turn, one wheel goes forward and the other goes back, so the car spins in place.

Wiring Diagram

  • Option 1: wire the ESP32 to the DRV8833 directly with jumper wires
The wiring diagram between ESP32 MicroPython DRV8833 two DC motors

This image is created using Fritzing. Click to enlarge image

The wiring diagram between ESP32 MicroPython DRV8833 two DC motors screw terminal block

This image is created using Fritzing. Click to enlarge image

DRV8833 Pin Connect To
IN1 ESP32 GPIO27
IN2 ESP32 GPIO26
IN3 ESP32 GPIO33
IN4 ESP32 GPIO32
EEP ESP32 3.3V
GND ESP32 GND and 5V adapter − (through the DC power jack)
VCC 5V adapter + (through the DC power jack)
OUT1, OUT2 Motor A (left wheel)
OUT3, OUT4 Motor B (right wheel)

Two motors pull more current than one. A small 5 volts adapter rated 2A or more is a safe choice. If one wheel turns the wrong way, swap the wires of that motor only.

ESP32 MicroPython Code - Two DC Motors

This script adds GPIO33 and GPIO32 for channel B. One shared function, set_channel(), handles any channel, and motor_a() and motor_b() call it with their own pins. On top of these, there are five easy driving functions: forward(), backward(), turn_left(), turn_right() and stop(). The speed for all of them is set in one place, DRIVE_SPEED = 70.

""" This ESP32 MicroPython code was developed by newbiely.com This ESP32 MicroPython code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/esp32-micropython/esp32-micropython-drv8833-dc-motor-driver """ from machine import Pin, PWM import time # Motor A (left wheel) is on channel A of the DRV8833 module IN1_PIN = 27 # ESP32 GPIO27 connected to the IN1 pin of the DRV8833 IN2_PIN = 26 # ESP32 GPIO26 connected to the IN2 pin of the DRV8833 # Motor B (right wheel) is on channel B of the DRV8833 module IN3_PIN = 33 # ESP32 GPIO33 connected to the IN3 pin of the DRV8833 IN4_PIN = 32 # ESP32 GPIO32 connected to the IN4 pin of the DRV8833 PWM_FREQ = 1000 # 1 kHz PWM FULL_DUTY = 65535 # duty_u16() range is 0 to 65535 DRIVE_SPEED = 70 # driving speed in % (0 to 100) in1 = PWM(Pin(IN1_PIN), freq=PWM_FREQ) in2 = PWM(Pin(IN2_PIN), freq=PWM_FREQ) in3 = PWM(Pin(IN3_PIN), freq=PWM_FREQ) in4 = PWM(Pin(IN4_PIN), freq=PWM_FREQ) def set_channel(pin_a, pin_b, speed): # speed: -100 to 100 (%). Positive = forward, negative = reverse, 0 = coast speed = max(-100, min(100, speed)) duty = abs(speed) * FULL_DUTY // 100 if speed > 0: pin_a.duty_u16(duty) # PWM on the first IN pin, second IN pin LOW pin_b.duty_u16(0) elif speed < 0: pin_a.duty_u16(0) # first IN pin LOW, PWM on the second IN pin pin_b.duty_u16(duty) else: pin_a.duty_u16(0) # both LOW = coast pin_b.duty_u16(0) def motor_a(speed): set_channel(in1, in2, speed) def motor_b(speed): set_channel(in3, in4, speed) def forward(): print("Car: forward") motor_a(DRIVE_SPEED) motor_b(DRIVE_SPEED) def backward(): print("Car: backward") motor_a(-DRIVE_SPEED) motor_b(-DRIVE_SPEED) def turn_left(): print("Car: turn left") motor_a(-DRIVE_SPEED) # left wheel goes back motor_b(DRIVE_SPEED) # right wheel goes forward def turn_right(): print("Car: turn right") motor_a(DRIVE_SPEED) # left wheel goes forward motor_b(-DRIVE_SPEED) # right wheel goes back def stop(): print("Car: stop") motor_a(0) motor_b(0) stop() # make sure both motors are stopped at start while True: forward() time.sleep(2) stop() time.sleep(1) backward() time.sleep(2) stop() time.sleep(1) turn_left() time.sleep(1) stop() time.sleep(1) turn_right() time.sleep(1) stop() time.sleep(2)

Detailed Instructions

  • Add the second motor and the IN3/IN4 wires as shown in the new diagram.
  • Copy the code above, paste it into Thonny, and save it to the ESP32 as main.py (replace the old file).
  • Plug in the 5V adapter, then click the green Run button.
  • Lift the car (or hold the motors) so the wheels can spin freely while you test.
  • Check out the message in the Shell at the bottom of Thonny.
Shell x
>>> %Run -c $EDITOR_CONTENT
MPY: soft reboot Car: stop Car: forward Car: stop Car: backward Car: stop Car: turn left Car: stop Car: turn right Car: stop Car: forward
MicroPython (ESP32) • CP2102 USB To UART Bridge Controller @ COM12 ≡

If you name your script main.py and save it to the MicroPython device, it will run automatically every time the ESP32 is powered on.

The motors stop by themselves in the middle of a run? The DRV8833 may be too hot, or the current may be too high, so its protection cut the power. Let it cool down, use smaller motors, or lower DRIVE_SPEED.

Video Tutorial

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!