4.2. turtleplotbot module¶
4.2.1. Hardware¶
The TurtlePlotBot uses an ESP32 Microcontroller module and a Esp32 DrawBot Board to run a pair of 28BYJ-48 stepper motors. The stepper motors are driven by a UNL2803A Darlington transistor array. The UNL2803A is connected to a MCP23017 i2c 16-bit port expander to run the stepper motors and provide an additional 8-bit I/O port.
4.2.2. Interface functions¶
The turtleplotbot module contains the TurtlePlotBot class used to provide the hardware interface needed by the turtlebot module to run the robot using an ESP32 Microcontroller device and a Esp32 DrawBot Board.
User programs use the functions inherited from the TurtlePlot class for moving and drawing.
-
class
turtleplotbot.
TurtlePlotBot
(scl=22, sda=21)¶ Initialize the TurtlePlotBot
- Parameters
i2c (machine.I2C) – The I2C peripheral to use.
to creating a device using the pins (Defaults) –
in _SCL_PIN and _SDA_PIN. (defined) –
-
_movesteppers
(left, right)¶ Internal routine to step steppers
Note
Both steppers always move the same distance, but not always in the same direction. De-energizes the stepper coils after moving to save power.
- Parameters
left (float or integer) – millimeters to move left stepper
right (float or integer) – millimeters to move right stepper
-
_turn
(angle)¶ Turn TurtlePlotBot left angle degrees
- Parameters
angle (integer or float) – turn left degrees
This Method overrides the TurtlePlotBot method
-
_move
(distance)¶ Move the TurtlePlotBot distance millimeters
- Parameters
distance (integer or float) –
This Method overrides the TurtlePlotBot method
-
_pen
(down)¶ lower or raise the pen
- Parameters
down (boolean) –
This Method overrides the TurtlePlotBot method
-
done
()¶ Raise pen and turn off the stepper motors.
4.2.3. turtleplotbot implementation¶
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | """
.. module:: turtleplotbot
:synopsis: functions to control the ESP-32 based TurtlePlotBot
TurtlePlotBot Class Functions
============================
The `turtleplotbot` module contains the `TurtlePlotBot` class used to provide the
hardware interface needed by the `turtleplotbot` module to run a
`TurtlePlotBot` using an ESP-32 device and a |esp32bot|.
.. topic::Library Dependencies
`micropython-servo
<https://bitbucket.org/thesheep/micropython-servo/src/default/>`_
by `Radomir Dopieralski
<https://bitbucket.org/%7Bb0f7a17e-f9c6-4d4d-ad93-a016dd5a2f8d%7D/>`_
`MicroPython ssd1306 display driver
<https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py>`_
"""
#pylint: disable-msg=import-error
import time
from math import pi
import machine
import mcp23017
from servo import Servo
from turtleplot import TurtlePlot
#pylint: disable-msg=invalid-name
const = lambda x: x
#pylint: disable-msg=bad-whitespace
_I2C_ADDR = const(0x20) # MCP23008 i2c address
_SCL_PIN = const(22) # i2c SCL Pin
_SDA_PIN = const(21) # i2c SDA Pin
_SERVO_PIN = const(13) # Servo control pin
_PEN_UP_ANGLE = const(90) # servo angle for pen up
_PEN_DOWN_ANGLE = const(180) # servo angle for pen down
_STEPS_PER_REV = const(4076) # stepper steps per revolution
_WHEEL_DIAMETER = 64.5 # in mm (increase = spiral out)
_WHEELBASE = 112.5 # in mm (increase = spiral in)
_LEFT_MOTOR = const(0) # left motor index
_RIGHT_MOTOR = const(1) # right motor index
_WHEEL_BPI = _WHEELBASE * pi
_STEPS_PER_MM = _STEPS_PER_REV / (_WHEEL_DIAMETER * pi)
_MOTORS = (_LEFT_MOTOR, _RIGHT_MOTOR)
_STEP_MASKS = (
0b1000, 0b1100, 0b0100, 0b0110, 0b0010, 0b0011, 0b0001, 0b1001
)
class TurtlePlotBot(TurtlePlot): # pylint: disable=too-many-instance-attributes, too-many-public-methods
"""
Initialize the TurtlePlotBot
Args:
i2c (machine.I2C): The I2C peripheral to use.
Defaults to creating a device using the pins
defined in _SCL_PIN and _SDA_PIN.
"""
def __init__(self, scl=_SCL_PIN, sda=_SDA_PIN):
"""
Initialize the turtleplotbot, optionally passing an i2c object to use.
"""
self._current_step = [0, 0] # current step indexes
self._step_delay = 1000 # us delay between steps
self._pen_delay = 250 # ms delay for pen raise or lower
self.mcp23017 = mcp23017.MCP23017(
machine.I2C(
scl=machine.Pin(scl),
sda=machine.Pin(sda),
freq=100000),
0x20)
# pylint: disable=no-member
self.mcp23017.porta.mode = 0x00 # porta output
self.mcp23017.porta.gpio = 0x00 # all pins low
self._pen_servo = Servo(
machine.Pin(_SERVO_PIN, machine.Pin.OUT),
freq=50,
min_us=600,
max_us=2400,
angle=180)
time.sleep_ms(100)
self._pen_servo.write_angle(degrees=_PEN_UP_ANGLE)
self.rst = machine.Pin(16, machine.Pin.OUT) # power pin for LCD display
self.rst.value(1) # power on
super().__init__()
def _movesteppers(self, left, right):
"""
Internal routine to step steppers
Note:
Both steppers always move the same distance, but not
always in the same direction. De-energizes the stepper
coils after moving to save power.
Args:
left (float or integer): millimeters to move left stepper
right (float or integer): millimeters to move right stepper
"""
steppers = [int(left * _STEPS_PER_MM), int(right * _STEPS_PER_MM)]
steps = abs(steppers[_LEFT_MOTOR])
for _ in range(steps):
# pylint: disable=no-member
last = time.ticks_us()
out = 0
for motor in _MOTORS:
if steppers[motor]:
self._current_step[motor] &= 0x07
mask = _STEP_MASKS[self._current_step[motor]]
out |= mask <<4 if motor else mask
if steppers[motor] > 0:
self._current_step[motor] -= 1
if steppers[motor] < 0:
self._current_step[motor] += 1
self.mcp23017.porta.gpio = out
while time.ticks_diff(time.ticks_us(), last) < self._step_delay:
time.sleep_us(100)
# de-energize stepper coils between moves to save power
self.mcp23017.porta.gpio = 0x00 # all pins low
def _turn(self, angle):
"""
Turn TurtlePlotBot left angle degrees
Args:
angle (integer or float): turn left degrees
This Method overrides the TurtlePlotBot method
"""
distance = _WHEEL_BPI * (angle / 360.0)
self._movesteppers(-distance, -distance)
def _move(self, distance):
"""
Move the TurtlePlotBot distance millimeters
Args:
distance (integer or float):
This Method overrides the TurtlePlotBot method
"""
self._movesteppers(-distance, distance)
def _pen(self, down):
"""
lower or raise the pen
Args:
down (boolean):
This Method overrides the TurtlePlotBot method
"""
if down:
self._pen_servo.write_angle(degrees=_PEN_DOWN_ANGLE)
else:
self._pen_servo.write_angle(degrees=_PEN_UP_ANGLE)
# pylint: disable=no-member
time.sleep_ms(self._pen_delay)
def done(self):
"""
Raise pen and turn off the stepper motors.
"""
self.penup()
self._pen_servo.deinit()
self.mcp23017.porta.gpio = 0x00 # all outputs to zero
|