Controlling DC Motors with DRV8833 Motor Driver and Arduino

Without a doubt, L293D and L298N are the go-to motor drivers for Arduino projects. They are reliable and have been used in hundreds, if not thousands, of projects. However, they have a major downside – they use bipolar junction transistors (BJTs), which makes them extremely inefficient.

The issue with BJTs is that they have an on-state voltage drop. The energy from that voltage needs to go somewhere, and it indeed does; it dissipates as heat. Over time, this can result in a considerable amount of energy loss and, in some cases, cause the driver to overheat. This can be a significant disadvantage for projects that must run for extended periods of time.

Thankfully, modern motor drivers like the DRV8833 really shine when it comes to efficiency. Instead of using BJTs, the DRV8833 uses MOSFETs. MOSFETs have almost negligible voltage drop, meaning that nearly all the voltage from the power supply is delivered to the motor. That is why the DRV8833 is not only more energy-efficient than BJT-based motor drivers, but it also generates far less heat, making it safer to use for longer periods.

So let’s dive in and discover the remarkable capabilities of the DRV8833 motor driver.

DRV8833 Motor Driver

At the heart of the module is an integrated H-Bridge driver IC from Texas Instruments that is optimized for motor driving applications – The DRV8833.

drv8833 module hardware overview

The DRV8833 features two NMOS H-bridge drivers, enabling it to control two DC brush motors, a bipolar stepper motor, solenoids, and other inductive loads.

It operates in a voltage range from 2.7 V to 10.8 V, and can continuously supply up to 1.2 A per channel. Additionally, it can tolerate peak currents up to 2 A per channel for a few seconds.

The DRV8833 also contains a number of protection features, such as under-voltage lockout, over-current, and over-temperature protection, offering a high level of reliability. Each of these events will disable the H-Bridge MOSFETs. After a fault condition has been removed, the device will resume its operation.

It also includes a low-power sleep mode, which lets you save power, especially when the motors are not in use.

All these features make it an excellent choice for powering small, low-voltage motors.

Technical Specifications

Here are the specifications:

Motor Voltage2.7V – 10.8V
Logic Voltage3V- and 5V-compatible
Continuous Output Current1.2A (Per Channel)
Peak Output Current2A (Per Channel)
Motor Channels2
Protection Featuresunder-voltage lockout, over-current, and over-temperature

For more information, please refer to the datasheet below.

DRV8833 Motor Driver Pinout

The DRV8833 driver has a total of 12 pins that connect it to the outside world. The pinout is as follows:

drv8833 motor driver pinout

Let’s get to know all the pins one by one.

Power Pins

Unlike most motor drivers, the DRV8833 has only one power supply connection (because the motor voltage is the same as the logic voltage).

drv8833 power pins

VCC and GND is where you connect the power supply that drives the motors, which can be in the range of 2.7V to 10.8V.

Note that the DRV8833 can work with voltages as low as 2.7V. This means it’s perfect for low-voltage projects, like those running on single-cell LiPo batteries and low-voltage motors.

Output Pins

The output pins of the DRV8825 motor driver, namely OUT1, OUT2, OUT3, and OUT4, are conveniently located on one side of the module for easy interfacing.

drv8833 output pins

Motor A should be connected to OUT1 and OUT2, while Motor B should be connected to OUT3, and OUT4. You can connect any brushed DC motor ranging from 2.7 V to 10.8 V to these pins.

Keep in mind that the DRV8833 can deliver 1.2 A per channel continuously (2 A peak) to a pair of DC motors.

Control Input Pins

Each motor has two control inputs; IN1 and IN2 are the control inputs for Motor A, while IN3 and IN4 are for Motor B. These control inputs allow you to control both the speed and spinning direction of the motor.

drv8833 input control pins

Direction Control:

The spinning direction of the motor can be controlled by applying logic HIGH (5V) or logic LOW (Ground) to these inputs.The truth table below shows how the inputs affect the driver outputs.

