-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added dual motor examples, and fixed some things
- Loading branch information
1 parent
04b5863
commit 80d694a
Showing
9 changed files
with
297 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import math | ||
from pimoroni_yukon import Yukon | ||
from pimoroni_yukon.modules import DualMotorModule | ||
from pimoroni_yukon.timing import ticks_ms, ticks_add | ||
from pimoroni_yukon.logging import LOG_WARN | ||
from motor import MotorCluster | ||
|
||
""" | ||
How to drive up to 12 motors from a set of Dual Motor Modules connected to Slots, using a MotorCluster. | ||
A wave pattern will be played on the attached motors. | ||
The MotorCluster controls the whole set of motors using PIO. | ||
It also staggers the updates of each motor to reduce peak current draw. | ||
""" | ||
|
||
# Constants | ||
SPEED = 0.005 # How much to advance the motor phase offset by each update | ||
UPDATES = 50 # How many times to update the motors per second | ||
SPEED_EXTENT = 1.0 # How far from zero to drive the motors | ||
CURRENT_LIMIT = 0.5 # The maximum current (in amps) the motors will be driven with | ||
CLUSTER_PIO = 0 # The PIO system to use (0 or 1) to drive the motor cluster | ||
CLUSTER_SM = 0 # The State Machines (SM) to use to drive the motor cluster | ||
|
||
# Variables | ||
yukon = Yukon(logging_level=LOG_WARN) # Create a new Yukon object, with its logging level lowered | ||
modules = [] # A list to store QuadServo module objects created later | ||
phase_offset = 0 # The offset used to animate the motors | ||
|
||
|
||
# Function to get a motor speed from its index | ||
def speed_from_index(index, offset=0.0): | ||
phase = ((index / DualMotorModule.NUM_MOTORS) + offset) * math.pi * 2 | ||
speed = math.sin(phase) * SPEED_EXTENT | ||
return speed | ||
|
||
|
||
# Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt) | ||
try: | ||
# Find out which slots of Yukon have DualMotorModule attached | ||
for slot in yukon.find_slots_with(DualMotorModule): | ||
module = DualMotorModule(init_motors=False) # Create a DualMotorModule object | ||
yukon.register_with_slot(module, slot) # Register the DualMotorModule object with the slot | ||
modules.append(module) # Add the object to the module list | ||
|
||
# Record the number of motors that will be driven | ||
NUM_MOTORS = len(modules) * DualMotorModule.NUM_MOTORS | ||
print(f"Up to {NUM_MOTORS} motors available") | ||
|
||
yukon.verify_and_initialise() # Verify that DualMotorModules are attached to Yukon, and initialise them | ||
|
||
# Create a MotorCluster object, with a list of motor pin pairs to control. | ||
# The pin list is created using nested list comprehension | ||
motors = MotorCluster(CLUSTER_PIO, CLUSTER_SM, | ||
pins=[pin for module in modules for pin in module.motor_pins]) | ||
|
||
yukon.enable_main_output() # Turn on power to the module slots | ||
|
||
for module in modules: | ||
module.current_limit(CURRENT_LIMIT) # Change the current limit (in amps) of the motor driver | ||
module.enable() # Enable the motor driver on the DualMotorModule | ||
|
||
current_time = ticks_ms() # Record the start time of the program loop | ||
|
||
# Loop until the BOOT/USER button is pressed | ||
while not yukon.is_boot_pressed(): | ||
|
||
# Give all the motors new speeds | ||
for current_motor in range(motors.count()): | ||
speed = speed_from_index(current_motor, phase_offset) | ||
motors.speed(current_motor, speed) | ||
|
||
# Advance the phase offset, wrapping if it exceeds 1.0 | ||
phase_offset += SPEED | ||
if phase_offset >= 1.0: | ||
phase_offset -= 1.0 | ||
|
||
print(f"Phase = {phase_offset}") | ||
|
||
# Advance the current time by a number of seconds | ||
current_time = ticks_add(current_time, int(1000 / UPDATES)) | ||
|
||
# Monitor sensors until the current time is reached, recording the min, max, and average for each | ||
# This approach accounts for the updating of the rainbows taking a non-zero amount of time to complete | ||
yukon.monitor_until_ms(current_time) | ||
|
||
finally: | ||
# Put the board back into a safe state, regardless of how the program may have ended | ||
yukon.reset() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import math | ||
from pimoroni_yukon import Yukon | ||
from pimoroni_yukon.modules import DualMotorModule | ||
from pimoroni_yukon.timing import ticks_ms, ticks_add | ||
from pimoroni_yukon.logging import LOG_WARN | ||
|
||
""" | ||
How to drive up to 8 motors from a set of Dual Motor Module connected to Slots. | ||
A wave pattern will be played on the attached motors. | ||
To use more motors, look at the all_motors.py example. | ||
""" | ||
|
||
# Constants | ||
SPEED = 0.005 # How much to advance the motor phase offset by each update | ||
UPDATES = 50 # How many times to update the motors per second | ||
SPEED_EXTENT = 1.0 # How far from zero to drive the motors | ||
CURRENT_LIMIT = 0.5 # The maximum current (in amps) the motors will be driven with | ||
|
||
# Variables | ||
yukon = Yukon(logging_level=LOG_WARN) # Create a new Yukon object, with its logging level lowered | ||
modules = [] # A list to store DualMotorModule objects created later | ||
phase_offset = 0 # The offset used to animate the motors | ||
|
||
|
||
# Function to get a motor speed from its index | ||
def speed_from_index(index, offset=0.0): | ||
phase = ((index / DualMotorModule.NUM_MOTORS) + offset) * math.pi * 2 | ||
speed = math.sin(phase) * SPEED_EXTENT | ||
return speed | ||
|
||
|
||
# Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt) | ||
try: | ||
# Find out which slots of Yukon have DualMotorModule attached | ||
for slot in yukon.find_slots_with(DualMotorModule): | ||
module = DualMotorModule() # Create a DualMotorModule object | ||
yukon.register_with_slot(module, slot) # Register the DualMotorModule object with the slot | ||
modules.append(module) # Add the object to the module list | ||
|
||
# Record the number of motors that will be driven | ||
NUM_MOTORS = len(modules) * DualMotorModule.NUM_MOTORS | ||
print(f"Up to {NUM_MOTORS} motors available") | ||
|
||
yukon.verify_and_initialise() # Verify that DualMotorModules are attached to Yukon, and initialise them | ||
yukon.enable_main_output() # Turn on power to the module slots | ||
|
||
for module in modules: | ||
module.current_limit(CURRENT_LIMIT) # Change the current limit (in amps) of the motor driver | ||
module.enable() # Enable the motor driver on the DualMotorModule | ||
|
||
current_time = ticks_ms() # Record the start time of the program loop | ||
|
||
# Loop until the BOOT/USER button is pressed | ||
while not yukon.is_boot_pressed(): | ||
|
||
# Give all the motors new speeds | ||
current_motor = 0 | ||
for module in modules: | ||
for motor in module.motors: | ||
speed = speed_from_index(current_motor, phase_offset) | ||
motor.speed(speed) | ||
current_motor += 1 | ||
|
||
# Advance the phase offset, wrapping if it exceeds 1.0 | ||
phase_offset += SPEED | ||
if phase_offset >= 1.0: | ||
phase_offset -= 1.0 | ||
|
||
print(f"Phase = {phase_offset}") | ||
|
||
# Advance the current time by a number of seconds | ||
current_time = ticks_add(current_time, int(1000 / UPDATES)) | ||
|
||
# Monitor sensors until the current time is reached, recording the min, max, and average for each | ||
# This approach accounts for the updating of the rainbows taking a non-zero amount of time to complete | ||
yukon.monitor_until_ms(current_time) | ||
|
||
finally: | ||
# Put the board back into a safe state, regardless of how the program may have ended | ||
yukon.reset() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import math | ||
from pimoroni_yukon import Yukon | ||
from pimoroni_yukon import SLOT1 as SLOT | ||
from pimoroni_yukon.modules import DualMotorModule | ||
from pimoroni_yukon.timing import ticks_ms, ticks_add | ||
from pimoroni_yukon.logging import LOG_WARN | ||
|
||
""" | ||
How to drive up to 2 motors from a Dual Motor Module connected to Slot1. | ||
A wave pattern will be played on the attached motors. | ||
""" | ||
|
||
# Constants | ||
SPEED = 0.005 # How much to advance the motor phase offset by each update | ||
UPDATES = 50 # How many times to update the motors per second | ||
SPEED_EXTENT = 1.0 # How far from zero to drive the motors | ||
CURRENT_LIMIT = 0.5 # The maximum current (in amps) the motors will be driven with | ||
|
||
# Variables | ||
yukon = Yukon(logging_level=LOG_WARN) # Create a new Yukon object, with its logging level lowered | ||
module = DualMotorModule() # Create a DualMotorModule object | ||
phase_offset = 0 # The offset used to animate the motors | ||
|
||
|
||
# Function to get a motor speed from its index | ||
def speed_from_index(index, offset=0.0): | ||
phase = ((index / DualMotorModule.NUM_MOTORS) + offset) * math.pi * 2 | ||
speed = math.sin(phase) * SPEED_EXTENT | ||
return speed | ||
|
||
|
||
# Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt) | ||
try: | ||
yukon.register_with_slot(module, SLOT) # Register the DualMotorModule object with the slot | ||
yukon.verify_and_initialise() # Verify that a DualMotorModule is attached to Yukon, and initialise it | ||
yukon.enable_main_output() # Turn on power to the module slots | ||
|
||
module.current_limit(CURRENT_LIMIT) # Change the current limit (in amps) of the motor driver | ||
module.enable() # Enable the motor driver on the DualMotorModule | ||
|
||
current_time = ticks_ms() # Record the start time of the program loop | ||
|
||
# Loop until the BOOT/USER button is pressed | ||
while not yukon.is_boot_pressed(): | ||
|
||
# Give all the motors new speeds | ||
current_motor = 0 | ||
for motor in module.motors: | ||
speed = speed_from_index(current_motor, phase_offset) | ||
motor.speed(speed) | ||
current_motor += 1 | ||
|
||
# Advance the phase offset, wrapping if it exceeds 1.0 | ||
phase_offset += SPEED | ||
if phase_offset >= 1.0: | ||
phase_offset -= 1.0 | ||
|
||
print(f"Phase = {phase_offset}") | ||
|
||
# Advance the current time by a number of seconds | ||
current_time = ticks_add(current_time, int(1000 / UPDATES)) | ||
|
||
# Monitor sensors until the current time is reached, recording the min, max, and average for each | ||
# This approach accounts for the updating of the rainbows taking a non-zero amount of time to complete | ||
yukon.monitor_until_ms(current_time) | ||
|
||
finally: | ||
# Put the board back into a safe state, regardless of how the program may have ended | ||
yukon.reset() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.