The following CircuitPython code examples will sweep an attached motor's duty cycle from 0% to 100% in 2% increments in one direction. Each step of the duty cycle will hold for 1 second. The motor stops at the end of the code. During execution, the code prints the duty cycle as a throttle value for display in the REPL's Serial and Plotter windows. 

The first portion of each example imports the needed libraries and instantiates the motor controller with a new PWM frequency. Change the frequency value to select the one that works best for the attached motor.

Each motor controller is implemented differently, so refer to the example's code description to change the controller's frequency. The examples describe the frequency setting techniques when using:

  • Crickit FeatherWing and Crickit for Circuit Playground Express
  • Motor FeatherWing and Motor Shield
  • Breakout Boards and H-Bridge Chips

Crickit FeatherWing and Crickit for Circuit Playground Express

Upon initiation, the Crickit library sets the DC motor PWM frequency to 50Hz, useful for most brushed DC motors like the Yellow TT motor. It is possible to override the default if a custom PWM frequency is needed while still preserving the ability to use the Crickit library's motor statements such as motor.throttle.

The Crickit library also initially sets the controller's decay mode to FAST_DECAY. We'll change the decay mode to SLOW_DECAY to take advantage of the resultant performance improvement.

The Crickit uses two internal GPIO pins for each of the two DC motor controllers. The internal pins reserved for the motor controllers are 18, 19, 22, and 23. This is the section of the example code that changes the PWM to a custom value:

PWM_FREQ = 25  # Custom PWM frequency; Crickit min/max 3Hz/720Hz, default is 50Hz
DECAY_MODE = motor.SLOW_DECAY  # Set controller to Slow Decay (braking) mode
THROTTLE_HOLD = 1  # Hold the throttle (seconds)

motor1 = crickit.dc_motor_1
motor2 = crickit.dc_motor_2

motor1.decay_mode = DECAY_MODE
motor2.decay_mode = DECAY_MODE

ss = crickit.seesaw  # To access Seesaw motor pins
ss.set_pwm_freq(22, PWM_FREQ)  # Set motor1A pin to custom PWM frequency
ss.set_pwm_freq(23, PWM_FREQ)  # Set motor1B pin to custom PWM frequency
ss.set_pwm_freq(19, PWM_FREQ)  # Set motor2A pin to custom PWM frequency
ss.set_pwm_freq(18, PWM_FREQ)  # Set motor2B pin to custom PWM frequency

Line 1 defines the constant used for the custom PWM frequency value, followed by a constant that defines the controller's decay mode. A throttle holding constant (THROTTLE_HOLD) of 1 second is used later in the example code. The next lines define names for the two Crickit motor controllers. Defining the names also instantiates the motor pin definitions that will be changed.

In lines 8 and 9, the decay mode is set for each motor instance using the decay mode constant defined earlier. Next we'll access each motor controller pin individually and reset the default PWM frequency. For example, the first pin of DC_Motor_1's controller is updated in line 12:

ss.set_pwm_freq(22, PWM_FREQ)

The PWM frequency of each pin is then set to the custom value stored in the PWM_FREQ constant.

Example code for the Crickit FeatherWing and Circuit Playground Express Crickit:

# SPDX-FileCopyrightText: 2021 Jan Goolsbey for Adafruit Industries
# SPDX-License-Identifier: MIT

# Crickit PWM Frequency Example
# for Adafruit Crickit FeatherWing (#3343)
# and Circuit Playground Express Crickit(#3093)

import time
from adafruit_motor import motor
from adafruit_crickit import crickit

PWM_FREQ = 25  # Custom PWM frequency; Crickit min/max 3Hz/720Hz, default is 50Hz
DECAY_MODE = motor.SLOW_DECAY  # Set controller to Slow Decay (braking) mode
THROTTLE_HOLD = 1  # Hold the throttle (seconds)

motor1 = crickit.dc_motor_1
motor2 = crickit.dc_motor_2

motor1.decay_mode = DECAY_MODE
motor2.decay_mode = DECAY_MODE