IN1/IN3IN2/IN4Spinning Direction
Low(0)Low(0)Motor OFF
High(1)Low(0)Forward
Low(0)High(1)Reverse
High(1)High(1)Motor OFF

Speed Control:

If you want to control speed, you can use Pulse Width Modulation (PWM) on the pin that’s usually high. If speed control isn’t needed, just set them to either HIGH or LOW.

Note that the control inputs are pulled low internally, effectively disabling the motor driver outputs by default.

Sleep Mode Pin

The SLEEP pin (labeled EEP on the board silkscreen) controls the DRV8833’s sleep mode. Setting this pin low puts the DRV8833 into a low-power sleep mode, while setting it high makes it active again.

drv8833 sleep pin

In this mode, the H-bridges are disabled, the gate drive charge pump is stopped, all internal logic is reset, all internal clocks are stopped, and all inputs are ignored. It’s important to note that when returning from sleep mode, the motor driver needs a little time, up to 1 millisecond, to become fully operational again.

By default, the SLEEP pin is pulled high on the board, so if you don’t plan to use the low-power sleep mode, you can just leave it disconnected.

On the backside of the DRV8833 module, there’s a solder jumper J1.

drv8833 enable jumper

By default, J1 is closed, which connects an on-board pullup to the SLEEP pin, thereby keeping the DRV8833 enabled. However, if you open J1, the onboard pullup gets disconnected from the SLEEP pin. This action enables the on-chip pulldown, which means that the DRV8833 will stay disabled by default. So, if you choose to open J1, remember that you’ll need to manually turn the DRV8833 on when needed.

Fault Detection Pin

The FAULT pin (labeled ULT on the board silkscreen) is an open-drain output that is driven low by the chip whenever an over-current, over-temperature-or under-voltage condition occurs.

drv8833 fault pin

By default, this pin remains in a floating state. So, if you want to monitor fault conditions on the driver, you will need to connect an external pull-up resistor (or use a microcontroller input with its built-in pull-up enabled).

Current limiting

The DRV8833 can actively limit the current passing through the motors. This is generally accomplished by connecting a resistor between AISEN pin and ground to set the limit for Motor A, and another resistor between BISEN pin and ground to set the limit for Motor B.

However, this specific DRV8833 breakout board connects these current sense pins directly to ground, effectively disabling the current limiting feature.

Wiring a DRV8833 Module to an Arduino

Now that we know everything about the module, we can start hooking it up to our Arduino!

To begin, connect the motor power supply. The VCC pin is the power supply for the motors and should be connected to an appropriate power source depending on your motor requirements (2.7V to 10.8V). In our experiment, we are using DC gearbox motors, also called “TT” motors, which are often found in two-wheel-drive robots. They are rated for 3 to 12V. We will therefore connect an external 5V power source to the VCC pin.

Now connect the DRV8833’s control inputs (IN1, IN2, IN3, and IN4) to the four digital output pins (10, 9, 6, and 5) on the Arduino. Note that all of these pins are PWM-enabled.

Wire one motor to terminal A (OUT1 and OUT2) and the other to terminal B (OUT3 and OUT4). You can swap out your motor’s connections. There is technically no right or wrong way.

If you want to monitor fault conditions, you can connect the FAULT pin to a digital pin on the Arduino. Remember to use an external pull-up resistor or enable the built-in pull-up resistor in the Arduino for this pin because it’s an open-drain output.

Finally, make sure your circuit and the Arduino share a common ground.

The following table lists the pin connections for connecting the DRV8833 motor driver to the Arduino:

DRV8833 DriverArduino
GNDGND
IN110
IN29
IN36
IN45

The image below shows how to build the circuit.

wiring drv8833 motor driver module to arduino

Arduino Example Code

The sketch below will show you how to control the speed and spinning direction of a pair of DC motors-using the DRV8833 Motor Driver and can serve as the basis for more practical experiments and projects.

