Motor Shield

The Motor Shield drives two DC motors from the OpenMV Cam using a TB6612FNG dual H-bridge, with an NCP1117 5 V linear regulator that powers both the camera and the motors from a single 6.5–18 V battery input.

Motor Shield

For full datasheet, photos, and ordering see the Motor Shield product page.

Highlights

  • Two independent motor channels with PWM speed control

  • Up to 2 A drive current per channel

  • Can also drive a bipolar stepper motor

  • Stacks with the Servo Shield

Pinout

Motor Shield Pinout

Pin reference

Pin

Function

P0

DIR B1 (motor B direction)

P1

DIR B0 (motor B direction)

P2

DIR A1 (motor A direction)

P3

DIR A0 (motor A direction)

P6

TB6612FNG STANDBY — defaults on; pull low to enter low-power mode

P7

PWM speed input for motor A

P8

PWM speed input for motor B

VBAT in

6.5–18 V battery input on the screw terminal (NCP1117 limits)

VIN out

5 V from the on-board NCP1117 regulator (powers the camera)

3.3V rail

Powers the TB6612FNG logic

GND rail

Common ground

Note

P6 drives the TB6612 STANDBY input by default. Cut the solder trace on the back of the shield to disconnect P6 if you’d rather use the pin for something else (the driver then stays enabled).

Note

The TB6612FNG drives each motor through a two-input truth table plus a PWM enable. For motor A (with STBY high and PWMA at any non-zero duty):

  • (P3, P2) = (H, L) → forward

  • (P3, P2) = (L, H) → reverse

  • (P3, P2) = (L, L) → coast (outputs Hi-Z)

  • (P3, P2) = (H, H) → brake (outputs both low)

Driving PWMA low forces a short brake regardless of the direction inputs — a 0 % duty cycle brakes the motor. Motor B follows the same table on (P1, P0) with PWM on P8.

Usage

Cycle motor A through forward → brake → reverse → coast on a fixed PWM duty:

from machine import Pin, PWM
import time

a0 = Pin("P3", Pin.OUT)  # AIN1
a1 = Pin("P2", Pin.OUT)  # AIN2
pwma = PWM(Pin("P7"), freq=1_000, duty_u16=40_000)  # ~60%


def drive(in1, in2):
    a0.value(in1)
    a1.value(in2)


while True:
    drive(1, 0)         # forward
    time.sleep(2)
    drive(1, 1)         # brake
    time.sleep_ms(500)
    drive(0, 1)         # reverse
    time.sleep(2)
    drive(0, 0)         # coast
    time.sleep_ms(500)

For variable-speed control, hold the direction inputs constant and ramp PWMA. The loop below ramps motor A from coast up to full forward and back down:

from machine import Pin, PWM
import time

Pin("P3", Pin.OUT, value=1)  # AIN1=H
Pin("P2", Pin.OUT, value=0)  # AIN2=L → forward direction
pwma = PWM(Pin("P7"), freq=1_000, duty_u16=0)

while True:
    for duty in range(0, 65_536, 1024):
        pwma.duty_u16(duty)
        time.sleep_ms(10)
    for duty in range(65_535, -1, -1024):
        pwma.duty_u16(duty)
        time.sleep_ms(10)

The TB6612’s two H-bridges can also wave-drive a bipolar stepper — energize one coil at a time, walking through four phases. Hold both PWM channels at the desired drive current and call step() to advance one full sequence in either direction:

from machine import Pin, PWM
import time

a0 = Pin("P3", Pin.OUT)
a1 = Pin("P2", Pin.OUT)
b0 = Pin("P1", Pin.OUT)
b1 = Pin("P0", Pin.OUT)
PWM(Pin("P7"), freq=1_000, duty_u16=32_768)  # 50% drive on A
PWM(Pin("P8"), freq=1_000, duty_u16=32_768)  # 50% drive on B

SEQUENCE = [(1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0), (0, 0, 0, 1)]


def step(forward=True):
    for s in SEQUENCE if forward else reversed(SEQUENCE):
        a0.value(s[0])
        a1.value(s[1])
        b0.value(s[2])
        b1.value(s[3])
        time.sleep_ms(5)


while True:
    for _ in range(50):  # ~1 revolution forward (200 phases)
        step()
    for _ in range(50):  # ~1 revolution backward
        step(forward=False)

The on-board STANDBY line defaults high (driver enabled). Pull P6 low to put the TB6612 to sleep:

from machine import Pin
Pin("P6", Pin.OUT).value(0)  # standby