GPIO PWM For Raspberry Pi H-Bridge DC Motor Control

GPIO PWM for Raspberry Pi H-Bridge DC Motor Control

In this article, I look at using the Raspberry Pi GPIO PWM for DC motor control. Through Python programming, I look at how to interface with a typical H-Bridge DC motor driver. Furthermore, H-Bridge diver code examples with wire connection illustrations are included.

There is a lot that goes on in code between R/C controller input and H-Bridge DC motor driver output. This is especially true where the robot vehicle is a skid steer type. So, getting a bit of understanding of how the hardware works first will help create the rest of the robot control software. Furthermore, it is worth noting to keep hardware driver software code routines separate from robot control logic routines. This will help keep the Python code elements of the robot control software modular.

I have already covered R/C controller input using a game controller here. Now, I take a look at how to drive a typical H-Bridge module, connected to a Raspberry, with GPIO PWM.

GPIO PWM

GPIO PWM Output at 1200Hz Frequency
GPIO PWM Output at 1200Hz Frequency

I admit at this point I do not know how the GPIO PWM is implemented on the Raspberry Pi. But I believe the PWM is software driven using a shared clock source and might involve DMA channels. In any case, from my own tests, I am confident that I can get some decent DC motor control by attaching an H-Bridge module directly to the Raspberry Pi. Then use GPIO PWM through the GPIO Zero API. I think this is an ideal approach for makers beginning to build their own R/C robot project.

GPIO PWM Python 3 API

First, I will take a look at the GPIO Zero API as a quick brief on how to get PWM working. And while there are a few other ways to get PWM working on the Raspberry Pi, the Python class I will be focusing on is PWMOutputDevice. However, GPIO Zero API is well documented and information on all available classes is here. Then I take a look at how the GPIO PWM might interface with an H-Bridge module.

From gpiozero import PWMOutputDevice
leftWheels = PWMOutputDevice(21)
leftWheels.frequency = 1000
leftWheels.value = 0.50

The above python code shows the initial PWM setup. While using (BCM) pin numbering, I initialize a new object I call leftWheels with a Raspberry Pi GPIO pin Number. Then I use property setters frequency and value to set the initial PWM frequency and duty cycle. Then during robot control operation, the duty cycle is the only value I will change for PWM robot speed control.

The duty cycle range is between 0.0 and 1.0 inclusive. So consequently a re-map function may be required to convert controller output value ranges to PWM duty cycle ranges. Adjusting the PWM duty cycle, for instance, will allow variable RPM control of DC motors.

Also, check for additional initialisation settings and other class properties and methods at the following link.

GPIO PWM Python 3 Code Examples

Raspberry Pi and L298N H-Bridge Connection Schematic
Raspberry Pi and L298N H-Bridge Connection Schematic

The Python code examples provided show how to set up PWM for two different H-Bridge configurations. The full H-Bridge wiring schematic is not included in this case since a full example schematic is shown above. For now, I am just focussing on the H-Bridge control logic.

A typical H-Bridge module I am using here is an L298N Dual H-Bridge DC motor driver module. You can get more information about this module here. This H-Bridge module is compatible with the Raspberry Pi, however, other L298N configurations might not be as compatible. There are other popular H-Bridge modules about but not all are compatible with the Raspberry Pi. So, test the electrical characteristics of any H-Bridge module before connecting to the Raspberry Pi.

The L298N H-Bridge module, like in the image below, has two connection configurations available. Which connection configuration you choose will depend largely on the number of PWM channels you want to use. The Raspberry Pi, for example, can use GPIO PWM on any GPIO pin so only four pins require connection to the H-Bridge Module. However, a six wire connection scheme, including two PWM channels, is available.

GPIO PWM Four Wire H-Bridge

This wiring scheme is likely to be favourite because it only requires four GPIO pins on the Raspberry Pi. Furthermore, less code is required for each drive control GPIO pin transitions. However, with more efficient coding, the only real benefit between the four and the Six H-Bridge wire connections is the number of GPIO pins saved.

The H-Bridge Enable pins are closed so that the L298N direction control pins are always enabled. So, to drive DC motors, GPIO PWM is applied directly to the DC motor direction control pins. Review the code below for an example of how the four wire connection works.

L298N H-Bridge Control Scheme Illustration
L298N H-Bridge Control Scheme Four Wire Illustration
#!/usr/bin/env python3

"""
File: skidsteer_four_pwm_test.py

This code will test Raspberry Pi GPIO PWM on four GPIO
pins. The code test ran with L298N H-Bridge driver module connected.

Website:	www.bluetin.io
Date:		27/11/2017
"""