The sketch moves a pair of DC motors at varying rate and direction.

When accelerating or decelerating the motor, you may hear it humming, especially at lower PWM values. This is normal; there is nothing to be concerned about. This happens because the DC motor requires a minimum amount of voltage to operate.

// Define the control inputs
#define MOT_A1_PIN 10
#define MOT_A2_PIN 9
#define MOT_B1_PIN 6
#define MOT_B2_PIN 5

void setup(void)
{
  // Set all the motor control inputs to OUTPUT
  pinMode(MOT_A1_PIN, OUTPUT);
  pinMode(MOT_A2_PIN, OUTPUT);
  pinMode(MOT_B1_PIN, OUTPUT);
  pinMode(MOT_B2_PIN, OUTPUT);

  // Turn off motors - Initial state
  digitalWrite(MOT_A1_PIN, LOW);
  digitalWrite(MOT_A2_PIN, LOW);
  digitalWrite(MOT_B1_PIN, LOW);
  digitalWrite(MOT_B2_PIN, LOW);

  // Initialize the serial UART at 9600 baud
  Serial.begin(9600);
}

void loop(void)
{
  // Generate a fixed motion sequence to demonstrate the motor modes.

  // Ramp speed up.
  for (int i = 0; i < 11; i++) {
    spin_and_wait(25*i, 25*i, 500);
  }
  // Full speed forward.
  spin_and_wait(255,255,2000);

  // Ramp speed into full reverse.
  for (int i = 0; i < 21 ; i++) {
    spin_and_wait(255 - 25*i, 255 - 25*i, 500);
  }

  // Full speed reverse.
  spin_and_wait(-255,-255,2000);

  // Stop.
  spin_and_wait(0,0,2000);

  // Full speed, forward, turn, reverse, and turn for a two-wheeled base.
  spin_and_wait(255, 255, 2000);
  spin_and_wait(0, 0, 1000);
  spin_and_wait(-255, 255, 2000);
  spin_and_wait(0, 0, 1000);
  spin_and_wait(-255, -255, 2000);
  spin_and_wait(0, 0, 1000);
  spin_and_wait(255, -255, 2000);
  spin_and_wait(0, 0, 1000);
}

/// Set the current on a motor channel using PWM and directional logic.
///
/// \param pwm    PWM duty cycle ranging from -255 full reverse to 255 full forward
/// \param IN1_PIN  pin number xIN1 for the given channel
/// \param IN2_PIN  pin number xIN2 for the given channel
void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN)
{
  if (pwm < 0) {  // reverse speeds
    analogWrite(IN1_PIN, -pwm);
    digitalWrite(IN2_PIN, LOW);

  } else { // stop or forward
    digitalWrite(IN1_PIN, LOW);
    analogWrite(IN2_PIN, pwm);
  }
}

/// Set the current on both motors.
///
/// \param pwm_A  motor A PWM, -255 to 255
/// \param pwm_B  motor B PWM, -255 to 255
void set_motor_currents(int pwm_A, int pwm_B)
{
  set_motor_pwm(pwm_A, MOT_A1_PIN, MOT_A2_PIN);
  set_motor_pwm(pwm_B, MOT_B1_PIN, MOT_B2_PIN);

  // Print a status message to the console.
  Serial.print("Set motor A PWM = ");
  Serial.print(pwm_A);
  Serial.print(" motor B PWM = ");
  Serial.println(pwm_B);
}

/// Simple primitive for the motion sequence to set a speed and wait for an interval.
///
/// \param pwm_A  motor A PWM, -255 to 255
/// \param pwm_B  motor B PWM, -255 to 255
/// \param duration delay in milliseconds
void spin_and_wait(int pwm_A, int pwm_B, int duration)
{
  set_motor_currents(pwm_A, pwm_B);
  delay(duration);
}

