Note

To minimize the margin of error during these tests, we suggest connecting each motor pin (specified in the example codes) to its own resistor and LED (in series). By doing so, you can distinguish between pinout errors and faulty motor driver ICs more easily (not to mention doing away with the motors’ isolated power requirements).

BiMotor test

examples/bimotor_test.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
A simple test of the BiMotor class

This iterates through a list of motor commands
and prints the ellapsed time taken to acheive each command
"""
# pylint: disable=invalid-name
import time
import board
from drivetrain import BiMotor

motor = BiMotor([board.D22, board.D13], ramp_time=2000)
Value = [-25, 25, -100, 100, 0]
for test in Value:
    # send input instructions
    # NOTE we convert the percentage value to range [-65535, 65535]
    motor.cellerate(test * 655.35)
    start = time.monotonic()
    t = start
    # do a no delay wait for at most 3 seconds
    while motor.is_cellerating and t < start + 3:
        t = time.monotonic()
    print('test result {} took {} seconds'.format(motor.value, t - start))

PhasedMotor test

examples/phasedmotor_test.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
A simple test of the PhasedMotor class

This iterates through a list of motor commands
and prints the ellapsed time taken to acheive each command
"""
# pylint: disable=invalid-name
import time
import board
from drivetrain.motor import PhasedMotor

motor = PhasedMotor([board.D17, board.D18], ramp_time=2000)
Value = [-25, 25, -100, 100, 0]
for test in Value:
    # send input instructions
    # NOTE we convert the percentage value to range [-65535, 65535]
    motor.cellerate(test * 655.35)
    start = time.monotonic()
    t = start
    # do a no delay wait for at most 3 seconds
    while motor.is_cellerating and t < start + 3:
        t = time.monotonic()
    print('test result {} took {} seconds'.format(motor.value, t - start))

StepperMotor test

examples/steppermotor_test.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
"""A simple test of the StepperMotor class driving a 5V microstepper"""
# pylint: disable=invalid-name
import time
import board
from drivetrain.stepper import StepperMotor

motor = StepperMotor([board.D13, board.D12, board.D11, board.D10])
Steps = [-256, 256, 0] # 1024, 2048, 4096]
Angle = [-15, 15, 0] # 180, 360]
Value = [-25, 25, 0] # -50, 100, 0]
for test in Value:
    motor.value = test # send input instructions
    # do a no delay wait for at least 2 seconds
    start = time.monotonic()
    t = start
    end = None
    while motor.is_cellerating or t < start + 2:
        t = time.monotonic()
        if not motor.is_cellerating and end is None:
            end = t
            print(repr(motor))
            print('value acheived in', end-start, 'seconds')
        # elif motor.is_cellerating:
        #     print(repr(motor))

Tank Drivetrain test

examples/tank_test.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
"""
A simple test of the Tank drivetrain class.

This iterates through a list of drivetrain commands
and tallies up the ellapsed time taken to acheive each set of commands
as well as the ellapsed time taken for each motor to acheive each individual command
"""
# pylint: disable=invalid-name
import time
import board
from drivetrain.drivetrain import Tank, BiMotor

mymotors = [BiMotor([board.D22, board.D13], ramp_time=2000),
            BiMotor([board.D17, board.D18], ramp_time=2000)]
d = Tank(mymotors)
testInput = [[100, 0],
             [-100, 0],
             [0, 0],
             [0, 100],
             [0, -100],
             [0, 0]]
for test in testInput:
    # use the list `end` to keep track of each motor's ellapsed time
    end = []
    # NOTE we convert a percentage to range of an 32 bit int
    for i, t_val in enumerate(test):
        test[i] = t_val * 655.35
    for m in mymotors:
        # end timer for motor[i] = end[i]
        end.append(None)
    d.go(test)  # send input commands
    # unanimous start of all timmers
    start = time.monotonic()
    t = start
    # do a no delay wait for at least 3 seconds
    while d.is_cellerating or t < start + 3:
        t = time.monotonic()
        for j, m in enumerate(mymotors):
            if not m.is_cellerating and end[j] is None:
                end[j] = t

    print('test commands {} took {} seconds'.format(repr(test), t - start))
    for j, m in enumerate(mymotors):
        if end[j] is not None:
            print('motor {} acheived {} in {} seconds'.format(j, m.value, end[j]-start))
        else:
            print("motor {} didn't finish cellerating and a has value of {}".format(j, m.value))
    print(' ') # for clearer print statement grouping

Automotive Drivetrain test

examples/automotive_test.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
"""
A simple test of the Automotive drivetrain class.

This iterates through a list of drivetrain commands
and tallies up the ellapsed time taken to acheive each set of commands
as well as the ellapsed time taken for each motor to acheive each individual command
"""
# pylint: disable=invalid-name
import time
import board
from drivetrain.drivetrain import Automotive, PhasedMotor

mymotors = [PhasedMotor([board.D22, board.D13], ramp_time=2000),
            PhasedMotor([board.D17, board.D18], ramp_time=2000)]
d = Automotive(mymotors)
testInput = [[100, 0],
             [-100, 0],
             [0, 0],
             [0, 100],
             [0, -100],
             [0, 0]]
for test in testInput:
    # use the list `end` to keep track of each motor's ellapsed time
    end = []
    # NOTE we convert a percentage to range of an 32 bit int
    for i, t_val in enumerate(test):
        test[i] = t_val * 655.35
    for m in mymotors:
        # end timer for motor[i] = end[i]
        end.append(None)
    d.go(test)  # send input commands
    # unanimous start of all timmers
    start = time.monotonic()
    t = start
    # do a no delay wait for at least 3 seconds
    while d.is_cellerating or t < start + 3:
        t = time.monotonic()
        for j, m in enumerate(mymotors):
            if not m.is_cellerating and end[j] is None:
                end[j] = t

    print('test commands {} took {} seconds'.format(repr(test), t - start))
    for j, m in enumerate(mymotors):
        if end[j] is not None:
            print('motor {} acheived {} in {} seconds'.format(j, m.value, end[j]-start))
        else:
            print("motor {} didn't finish cellerating and a has value of {}".format(j, m.value))
    print(' ') # for clearer print statement grouping

nRF24L01 receiving test

examples/nrf24l01_rx_test.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
"""
Example of library usage receiving commands via an
nRF24L01 transceiver to control a Mecanum drivetrain.
"""
import board
from digitalio import DigitalInOut as Dio
from circuitpython_nrf24l01 import RF24
from drivetrain import Mecanum, BiMotor, NRF24L01rx

# instantiate transceiver radio on the SPI bus
nrf = RF24(board.SPI(), Dio(board.D5), Dio(board.D4))

# instantiate motors for a Mecanum drivetrain in the following order
# Front-Right, Rear-Right, Rear-Left, Front-Left
motors = [
    BiMotor([board.RX, board.TX]),
    BiMotor([board.D13, board.D12]),
    BiMotor([board.D11, board.D10]),
    BiMotor([board.D2, board.D7])
    ]
# NOTE there are no more PWM pins available

# instantiate receiving object for a Mecanum drivetrain
d = NRF24L01rx(nrf, Mecanum(motors))

while True: # this runs forever
    d.sync()
# doing a keyboard interupt will most likely leave the SPI bus in an
# undesirable state. You must do a hard-reset of the circuitoython MCU to
# reset the SPI bus for continued use. This code assumes power is lost on exit.