DC Motor Examples - Raspberry Pi Pico¶
The following short Python programs will demonstrate essential operation of the
Raspberry Pi Pico board. These assume one or DC motor actuators are externally
attached. Each can be run by copying the program into code.py
on the
CIRCUITPY drive offered by the board. The text can be pasted directly from this
page, or each file can be downloaded from the CircuitPython sample code folder on this site.
Related Pages
Contents
Sample DRV8833 Motor Driver Circuit¶
Dual Spin Example¶
This self-contained example operates two small DC motors.
Direct download: dual_spin.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | # dual_spin.py
#
# Raspberry Pi Pico - DC motor motion demo
#
# Demonstrates operating two DC motors driven by a DRV8833.
#
# This assumes a Pololu DRV8833 dual motor driver has been wired up to the Pico as follows:
# Pico pin 24, GPIO18 -> AIN1
# Pico pin 25, GPIO19 -> AIN2
# Pico pin 26, GPIO20 -> BIN2
# Pico pin 27, GPIO21 -> BIN1
# any Pico GND -> GND
# DRV8833 carrier board: https://www.pololu.com/product/2130
################################################################
# CircuitPython module documentation:
# time https://circuitpython.readthedocs.io/en/latest/shared-bindings/time/index.html
# math https://circuitpython.readthedocs.io/en/latest/shared-bindings/math/index.html
# board https://circuitpython.readthedocs.io/en/latest/shared-bindings/board/index.html
# pwmio https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html
################################################################################
# print a banner as reminder of what code is loaded
print("Starting dual_spin script.")
# load standard Python modules
import math, time
# load the CircuitPython hardware definition module for pin definitions
import board
# load the CircuitPython pulse-width-modulation module for driving hardware
import pwmio
#--------------------------------------------------------------------------------
# Class to represent a single dual H-bridge driver.
class DRV8833():
def __init__(self, AIN1=board.GP18, AIN2=board.GP19, BIN2=board.GP20, BIN1=board.GP21, pwm_rate=20000):
# Create a pair of PWMOut objects for each motor channel.
self.ain1 = pwmio.PWMOut(AIN1, duty_cycle=0, frequency=pwm_rate)
self.ain2 = pwmio.PWMOut(AIN2, duty_cycle=0, frequency=pwm_rate)
self.bin1 = pwmio.PWMOut(BIN1, duty_cycle=0, frequency=pwm_rate)
self.bin2 = pwmio.PWMOut(BIN2, duty_cycle=0, frequency=pwm_rate)
def write(self, channel, rate):
"""Set the speed and direction on a single motor channel.
:param channel: 0 for motor A, 1 for motor B
:param rate: modulation value between -1.0 and 1.0, full reverse to full forward."""
# convert the rate into a 16-bit fixed point integer
pwm = min(max(int(2**16 * abs(rate)), 0), 65535)
if channel == 0:
if rate < 0:
self.ain1.duty_cycle = pwm
self.ain2.duty_cycle = 0
else:
self.ain1.duty_cycle = 0
self.ain2.duty_cycle = pwm
else:
if rate < 0:
self.bin1.duty_cycle = pwm
self.bin2.duty_cycle = 0
else:
self.bin1.duty_cycle = 0
self.bin2.duty_cycle = pwm
#--------------------------------------------------------------------------------
# Create an object to represent a dual motor driver.
print("Creating driver object.")
driver = DRV8833()
#--------------------------------------------------------------------------------
# Begin the main processing loop. This is structured as a looping script, since
# each movement primitive 'blocks', i.e. doesn't return until the action is
# finished.
print("Starting main script.")
while True:
# initial pause
time.sleep(2.0)
print("Testing motor A.")
driver.write(0, 1.0)
time.sleep(2.0)
driver.write(0, 0.0)
time.sleep(2.0)
driver.write(0, -1.0)
time.sleep(2.0)
driver.write(0, 0.0)
time.sleep(2.0)
print("Testing motor B.")
driver.write(1, 1.0)
time.sleep(2.0)
driver.write(1, 0.0)
time.sleep(2.0)
driver.write(1, -1.0)
time.sleep(2.0)
driver.write(1, 0.0)
time.sleep(2.0)
print("Ramp test.")
for i in range(10):
driver.write(0, i*0.1)
driver.write(1, i*0.1)
time.sleep(0.5)
driver.write(0, 0.0)
driver.write(1, 0.0)
time.sleep(2.0)
for i in range(10):
driver.write(0, -i*0.1)
driver.write(1, -i*0.1)
time.sleep(0.5)
driver.write(0, 0.0)
driver.write(1, 0.0)
time.sleep(2.0)
|
drv8833 module¶
This module provides a class for controlling a DRV8833 dual H-bridge DC motor driver. This device can drive two low-power DC motor bidirectionally with variable speed. Note that this file will normally be copied to the top-level folder of the CIRCUITPY filesystem so it can be imported by other scripts.
-
class
drv8833.
DRV8833
¶ This class represents a single dual H-bridge driver. It configures four pins for PWM output and can be used to control two DC motors bidirectionally at variable speed.
N.B. this does not implement any other timing process, it simply sets motor PWM levels but does not apply feedback, duration, or trajectory.
Direct download: drv8833.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | # drv8833.py
#
# Raspberry Pi Pico - dual H-bridge motor driver support
#
# This module provides a class for controlling a DRV8833 dual H-bridge DC motor driver.
# This device can drive two low-power DC motor bidirectionally with variable speed.
#
# A typical usage requires four digital outputs. The defaults assumes a Pololu
# DRV8833 dual motor driver has been wired up to the Pico as follows:
# Pico pin 24, GPIO18 -> AIN1
# Pico pin 25, GPIO19 -> AIN2
# Pico pin 26, GPIO20 -> BIN2
# Pico pin 27, GPIO21 -> BIN1
# any Pico GND -> GND
# DRV8833 carrier board: https://www.pololu.com/product/2130
################################################################
# CircuitPython module documentation:
# time https://circuitpython.readthedocs.io/en/latest/shared-bindings/time/index.html
# math https://circuitpython.readthedocs.io/en/latest/shared-bindings/math/index.html
# board https://circuitpython.readthedocs.io/en/latest/shared-bindings/board/index.html
# pwmio https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html
#
# Driver lifecycle documentation:
# https://circuitpython.readthedocs.io/en/latest/docs/design_guide.html#lifetime-and-contextmanagers
#
################################################################################
# load standard Python modules
import math, time
# load the CircuitPython hardware definition module for pin definitions
import board
# load the CircuitPython pulse-width-modulation module for driving hardware
import pwmio
#--------------------------------------------------------------------------------
class DRV8833:
def __init__(self,
AIN1=board.GP18, AIN2=board.GP19, # control pins for motor A
BIN2=board.GP20, BIN1=board.GP21, # control pins for motor B
pwm_rate=20000):
"""This class represents a single dual H-bridge driver. It configures four pins
for PWM output and can be used to control two DC motors bidirectionally
at variable speed.
N.B. this does not implement any other timing process, it simply sets
motor PWM levels but does not apply feedback, duration, or trajectory.
"""
self.ain1 = pwmio.PWMOut(AIN1, duty_cycle=0, frequency=pwm_rate)
self.ain2 = pwmio.PWMOut(AIN2, duty_cycle=0, frequency=pwm_rate)
self.bin1 = pwmio.PWMOut(BIN1, duty_cycle=0, frequency=pwm_rate)
self.bin2 = pwmio.PWMOut(BIN2, duty_cycle=0, frequency=pwm_rate)
def write(self, channel, rate):
"""Set the speed and direction on a single motor channel.
:param int channel: 0 for motor A, 1 for motor B
:param float rate: modulation value between -1.0 and 1.0, full reverse to full forward."""
# convert the rate into a 16-bit fixed point integer
pwm = min(max(int(2**16 * abs(rate)), 0), 65535)
if channel == 0 or channel == 'A' or channel == 'a':
if rate < 0:
self.ain1.duty_cycle = pwm
self.ain2.duty_cycle = 0
else:
self.ain1.duty_cycle = 0
self.ain2.duty_cycle = pwm
else:
if rate < 0:
self.bin1.duty_cycle = pwm
self.bin2.duty_cycle = 0
else:
self.bin1.duty_cycle = 0
self.bin2.duty_cycle = pwm
def deinit(self):
"""Manage resource release as part of object lifecycle."""
self.ain1.deinit()
self.ain2.deinit()
self.bin1.deinit()
self.bin2.deinit()
self.ain1 = None
self.ain2 = None
self.bin1 = None
self.bin2 = None
def __enter__(self):
return self
def __exit__(self):
# Automatically deinitializes the hardware when exiting a context.
self.deinit()
|