Brushed DC Motor Control Using an MDD3A H-bridge Featuring FreeRTOS and the Arduino C33

What is an H-bridge?

The H-bridge is a circuit featuring four semiconductor switches. In its simplest form, the H-bridge may be constructed using four switches. This engineering brief is focused on a modular subset of the H-bridge family known as motor controller modules. This is a popular topology for driving small brush type DC motors as shown in Figure 1. With relatively simple microcontroller code, we can control the motor’s direction and rotational velocity.

This engineering brief introduces the MDD3A dual channel motor driver which features a MOSFET based H-bridge. It includes sample code for the Arduino PORTENTA Pro C33 operating within a FreeRTOS environment.

Figure 1: Picture of the Seeed MDD3A motor drive, Polilu 4754 motor, Arduino C33 on breakout board and Digilent Analog Discovery.

Tech Tip: The MDD3A features a 5 VDC voltage regulator providing a convenient power source for your microcontroller circuit with a 200 mA capacity. This is an optional connection which should be used with caution especially with 3.3 VDC devices. Note that the MDD3A ground must be connected. This shared connection is used to provide a common reference between the microcontroller’s logic outputs and the motor driver’s inputs.

What is Pulse Width Modulation?

The typical motor drive module accommodates a Pulse Width Modulation (PWM) input. For most applications, the motor’s rotational velocity is approximately proportional to the PWM’s duty cycle. Many articles have been written about using the PWM. For example, you may already be familiar with the Arduino analogWrite( ) function. Perhaps this was your introduction to the PWM using hardware and code to dim a LED.

For this brief, we will use the enhanced PWM capabilities of the C33. If you have not already done so please review this article for the Arduino Nano Every PWM and this article for Arduino C33 PWM. Both articles demonstrate methods to improve the PWM performance from their respective microcontrollers. Please take the time to explore the C33 article as the remainder of this article assumed you are familiar with the underlying Arduino PWM Application Programming Interface (API).

How is an H-bridge motor controller physically connected to a microcontroller?

There are two general interfaces between the microcontroller and the motor control module including:

  • direction plus PWM
  • dual PWM

The result is the same for both interface types as both motor direction and rotation velocity are under direct control of the microcontroller. The techniques differ in the hardware tradeoffs. A direction pin plus PWM places additional constraints on the motor controller while minimizing microcontroller resources to a single digital I/O (input/ Output) pin and a PWM. On the other hand, the dual PWM simplifies the motor controller while consuming two microcontroller PWM. Note that one and only one of the PWM output drives in a dual interface is active at any given time. The “unused” PWM is typically set to a zero duty cycle. Please refer to the manufacturer’s datasheet for the specific device configuration.

As an example, the Cytron (Seeed) MD13S features a direction plus PWM. The small MDD3A showcased in this article features a dual PWM interface.

What microcontroller software is used for the PWM based H-bridge motor controller?

As implied in the introduction, we are using Arduino, but we deviate from the traditional software path. Rather than using the analogWrite( ) function we are leveraging the power of the PORTENTA Pro C33 by using a class-based API from deep within the Arduino IDE.

The FreeRTOS task is shown below. The end of the code shows that the individual PWMs may be set using a floating-point parameter passed to the pulse_perc method. The middle portion of the code causes the motor slowly oscillates from full CW to full CCW as determined by the float DutyCycle variable. The setup( ) portion of the FreeRTOS task configures the PWM.

This code closely follows the technique outlined in this article. Specifically, it leverages the API contained with: C:\Users\your_name\AppData\Local\Arduino15\packages\arduino\hardware\renesas_portenta\1.1.0

Note that a small change would allow a direction plus PWM controller to be used.

#include "TaskHeartbeat.h"

static uint32_t state = 1;
static float DutyCycle = 0;

void heartbeat_thread_func(void *pvParameters) {

  /* setup() */

  pinMode(HEARTBEAT_PIN, OUTPUT);		         // Defined in "TaskHeartbeat.h"
  pinMode(PWM_PIN_1A, OUTPUT);
  pinMode(PWM_PIN_1B, OUTPUT);

  PwmOut pwm_1A(PWM_PIN_1A), pwm_1B(PWM_PIN_1B); // Instantiate two PWM objects
  pwm_1A.begin();
  pwm_1B.begin();

  pwm_1A.period_us(PWM_PERIOD_us);               // Set for a PWM frequency of 10 kHz
  pwm_1B.period_us(PWM_PERIOD_us);

  pwm_1A.pulse_perc(0);
  pwm_1B.pulse_perc(0);

  /* loop() */

  for (;;) {

    digitalWrite(HEARTBEAT_PIN, HIGH);
    vTaskDelay(1);
    digitalWrite(HEARTBEAT_PIN, LOW);
    vTaskDelay(9);

    if (state) {		                          // Smooth transition from zero, to full CW, to zero, to full CW, to zero, repeat forever
      DutyCycle += 0.025;                 
      if (DutyCycle > 100.0) {
        DutyCycle = 100.0;
        state = 0;
      }
    } else {
      DutyCycle -= 0.025;
      if (DutyCycle < -100) {
        DutyCycle = -100;
        state = 1;
      }
    }

    if (DutyCycle > 0) {		                   // Bidirectional motor control with Duty cycle bounded at +/- 100.0 %
      pwm_1A.pulse_perc(fabs(DutyCycle));
      pwm_1B.pulse_perc(0);
    } else {
      pwm_1A.pulse_perc(0);
      pwm_1B.pulse_perc(fabs(DutyCycle));
    }
  }
}

Tech Tip: The code configures the Arduino C33 to operate at 10 kHz. The switching frequency is just audible when the motor is operating at slow speed. It may be desirable to shift the PWM frequency to the MDD3A maximum of 20 kHz. This would eliminate the motor squeal. However, the high frequency PWM can cause undesirable Electromagnetic Interference (EMI). This is readily observable using an AM radio as the PWM tone will be present at harmonics of the PWM frequency. For example, the 75th harmonic of a 20 kHz PWM may be present at 1.5 MHz. Normally, we wouldn’t worry about these high order harmonics. However, the high current motor leads are long and unshielded. A closely positioned radio may reveal the undesirable interference. Be sure to review your Fourier theory.

Parting thoughts

Controlling an H-bridge based motor control module is relatively easy. The challenge is to configure the PWM for the desired PWM frequency. Personally, I like the Arduino API solution as it allows the PWM to be set as a percentage (+/- 100). This abstraction makes it easy to code. However, this does come at the expense of CPU overhead. We shouldn’t be too cavalier, but the powerful C33 tends to make this an academic discussion.

Best Wishes,

APDahlen

Please follow this link for related Arduino education content.

About the author

Aaron Dahlen, LCDR USCG (Ret.), serves as an application engineer at DigiKey. He has a unique electronics and automation foundation built over a 27-year military career as a technician and engineer which was further enhanced by 12 years of teaching (interwoven). With an MSEE degree from Minnesota State University, Mankato, Dahlen has taught in an ABET accredited EE program, served as the program coordinator for an EET program, and taught component-level repair to military electronics technicians. Dahlen has returned to his Northern Minnesota home and thoroughly enjoys researching and writing articles such as this.