diff --git a/examples/Robot.py b/examples/Robot.py new file mode 100644 index 0000000..1d61d04 --- /dev/null +++ b/examples/Robot.py @@ -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() diff --git a/examples/RobotTest.py b/examples/RobotTest.py new file mode 100644 index 0000000..86454bb --- /dev/null +++ b/examples/RobotTest.py @@ -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. diff --git a/setup.py b/setup.py index 443295b..4cf76bb 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ use_setuptools() from setuptools import setup, find_packages setup(name = 'Adafruit_MotorHAT', - version = '1.2.0', + version = '1.3.0', author = 'Limor Fried', author_email = 'support@adafruit.com', description = 'Library for Adafruit Motor HAT',