Code Explanation:

The Arduino code is fairly simple. It does not require any libraries to work. The sketch starts by declaring the Arduino pins that are connected to the DRV8833’s control pins.

// Define the control inputs
#define MOT_A1_PIN 10
#define MOT_A2_PIN 9
#define MOT_B1_PIN 6
#define MOT_B2_PIN 5

The setup section of the code initializes the hardware. It configures all of the motor control pins as digital OUTPUT and sets them to LOW, to initially disable both motors. Then, it initializes the serial communication at a baud rate of 9600.

void setup(void)
{
  // Set all the motor control inputs to OUTPUT
  pinMode(MOT_A1_PIN, OUTPUT);
  pinMode(MOT_A2_PIN, OUTPUT);
  pinMode(MOT_B1_PIN, OUTPUT);
  pinMode(MOT_B2_PIN, OUTPUT);

  // Turn off motors - Initial state
  digitalWrite(MOT_A1_PIN, LOW);
  digitalWrite(MOT_A2_PIN, LOW);
  digitalWrite(MOT_B1_PIN, LOW);
  digitalWrite(MOT_B2_PIN, LOW);

  // Initialize the serial UART at 9600 baud
  Serial.begin(9600);
}

The loop section of the code generates a fixed motion sequence to demonstrate the motor modes.

It starts by gradually increasing the speed of the motors, then goes to full speed, slows down again and reverses direction to full speed, and finally stops.

// Ramp speed up.
for (int i = 0; i < 11; i++) {
  spin_and_wait(25*i, 25*i, 500);
}
// Full speed forward.
spin_and_wait(255,255,2000);

// Ramp speed into full reverse.
for (int i = 0; i < 21 ; i++) {
  spin_and_wait(255 - 25*i, 255 - 25*i, 500);
}

// Full speed reverse.
spin_and_wait(-255,-255,2000);

// Stop.
spin_and_wait(0,0,2000);

After the stop, it demonstrates a turn operation for a two-wheeled robot base, where one wheel moves forward while the other moves backward, causing the robot to turn. After demonstrating all these movements, the loop repeats.

// Full speed, forward, turn, reverse, and turn for a two-wheeled base.
spin_and_wait(255, 255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(-255, 255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(-255, -255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(255, -255, 2000);
spin_and_wait(0, 0, 1000);

Three user-defined functions are used in this sketch: set_motor_pwm(), set_motor_currents(), and spin_and_wait().

The set_motor_pwm() Function sets the current on a motor channel using PWM and directional logic. If the pwm value is negative, the motor spins in one direction. If the pwm value is 0 or positive, the motor either stops or spins in the other direction.

void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN)
{
  if (pwm < 0) {  // reverse speeds
    analogWrite(IN1_PIN, -pwm);
    digitalWrite(IN2_PIN, LOW);

  } else { // stop or forward
    digitalWrite(IN1_PIN, LOW);
    analogWrite(IN2_PIN, pwm);
  }
}

The set_motor_currents() function uses the previous function to set the currents on both motors. It prints the current PWM values for each motor to the serial monitor.

void set_motor_currents(int pwm_A, int pwm_B)
{
  set_motor_pwm(pwm_A, MOT_A1_PIN, MOT_A2_PIN);
  set_motor_pwm(pwm_B, MOT_B1_PIN, MOT_B2_PIN);

  // Print a status message to the console.
  Serial.print("Set motor A PWM = ");
  Serial.print(pwm_A);
  Serial.print(" motor B PWM = ");
  Serial.println(pwm_B);
}

The spin_and_wait() function sets the speed and waits for a specified amount of time before moving to the next command. It uses the set_motor_currents() function to set the PWM values for both motors and then waits for the specified duration in milliseconds.

void spin_and_wait(int pwm_A, int pwm_B, int duration)
{
  set_motor_currents(pwm_A, pwm_B);
  delay(duration);
}