Add simple two DC motor robot class and example.
This commit is contained in:
120
examples/Robot.py
Normal file
120
examples/Robot.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# Simple two DC motor robot class. Exposes a simple LOGO turtle-like API for
|
||||||
|
# moving a robot forward, backward, and turning. See RobotTest.py for an
|
||||||
|
# example of using this class.
|
||||||
|
# Author: Tony DiCola
|
||||||
|
# License: MIT License https://opensource.org/licenses/MIT
|
||||||
|
import time
|
||||||
|
import atexit
|
||||||
|
|
||||||
|
from Adafruit_MotorHAT import Adafruit_MotorHAT
|
||||||
|
|
||||||
|
|
||||||
|
class Robot(object):
|
||||||
|
def __init__(self, addr=0x60, left_id=1, right_id=2, left_trim=0, right_trim=0,
|
||||||
|
stop_at_exit=True):
|
||||||
|
"""Create an instance of the robot. Can specify the following optional
|
||||||
|
parameters:
|
||||||
|
- addr: The I2C address of the motor HAT, default is 0x60.
|
||||||
|
- left_id: The ID of the left motor, default is 1.
|
||||||
|
- right_id: The ID of the right motor, default is 2.
|
||||||
|
- left_trim: Amount to offset the speed of the left motor, can be positive
|
||||||
|
or negative and use useful for matching the speed of both
|
||||||
|
motors. Default is 0.
|
||||||
|
- right_trim: Amount to offset the speed of the right motor (see above).
|
||||||
|
- stop_at_exit: Boolean to indicate if the motors should stop on program
|
||||||
|
exit. Default is True (highly recommended to keep this
|
||||||
|
value to prevent damage to the bot on program crash!).
|
||||||
|
"""
|
||||||
|
# Initialize motor HAT and left, right motor.
|
||||||
|
self._mh = Adafruit_MotorHAT(addr)
|
||||||
|
self._left = self._mh.getMotor(left_id)
|
||||||
|
self._right = self._mh.getMotor(right_id)
|
||||||
|
self._left_trim = left_trim
|
||||||
|
self._right_trim = right_trim
|
||||||
|
# Start with motors turned off.
|
||||||
|
self._left.run(Adafruit_MotorHAT.RELEASE)
|
||||||
|
self._right.run(Adafruit_MotorHAT.RELEASE)
|
||||||
|
# Configure all motors to stop at program exit if desired.
|
||||||
|
if stop_at_exit:
|
||||||
|
atexit.register(self.stop)
|
||||||
|
|
||||||
|
def _left_speed(self, speed):
|
||||||
|
"""Set the speed of the left motor, taking into account its trim offset.
|
||||||
|
"""
|
||||||
|
assert 0 <= speed <= 255, 'Speed must be a value between 0 to 255 inclusive!'
|
||||||
|
speed += self._left_trim
|
||||||
|
speed = max(0, min(255, speed)) # Constrain speed to 0-255 after trimming.
|
||||||
|
self._left.setSpeed(speed)
|
||||||
|
|
||||||
|
def _right_speed(self, speed):
|
||||||
|
"""Set the speed of the right motor, taking into account its trim offset.
|
||||||
|
"""
|
||||||
|
assert 0 <= speed <= 255, 'Speed must be a value between 0 to 255 inclusive!'
|
||||||
|
speed += self._right_trim
|
||||||
|
speed = max(0, min(255, speed)) # Constrain speed to 0-255 after trimming.
|
||||||
|
self._right.setSpeed(speed)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop all movement."""
|
||||||
|
self._left.run(Adafruit_MotorHAT.RELEASE)
|
||||||
|
self._right.run(Adafruit_MotorHAT.RELEASE)
|
||||||
|
|
||||||
|
def forward(self, speed, seconds=None):
|
||||||
|
"""Move forward at the specified speed (0-255). Will start moving
|
||||||
|
forward and return unless a seconds value is specified, in which
|
||||||
|
case the robot will move forward for that amount of time and then stop.
|
||||||
|
"""
|
||||||
|
# Set motor speed and move both forward.
|
||||||
|
self._left_speed(speed)
|
||||||
|
self._right_speed(speed)
|
||||||
|
self._left.run(Adafruit_MotorHAT.FORWARD)
|
||||||
|
self._right.run(Adafruit_MotorHAT.FORWARD)
|
||||||
|
# If an amount of time is specified, move for that time and then stop.
|
||||||
|
if seconds is not None:
|
||||||
|
time.sleep(seconds)
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def backward(self, speed, seconds=None):
|
||||||
|
"""Move backward at the specified speed (0-255). Will start moving
|
||||||
|
backward and return unless a seconds value is specified, in which
|
||||||
|
case the robot will move backward for that amount of time and then stop.
|
||||||
|
"""
|
||||||
|
# Set motor speed and move both backward.
|
||||||
|
self._left_speed(speed)
|
||||||
|
self._right_speed(speed)
|
||||||
|
self._left.run(Adafruit_MotorHAT.BACKWARD)
|
||||||
|
self._right.run(Adafruit_MotorHAT.BACKWARD)
|
||||||
|
# If an amount of time is specified, move for that time and then stop.
|
||||||
|
if seconds is not None:
|
||||||
|
time.sleep(seconds)
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def right(self, speed, seconds=None):
|
||||||
|
"""Spin to the right at the specified speed. Will start spinning and
|
||||||
|
return unless a seconds value is specified, in which case the robot will
|
||||||
|
spin for that amount of time and then stop.
|
||||||
|
"""
|
||||||
|
# Set motor speed and move both forward.
|
||||||
|
self._left_speed(speed)
|
||||||
|
self._right_speed(speed)
|
||||||
|
self._left.run(Adafruit_MotorHAT.FORWARD)
|
||||||
|
self._right.run(Adafruit_MotorHAT.BACKWARD)
|
||||||
|
# If an amount of time is specified, move for that time and then stop.
|
||||||
|
if seconds is not None:
|
||||||
|
time.sleep(seconds)
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def left(self, speed, seconds=None):
|
||||||
|
"""Spin to the left at the specified speed. Will start spinning and
|
||||||
|
return unless a seconds value is specified, in which case the robot will
|
||||||
|
spin for that amount of time and then stop.
|
||||||
|
"""
|
||||||
|
# Set motor speed and move both forward.
|
||||||
|
self._left_speed(speed)
|
||||||
|
self._right_speed(speed)
|
||||||
|
self._left.run(Adafruit_MotorHAT.BACKWARD)
|
||||||
|
self._right.run(Adafruit_MotorHAT.FORWARD)
|
||||||
|
# If an amount of time is specified, move for that time and then stop.
|
||||||
|
if seconds is not None:
|
||||||
|
time.sleep(seconds)
|
||||||
|
self.stop()
|
||||||
65
examples/RobotTest.py
Normal file
65
examples/RobotTest.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# Simple two DC motor robot class usage example.
|
||||||
|
# Author: Tony DiCola
|
||||||
|
# License: MIT License https://opensource.org/licenses/MIT
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Import the Robot.py file (must be in the same directory as this file!).
|
||||||
|
import Robot
|
||||||
|
|
||||||
|
|
||||||
|
# Set the trim offset for each motor (left and right). This is a value that
|
||||||
|
# will offset the speed of movement of each motor in order to make them both
|
||||||
|
# move at the same desired speed. Because there's no feedback the robot doesn't
|
||||||
|
# know how fast each motor is spinning and the robot can pull to a side if one
|
||||||
|
# motor spins faster than the other motor. To determine the trim values move the
|
||||||
|
# robot forward slowly (around 100 speed) and watch if it veers to the left or
|
||||||
|
# right. If it veers left then the _right_ motor is spinning faster so try
|
||||||
|
# setting RIGHT_TRIM to a small negative value, like -5, to slow down the right
|
||||||
|
# motor. Likewise if it veers right then adjust the _left_ motor trim to a small
|
||||||
|
# negative value. Increase or decrease the trim value until the bot moves
|
||||||
|
# straight forward/backward.
|
||||||
|
LEFT_TRIM = 0
|
||||||
|
RIGHT_TRIM = 0
|
||||||
|
|
||||||
|
|
||||||
|
# Create an instance of the robot with the specified trim values.
|
||||||
|
# Not shown are other optional parameters:
|
||||||
|
# - addr: The I2C address of the motor HAT, default is 0x60.
|
||||||
|
# - left_id: The ID of the left motor, default is 1.
|
||||||
|
# - right_id: The ID of the right motor, default is 2.
|
||||||
|
robot = Robot.Robot(left_trim=LEFT_TRIM, right_trim=RIGHT_TRIM)
|
||||||
|
|
||||||
|
# Now move the robot around!
|
||||||
|
# Each call below takes two parameters:
|
||||||
|
# - speed: The speed of the movement, a value from 0-255. The higher the value
|
||||||
|
# the faster the movement. You need to start with a value around 100
|
||||||
|
# to get enough torque to move the robot.
|
||||||
|
# - time (seconds): Amount of time to perform the movement. After moving for
|
||||||
|
# this amount of seconds the robot will stop. This parameter
|
||||||
|
# is optional and if not specified the robot will start moving
|
||||||
|
# forever.
|
||||||
|
robot.forward(150, 1.0) # Move forward at speed 150 for 1 second.
|
||||||
|
robot.left(200, 0.5) # Spin left at speed 200 for 0.5 seconds.
|
||||||
|
robot.forward(150, 1.0) # Repeat the same movement 3 times below...
|
||||||
|
robot.left(200, 0.5)
|
||||||
|
robot.forward(150, 1.0)
|
||||||
|
robot.left(200, 0.5)
|
||||||
|
robot.forward(150, 1.0)
|
||||||
|
robot.right(200, 0.5)
|
||||||
|
|
||||||
|
# Spin in place slowly for a few seconds.
|
||||||
|
robot.right(100) # No time is specified so the robot will start spinning forever.
|
||||||
|
time.sleep(2.0) # Pause for a few seconds while the robot spins (you could do
|
||||||
|
# other processing here though!).
|
||||||
|
robot.stop() # Stop the robot from moving.
|
||||||
|
|
||||||
|
# Now move backwards and spin right a few times.
|
||||||
|
robot.backward(150, 1.0)
|
||||||
|
robot.right(200, 0.5)
|
||||||
|
robot.backward(150, 1.0)
|
||||||
|
robot.right(200, 0.5)
|
||||||
|
robot.backward(150, 1.0)
|
||||||
|
robot.right(200, 0.5)
|
||||||
|
robot.backward(150, 1.0)
|
||||||
|
|
||||||
|
# That's it! Note that on exit the robot will automatically stop moving.
|
||||||
2
setup.py
2
setup.py
@@ -3,7 +3,7 @@ use_setuptools()
|
|||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
setup(name = 'Adafruit_MotorHAT',
|
setup(name = 'Adafruit_MotorHAT',
|
||||||
version = '1.2.0',
|
version = '1.3.0',
|
||||||
author = 'Limor Fried',
|
author = 'Limor Fried',
|
||||||
author_email = 'support@adafruit.com',
|
author_email = 'support@adafruit.com',
|
||||||
description = 'Library for Adafruit Motor HAT',
|
description = 'Library for Adafruit Motor HAT',
|
||||||
|
|||||||
Reference in New Issue
Block a user