ss = crickit.seesaw  # To access Seesaw motor pins
ss.set_pwm_freq(22, PWM_FREQ)  # Set motor1A pin to custom PWM frequency
ss.set_pwm_freq(23, PWM_FREQ)  # Set motor1B pin to custom PWM frequency
ss.set_pwm_freq(19, PWM_FREQ)  # Set motor2A pin to custom PWM frequency
ss.set_pwm_freq(18, PWM_FREQ)  # Set motor2B pin to custom PWM frequency
print("PWM frequency:", PWM_FREQ)  # Display internal PWM frequency

motor1.throttle = 0  # Stop motor1
motor2.throttle = 0  # Stop motor2
print((0,))  # Plot/print current throttle value
time.sleep(THROTTLE_HOLD)  # Hold at current throttle value

# Sweep up through 50 duty cycle values
for duty_cycle in range(0, 101, 2):
    throttle = duty_cycle / 100  # Convert to throttle value (0 to 1.0)
    motor1.throttle = throttle
    motor2.throttle = throttle
    print((throttle,))  # Plot/print current throttle value
    time.sleep(THROTTLE_HOLD)  # Hold at current throttle value

motor1.throttle = 0  # Stop motor1
motor2.throttle = 0  # Stop motor2
print((0,))  # Plot/print current throttle value
time.sleep(THROTTLE_HOLD)  # Hold at current throttle value

Motor FeatherWing and MotorShield

Upon instantiation, the adafruit_motorkit MotorKit class sets the DC motor PWM frequency to a default of 1600Hz and the controller's decay mode to FAST_DECAY. Changing the frequency and decay mode to a custom value is accomplished using a MotorKit parameter after instantiation.

PWM_FREQ = 25  # Custom PWM frequency; MotorKit min/maz 24Hz/2100Hz, default is 1600Hz
DECAY_MODE = motor.SLOW_DECAY  # Set controller to Slow Decay (braking) mode
THROTTLE_HOLD = 1  # Hold the throttle (seconds)

# Instantiate motor controller wing
motorwing = MotorKit(i2c=board.I2C(), address=0x60)
motorwing.frequency = PWM_FREQ  # Set custom PWM frequency
print("PWM frequency:", motorwing.frequency)  # Verify internal PWM frequency
motor1 = motorwing.motor1
motor1.decay_mode = DECAY_MODE

The first line defines the constant used for the custom PWM frequency value. A constant value for the decay mode is defined as SLOW_DECAY, followed by a throttle holding constant (THROTTLE_HOLD) that's used later in the example code. Line 6 is the typical statement used to instantiate the Motor FeatherWing or Shield. Line 7 updates the MotorKit PWM frequency parameter with the custom value stored in the PWM_FREQ constant.

After the motor is instantiated in line 9, the controller's decay mode is set to SLOW_DECAY.

Example code for Motor FeatherWing and MotorShield:

# SPDX-FileCopyrightText: 2021 Jan Goolsbey for Adafruit Industries
# SPDX-License-Identifier: MIT

# Motor FeatherWing PWM Frequency Example
# for Adafruit Motor FeatherWing (#3243) and Motor Shield (#1438)

import time
import board
from adafruit_motor import motor
from adafruit_motorkit import MotorKit

PWM_FREQ = 25  # Custom PWM frequency; MotorKit min/maz 24Hz/2100Hz, default is 1600Hz
DECAY_MODE = motor.SLOW_DECAY  # Set controller to Slow Decay (braking) mode
THROTTLE_HOLD = 1  # Hold the throttle (seconds)

# Instantiate motor controller wing
motorwing = MotorKit(i2c=board.I2C(), address=0x60)
motorwing.frequency = PWM_FREQ  # Set custom PWM frequency
print("PWM frequency:", motorwing.frequency)  # Verify internal PWM frequency
motor1 = motorwing.motor1
motor1.decay_mode = DECAY_MODE

motor1.throttle = 0  # Stop motor1
print((0,))  # Plot/print current throttle value
time.sleep(THROTTLE_HOLD)  # Hold at current throttle value