__author__ = "Mark Heywood"
__version__ = "0.1.0"
__license__ = "MIT"

from gpiozero import PWMOutputDevice
from time import sleep

#///////////////// Define Motor Driver GPIO Pins /////////////////
# Motor A, Left Side GPIO CONSTANTS
PWM_FORWARD_LEFT_PIN = 26	# IN1 - Forward Drive
PWM_REVERSE_LEFT_PIN = 19	# IN2 - Reverse Drive
# Motor B, Right Side GPIO CONSTANTS
PWM_FORWARD_RIGHT_PIN = 13	# IN1 - Forward Drive
PWM_REVERSE_RIGHT_PIN = 6	# IN2 - Reverse Drive

# Initialise objects for H-Bridge PWM pins
# Set initial duty cycle to 0 and frequency to 1000
forwardLeft = PWMOutputDevice(PWM_FORWARD_LEFT_PIN, True, 0, 1000)
reverseLeft = PWMOutputDevice(PWM_REVERSE_LEFT_PIN, True, 0, 1000)

forwardRight = PWMOutputDevice(PWM_FORWARD_RIGHT_PIN, True, 0, 1000)
reverseRight = PWMOutputDevice(PWM_REVERSE_RIGHT_PIN, True, 0, 1000)


def allStop():
	forwardLeft.value = 0
	reverseLeft.value = 0
	forwardRight.value = 0
	reverseRight.value = 0

def forwardDrive():
	forwardLeft.value = 1.0
	reverseLeft.value = 0
	forwardRight.value = 1.0
	reverseRight.value = 0

def reverseDrive():
	forwardLeft.value = 0
	reverseLeft.value = 1.0
	forwardRight.value = 0
	reverseRight.value = 1.0

def spinLeft():
	forwardLeft.value = 0
	reverseLeft.value = 1.0
	forwardRight.value = 1.0
	reverseRight.value = 0

def SpinRight():
	forwardLeft.value = 1.0
	reverseLeft.value = 0
	forwardRight.value = 0
	reverseRight.value = 1.0

def forwardTurnLeft():
	forwardLeft.value = 0.2
	reverseLeft.value = 0
	forwardRight.value = 0.8
	reverseRight.value = 0

def forwardTurnRight():
	forwardLeft.value = 0.8
	reverseLeft.value = 0
	forwardRight.value = 0.2
	reverseRight.value = 0

def reverseTurnLeft():
	forwardLeft.value = 0
	reverseLeft.value = 0.2
	forwardRight.value = 0
	reverseRight.value = 0.8

def reverseTurnRight():
	forwardLeft.value = 0
	reverseLeft.value = 0.8
	forwardRight.value = 0
	reverseRight.value = 0.2

def main():
	allStop()
	forwardDrive()
	sleep(5)
	reverseDrive()
	sleep(5)
	spinLeft()
	sleep(5)
	SpinRight()
	sleep(5)
	forwardTurnLeft()
	sleep(5)
	forwardTurnRight()
	sleep(5)
	reverseTurnLeft()
	sleep(5)
	reverseTurnRight()
	sleep(5)
	allStop()


if __name__ == "__main__":
    """ This is executed when run from the command line """
    main()
GPIO PWM Six Wire H-Bridge

I use six wire H-Bridge connection for mostly the Arduino platform due to the limited number of PWM pins. In regards to the Raspberry Pi though, with software GPIO PWM, enough GPIO pins can be made PWM with consistent frequency. It is probably not necessary to use the six wire H-Bridge connection with the Raspberry Pi.

PWM is applied to the H-Bridge Enable pins and this will also add PWM to the DC motor direction control pins. The shunts are removed from the H-Bridge Enable pins before connecting to the Raspberry Pi. The Four H-Bridge DC motor direction control pins will now be pulled high or low depending on the motor direction required. So, review the Python code below to see how the six wire connection works.

L298N H-Bridge Control Scheme Six Wire Illustration
L298N H-Bridge Control Scheme Six Wire Illustration
#!/usr/bin/env python3

"""
File: skidsteer_two_pwm_test.py

This code will test Raspberry Pi GPIO PWM on four GPIO
pins. The code test ran with L298N H-Bridge driver module connected.

Website:	www.bluetin.io
Date:		27/11/2017
"""

__author__ = "Mark Heywood"
__version__ = "0.1.0"
__license__ = "MIT"

from gpiozero import PWMOutputDevice
from gpiozero import DigitalOutputDevice
from time import sleep