# Sweep up through 50 duty cycle values
for duty_cycle in range(0, 101, 2):
    throttle = duty_cycle / 100  # Convert to throttle value (0 to 1.0)
    motor1.throttle = throttle
    print((throttle,))  # Plot/print current throttle value
    time.sleep(THROTTLE_HOLD)  # Hold at current throttle value

motor1.throttle = 0  # Stop motor1
print((0,))  # Plot/print current throttle value
time.sleep(THROTTLE_HOLD)  # Hold at current throttle value

Breakout Boards and H-Bridge Chips

The adafruit_motor library's DCMotor class is the one to use with Adafruit motor controller breakout boards and H-bridge integrated circuits. Upon instantiation, the library works with the pwmio.PWMOut class to define which GPIO pins to use to drive the motor, set the 500Hz default PWM frequency and FAST_DECAY controller mode. We'll change the default frequency when the GPIO pins are defined and will change the controller's decay mode to SLOW_DECAY.

Refer to your selected breakout board's or H-bridge chip's learning guide for how to properly connect it to a microcontroller.

PWM_FREQ = 25  # Custom PWM frequency in Hz; PWMOut min/max 1Hz/50kHz, default is 500Hz
DECAY_MODE = motor.SLOW_DECAY  # Set controller to Slow Decay (braking) mode
THROTTLE_HOLD = 1  # Hold the throttle (seconds)

# DC motor setup; Set pins to custom PWM frequency
pwm_a = pwmio.PWMOut(PWM_PIN_A, frequency=PWM_FREQ)
pwm_b = pwmio.PWMOut(PWM_PIN_B, frequency=PWM_FREQ)
motor1 = motor.DCMotor(pwm_a, pwm_b)
motor1.decay_mode = DECAY_MODE

The first line defines the constant used for the custom PWM frequency value. Next, a constant value for the controller's mode is defined as SLOW_DECAY, followed by a throttle holding constant (THROTTLE_HOLD) that's used later in the example code. The two GPIO pins needed for the motor controller are defined next. Choose two pins that have their own unused PWM channel.

Lines 6 and 7 use pwmio.PWMOut to establish the pins and set the custom PWM frequency. After the motor is instantiated as motor1 in line 8, the controller's decay mode is set to SLOW_DECAY.

Example code for breakout motor controller boards:

# SPDX-FileCopyrightText: 2021 Jan Goolsbey for Adafruit Industries
# SPDX-License-Identifier: MIT

# Breakout PWM Frequency Example
# for Adafruit motor controller breakout boards and H-bridge drivers
# TB6612 (#2448), DRV8833 (#3297), DRV8871 (#3190), L9110 (#4489), L293D (#807)

import time
import board
import pwmio
from adafruit_motor import motor

PWM_PIN_A = board.D5  # Pick two PWM pins on their own channels
PWM_PIN_B = board.D6
PWM_FREQ = 25  # Custom PWM frequency in Hz; PWMOut min/max 1Hz/50kHz, default is 500Hz
DECAY_MODE = motor.SLOW_DECAY  # Set controller to Slow Decay (braking) mode
THROTTLE_HOLD = 1  # Hold the throttle (seconds)

# DC motor setup; Set pins to custom PWM frequency
pwm_a = pwmio.PWMOut(PWM_PIN_A, frequency=PWM_FREQ)
pwm_b = pwmio.PWMOut(PWM_PIN_B, frequency=PWM_FREQ)
motor1 = motor.DCMotor(pwm_a, pwm_b)
motor1.decay_mode = DECAY_MODE

motor1.throttle = 0  # Stop motor1
print((0,))  # Plot/print current throttle value

# Sweep up through 50 duty cycle values
for duty_cycle in range(0, 101, 2):
    throttle = duty_cycle / 100  # Convert to throttle value (0 to 1.0)
    motor1.throttle = throttle
    print((throttle,))  # Plot/print current throttle value
    time.sleep(1)  # Hold at current throttle value

motor1.throttle = 0  # Stop motor1
print((0,))  # Plot/print current throttle value

This guide was first published on Feb 23, 2021. It was last updated on Mar 08, 2024.

This page (CircuitPython Code Examples) was last updated on Mar 08, 2024.

Text editor powered by tinymce.