#///////////////// Define Motor Driver GPIO Pins /////////////////
# Motor A, Left Side GPIO CONSTANTS
PWM_DRIVE_LEFT = 21		# ENA - H-Bridge enable pin
FORWARD_LEFT_PIN = 26	# IN1 - Forward Drive
REVERSE_LEFT_PIN = 19	# IN2 - Reverse Drive
# Motor B, Right Side GPIO CONSTANTS
PWM_DRIVE_RIGHT = 5		# ENB - H-Bridge enable pin
FORWARD_RIGHT_PIN = 13	# IN1 - Forward Drive
REVERSE_RIGHT_PIN = 6	# IN2 - Reverse Drive

# Initialise objects for H-Bridge GPIO PWM pins
# Set initial duty cycle to 0 and frequency to 1000
driveLeft = PWMOutputDevice(PWM_DRIVE_LEFT, True, 0, 1000)
driveRight = PWMOutputDevice(PWM_DRIVE_RIGHT, True, 0, 1000)

# Initialise objects for H-Bridge digital GPIO pins
forwardLeft = PWMOutputDevice(FORWARD_LEFT_PIN)
reverseLeft = PWMOutputDevice(REVERSE_LEFT_PIN)
forwardRight = PWMOutputDevice(FORWARD_RIGHT_PIN)
reverseRight = PWMOutputDevice(REVERSE_RIGHT_PIN)

def allStop():
	forwardLeft.value = False
	reverseLeft.value = False
	forwardRight.value = False
	reverseRight.value = False
	driveLeft.value = 0
	driveRight.value = 0

def forwardDrive():
	forwardLeft.value = True
	reverseLeft.value = False
	forwardRight.value = True
	reverseRight.value = False
	driveLeft.value = 1.0
	driveRight.value = 1.0

def reverseDrive():
	forwardLeft.value = False
	reverseLeft.value = True
	forwardRight.value = False
	reverseRight.value = True
	driveLeft.value = 1.0
	driveRight.value = 1.0

def spinLeft():
	forwardLeft.value = False
	reverseLeft.value = True
	forwardRight.value = True
	reverseRight.value = False
	driveLeft.value = 1.0
	driveRight.value = 1.0

def SpinRight():
	forwardLeft.value = True
	reverseLeft.value = False
	forwardRight.value = False
	reverseRight.value = True
	driveLeft.value = 1.0
	driveRight.value = 1.0

def forwardTurnLeft():
	forwardLeft.value = True
	reverseLeft.value = False
	forwardRight.value = True
	reverseRight.value = False
	driveLeft.value = 0.2
	driveRight.value = 0.8

def forwardTurnRight():
	forwardLeft.value = True
	reverseLeft.value = False
	forwardRight.value = True
	reverseRight.value = False
	driveLeft.value = 0.8
	driveRight.value = 0.2

def reverseTurnLeft():
	forwardLeft.value = False
	reverseLeft.value = True
	forwardRight.value = False
	reverseRight.value = True
	driveLeft.value = 0.2
	driveRight.value = 0.8

def reverseTurnRight():
	forwardLeft.value = False
	reverseLeft.value = True
	forwardRight.value = False
	reverseRight.value = True
	driveLeft.value = 0.8
	driveRight.value = 0.2

def main():
	allStop()
	forwardDrive()
	sleep(5)
	reverseDrive()
	sleep(5)
	spinLeft()
	sleep(5)
	SpinRight()
	sleep(5)
	forwardTurnLeft()
	sleep(5)
	forwardTurnRight()
	sleep(5)
	reverseTurnLeft()
	sleep(5)
	reverseTurnRight()
	sleep(5)
	allStop()


if __name__ == "__main__":
    """ This is executed when run from the command line """
    main()

Related Articles

Motor Driver for Raspberry Pi Robot using the TB6612FNG

Motor Driver for Raspberry Pi Robot using TB6612FNG – Link.

L298N Dual H Bridge DC Motor Driver Module

L298N H-Bridge DC Motor Driver Module Quick Start Guide – Link.

Buying Featured Items

The purchase price is going to vary greatly depending on how quickly you want the items. Therefore shop around checking out Amazon, Ebay, Adafruit and local electronic stores.

UK Searches:

UK Amazon:

  • L298N Dual H-Bridge – Search
  • Raspberry Pi – Search
  • MicroSD Card – Search
  • Raspberry Pi Compatible Wi-Fi Dongle – Search

US Searches:

US Amazon:

  • L298N Dual H-Bridge – Search
  • Raspberry Pi – Search
  • MicroSD Card – Search
  • Raspberry Pi Compatible Wi-Fi Dongle – Search

On Closing

I hope you find this article useful – GPIO PWM For Raspberry Pi H-Bridge DC Motor Control, please like and share.

One thought on “GPIO PWM For Raspberry Pi H-Bridge DC Motor Control”

Comments are closed.