mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-10-29 17:50:37 +00:00
766 lines
23 KiB
Python
766 lines
23 KiB
Python
from __future__ import (
|
|
unicode_literals,
|
|
print_function,
|
|
absolute_import,
|
|
division,
|
|
)
|
|
try:
|
|
from itertools import izip as zip
|
|
except ImportError:
|
|
pass
|
|
|
|
from time import sleep
|
|
from collections import namedtuple
|
|
from itertools import repeat, cycle, chain
|
|
|
|
from .exc import InputDeviceError, OutputDeviceError
|
|
from .input_devices import Button
|
|
from .output_devices import LED, PWMLED, Buzzer, Motor
|
|
from .devices import GPIOThread, CompositeDevice, SourceMixin
|
|
|
|
|
|
class LEDCollection(SourceMixin, CompositeDevice):
|
|
"""
|
|
Abstract base class for :class:`LEDBoard` and :class:`LEDBarGraph`.
|
|
"""
|
|
|
|
def __init__(self, *pins, **kwargs):
|
|
self._blink_thread = None
|
|
super(LEDCollection, self).__init__()
|
|
pwm = kwargs.get('pwm', False)
|
|
LEDClass = PWMLED if pwm else LED
|
|
self._leds = tuple(LEDClass(pin) for pin in pins)
|
|
|
|
def close(self):
|
|
for led in self.leds:
|
|
led.close()
|
|
|
|
@property
|
|
def closed(self):
|
|
return all(led.closed for led in self.leds)
|
|
|
|
@property
|
|
def leds(self):
|
|
"""
|
|
A tuple of all the :class:`LED` or :class:`PWMLED` objects contained by
|
|
the instance.
|
|
"""
|
|
return self._leds
|
|
|
|
def on(self):
|
|
"""
|
|
Turn all the LEDs on.
|
|
"""
|
|
for led in self.leds:
|
|
led.on()
|
|
|
|
def off(self):
|
|
"""
|
|
Turn all the LEDs off.
|
|
"""
|
|
for led in self.leds:
|
|
led.off()
|
|
|
|
def toggle(self):
|
|
"""
|
|
Toggle all the LEDs. For each LED, if it's on, turn it off; if it's
|
|
off, turn it on.
|
|
"""
|
|
for led in self.leds:
|
|
led.toggle()
|
|
|
|
|
|
|
|
class LEDBoard(LEDCollection):
|
|
"""
|
|
Extends :class:`CompositeDevice` and represents a generic LED board or
|
|
collection of LEDs.
|
|
|
|
The following example turns on all the LEDs on a board containing 5 LEDs
|
|
attached to GPIO pins 2 through 6::
|
|
|
|
from gpiozero import LEDBoard
|
|
|
|
leds = LEDBoard(2, 3, 4, 5, 6)
|
|
leds.on()
|
|
|
|
:param int \*pins:
|
|
Specify the GPIO pins that the LEDs of the board are attached to. You
|
|
can designate as many pins as necessary.
|
|
|
|
:param bool pwm:
|
|
If ``True``, construct :class:`PWMLED` instances for each pin. If
|
|
``False`` (the default), construct regular :class:`LED` instances. This
|
|
parameter can only be specified as a keyword parameter.
|
|
"""
|
|
|
|
def close(self):
|
|
self._stop_blink()
|
|
super(LEDBoard, self).close()
|
|
|
|
@property
|
|
def value(self):
|
|
"""
|
|
A tuple containing a value for each LED on the board. This property can
|
|
also be set to update the state of all LEDs on the board.
|
|
"""
|
|
return tuple(led.value for led in self._leds)
|
|
|
|
@value.setter
|
|
def value(self, value):
|
|
self._stop_blink()
|
|
for l, v in zip(self.leds, value):
|
|
l.value = v
|
|
|
|
def on(self):
|
|
self._stop_blink()
|
|
super(LEDBoard, self).on()
|
|
|
|
def off(self):
|
|
self._stop_blink()
|
|
super(LEDBoard, self).off()
|
|
|
|
def toggle(self):
|
|
self._stop_blink()
|
|
super(LEDBoard, self).toggle()
|
|
|
|
def blink(
|
|
self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0,
|
|
n=None, background=True):
|
|
"""
|
|
Make all the LEDs turn on and off repeatedly.
|
|
|
|
:param float on_time:
|
|
Number of seconds on. Defaults to 1 second.
|
|
|
|
:param float off_time:
|
|
Number of seconds off. Defaults to 1 second.
|
|
|
|
:param float fade_in_time:
|
|
Number of seconds to spend fading in. Defaults to 0. Must be 0 if
|
|
``pwm`` was ``False`` when the class was constructed
|
|
(:exc:`ValueError` will be raised if not).
|
|
|
|
:param float fade_out_time:
|
|
Number of seconds to spend fading out. Defaults to 0. Must be 0 if
|
|
``pwm`` was ``False`` when the class was constructed
|
|
(:exc:`ValueError` will be raised if not).
|
|
|
|
:param int n:
|
|
Number of times to blink; ``None`` (the default) means forever.
|
|
|
|
:param bool background:
|
|
If ``True``, start a background thread to continue blinking and
|
|
return immediately. If ``False``, only return when the blink is
|
|
finished (warning: the default value of *n* will result in this
|
|
method never returning).
|
|
"""
|
|
if isinstance(self.leds[0], LED):
|
|
if fade_in_time:
|
|
raise ValueError('fade_in_time must be 0 with non-PWM LEDs')
|
|
if fade_out_time:
|
|
raise ValueError('fade_out_time must be 0 with non-PWM LEDs')
|
|
self._stop_blink()
|
|
self._blink_thread = GPIOThread(
|
|
target=self._blink_device,
|
|
args=(on_time, off_time, fade_in_time, fade_out_time, n)
|
|
)
|
|
self._blink_thread.start()
|
|
if not background:
|
|
self._blink_thread.join()
|
|
self._blink_thread = None
|
|
|
|
def _stop_blink(self):
|
|
if self._blink_thread:
|
|
self._blink_thread.stop()
|
|
self._blink_thread = None
|
|
|
|
def _blink_device(self, on_time, off_time, fade_in_time, fade_out_time, n, fps=50):
|
|
sequence = []
|
|
if fade_in_time > 0:
|
|
sequence += [
|
|
(i * (1 / fps) / fade_in_time, 1 / fps)
|
|
for i in range(int(fps * fade_in_time))
|
|
]
|
|
sequence.append((1, on_time))
|
|
if fade_out_time > 0:
|
|
sequence += [
|
|
(1 - (i * (1 / fps) / fade_out_time), 1 / fps)
|
|
for i in range(int(fps * fade_out_time))
|
|
]
|
|
sequence.append((0, off_time))
|
|
sequence = (
|
|
cycle(sequence) if n is None else
|
|
chain.from_iterable(repeat(sequence, n))
|
|
)
|
|
for value, delay in sequence:
|
|
for led in self.leds:
|
|
led.value = value
|
|
if self._blink_thread.stopping.wait(delay):
|
|
break
|
|
|
|
|
|
class LEDBarGraph(LEDCollection):
|
|
"""
|
|
Extends :class:`CompositeDevice` to control a line of LEDs representing a
|
|
bar graph. Positive values (0 to 1) light the LEDs from first to last.
|
|
Negative values (-1 to 0) light the LEDs from last to first.
|
|
|
|
The following example turns on all the LEDs on a board containing 5 LEDs
|
|
attached to GPIO pins 2 through 6::
|
|
|
|
from gpiozero import LEDBarGraph
|
|
|
|
graph = LEDBarGraph(2, 3, 4, 5, 6)
|
|
graph.value = 2/5 # Light the first two LEDs only
|
|
graph.value = -2/5 # Light the last two LEDs only
|
|
graph.off()
|
|
|
|
As with other output devices, :attr:`source` and :attr:`values` are
|
|
supported::
|
|
|
|
from gpiozero import LEDBarGraph, MCP3008
|
|
from signal import pause
|
|
|
|
graph = LEDBarGraph(2, 3, 4, 5, 6)
|
|
pot = MCP3008(channel=0)
|
|
graph.source = pot.values
|
|
pause()
|
|
|
|
:param int \*pins:
|
|
Specify the GPIO pins that the LEDs of the bar graph are attached to.
|
|
You can designate as many pins as necessary.
|
|
|
|
:param float initial_value:
|
|
The initial :attr:`value` of the graph given as a float between -1 and
|
|
+1. Defaults to 0.0.
|
|
"""
|
|
|
|
def __init__(self, *pins, **kwargs):
|
|
super(LEDBarGraph, self).__init__(*pins, pwm=False)
|
|
initial_value = kwargs.get('initial_value', 0)
|
|
self.value = initial_value
|
|
|
|
@property
|
|
def value(self):
|
|
"""
|
|
The value of the LED bar graph. When no LEDs are lit, the value is 0.
|
|
When all LEDs are lit, the value is 1. Values between 0 and 1
|
|
light LEDs linearly from first to last. Values between 0 and -1
|
|
light LEDs linearly from last to first.
|
|
|
|
To light a particular number of LEDs, simply divide that number by
|
|
the number of LEDs. For example, if your graph contains 3 LEDs, the
|
|
following will light the first::
|
|
|
|
from gpiozero import LEDBarGraph
|
|
|
|
graph = LEDBarGraph(12, 16, 19)
|
|
graph.value = 1/3
|
|
|
|
.. note::
|
|
|
|
Setting value to -1 will light all LEDs. However, querying it
|
|
subsequently will return 1 as both representations are the same in
|
|
hardware.
|
|
"""
|
|
for index, led in enumerate(self.leds):
|
|
if not led.is_lit:
|
|
break
|
|
else:
|
|
index = len(self.leds)
|
|
if not index:
|
|
for index, led in enumerate(reversed(self.leds)):
|
|
if not led.is_lit:
|
|
break
|
|
index = -index
|
|
return index / len(self.leds)
|
|
|
|
@value.setter
|
|
def value(self, value):
|
|
count = len(self.leds)
|
|
if value >= 0:
|
|
for index, led in enumerate(self.leds, start=1):
|
|
led.value = value >= (index / count)
|
|
else:
|
|
for index, led in enumerate(reversed(self.leds), start=1):
|
|
led.value = value <= -(index / count)
|
|
|
|
|
|
class PiLiter(LEDBoard):
|
|
"""
|
|
Extends :class:`LEDBoard` for the `Ciseco Pi-LITEr`_: a strip of 8 very bright
|
|
LEDs.
|
|
|
|
The Pi-LITEr pins are fixed and therefore there's no need to specify them
|
|
when constructing this class. The following example turns on all the LEDs
|
|
of the Pi-LITEr::
|
|
|
|
from gpiozero import PiLiter
|
|
|
|
lite = PiLiter()
|
|
lite.on()
|
|
|
|
:param bool pwm:
|
|
If ``True``, construct :class:`PWMLED` instances for each pin. If
|
|
``False`` (the default), construct regular :class:`LED` instances. This
|
|
parameter can only be specified as a keyword parameter.
|
|
|
|
.. _Ciseco Pi-LITEr: http://shop.ciseco.co.uk/pi-liter-8-led-strip-for-the-raspberry-pi/
|
|
"""
|
|
def __init__(self, pwm=False):
|
|
super(PiLiter, self).__init__(4, 17, 27, 18, 22, 23, 24, 25, pwm=pwm)
|
|
|
|
|
|
class PiLiterBarGraph(LEDBarGraph):
|
|
"""
|
|
Extends :class:`LEDBarGraph` to treat the `Ciseco Pi-LITEr`_ as an
|
|
8-segment bar graph.
|
|
|
|
The Pi-LITEr pins are fixed and therefore there's no need to specify them
|
|
when constructing this class. The following example sets the graph value
|
|
to 0.5::
|
|
|
|
from gpiozero import PiLiterBarGraph
|
|
|
|
graph = PiLiterBarGraph()
|
|
graph.value = 0.5
|
|
|
|
:param bool initial_value:
|
|
The initial value of the graph given as a float between -1 and +1.
|
|
Defaults to 0.0.
|
|
|
|
.. _Ciseco Pi-LITEr: http://shop.ciseco.co.uk/pi-liter-8-led-strip-for-the-raspberry-pi/
|
|
"""
|
|
def __init__(self, initial_value=0):
|
|
super(PiLiterBarGraph, self).__init__(
|
|
4, 17, 27, 18, 22, 23, 24, 25, initial_value=initial_value)
|
|
|
|
|
|
TrafficLightTuple = namedtuple('TrafficLightTuple', ('red', 'amber', 'green'))
|
|
|
|
|
|
class TrafficLights(LEDBoard):
|
|
"""
|
|
Extends :class:`LEDBoard` for devices containing red, amber, and green
|
|
LEDs.
|
|
|
|
The following example initializes a device connected to GPIO pins 2, 3,
|
|
and 4, then lights the amber LED attached to GPIO 3::
|
|
|
|
from gpiozero import TrafficLights
|
|
|
|
traffic = TrafficLights(2, 3, 4)
|
|
traffic.amber.on()
|
|
|
|
:param int red:
|
|
The GPIO pin that the red LED is attached to.
|
|
|
|
:param int amber:
|
|
The GPIO pin that the amber LED is attached to.
|
|
|
|
:param int green:
|
|
The GPIO pin that the green LED is attached to.
|
|
|
|
:param bool pwm:
|
|
If ``True``, construct :class:`PWMLED` instances to represent each
|
|
LED. If ``False`` (the default), construct regular :class:`LED`
|
|
instances.
|
|
"""
|
|
def __init__(self, red=None, amber=None, green=None, pwm=False):
|
|
if not all([red, amber, green]):
|
|
raise OutputDeviceError(
|
|
'red, amber and green pins must be provided'
|
|
)
|
|
super(TrafficLights, self).__init__(red, amber, green, pwm=pwm)
|
|
|
|
@property
|
|
def value(self):
|
|
"""
|
|
A 3-tuple containing values for the red, amber, and green LEDs. This
|
|
property can also be set to alter the state of the LEDs.
|
|
"""
|
|
return TrafficLightTuple(*super(TrafficLights, self).value)
|
|
|
|
@value.setter
|
|
def value(self, value):
|
|
# Eurgh, this is horrid but necessary (see #90)
|
|
super(TrafficLights, self.__class__).value.fset(self, value)
|
|
|
|
@property
|
|
def red(self):
|
|
"""
|
|
The :class:`LED` or :class:`PWMLED` object representing the red LED.
|
|
"""
|
|
return self.leds[0]
|
|
|
|
@property
|
|
def amber(self):
|
|
"""
|
|
The :class:`LED` or :class:`PWMLED` object representing the red LED.
|
|
"""
|
|
return self.leds[1]
|
|
|
|
@property
|
|
def green(self):
|
|
"""
|
|
The :class:`LED` or :class:`PWMLED` object representing the green LED.
|
|
"""
|
|
return self.leds[2]
|
|
|
|
|
|
class PiTraffic(TrafficLights):
|
|
"""
|
|
Extends :class:`TrafficLights` for the Low Voltage Labs PI-TRAFFIC:
|
|
vertical traffic lights board when attached to GPIO pins 9, 10, and 11.
|
|
|
|
There's no need to specify the pins if the PI-TRAFFIC is connected to the
|
|
default pins (9, 10, 11). The following example turns on the amber LED on
|
|
the PI-TRAFFIC::
|
|
|
|
from gpiozero import PiTraffic
|
|
|
|
traffic = PiTraffic()
|
|
traffic.amber.on()
|
|
|
|
To use the PI-TRAFFIC board when attached to a non-standard set of pins,
|
|
simply use the parent class, :class:`TrafficLights`.
|
|
"""
|
|
def __init__(self):
|
|
super(PiTraffic, self).__init__(9, 10, 11)
|
|
|
|
|
|
TrafficLightsBuzzerTuple = namedtuple('TrafficLightsBuzzerTuple', (
|
|
'red', 'amber', 'green', 'buzzer'))
|
|
|
|
|
|
class TrafficLightsBuzzer(SourceMixin, CompositeDevice):
|
|
"""
|
|
Extends :class:`CompositeDevice` and is a generic class for HATs with
|
|
traffic lights, a button and a buzzer.
|
|
|
|
:param TrafficLights lights:
|
|
An instance of :class:`TrafficLights` representing the traffic lights
|
|
of the HAT.
|
|
|
|
:param Buzzer buzzer:
|
|
An instance of :class:`Buzzer` representing the buzzer on the HAT.
|
|
|
|
:param Button button:
|
|
An instance of :class:`Button` representing the button on the HAT.
|
|
"""
|
|
def __init__(self, lights, buzzer, button):
|
|
super(TrafficLightsBuzzer, self).__init__()
|
|
self.lights = lights
|
|
self.buzzer = buzzer
|
|
self.button = button
|
|
self._all = self.lights.leds + (self.buzzer,)
|
|
|
|
def close(self):
|
|
self.lights.close()
|
|
self.buzzer.close()
|
|
self.button.close()
|
|
|
|
@property
|
|
def closed(self):
|
|
return all(o.closed for o in self.all)
|
|
|
|
@property
|
|
def all(self):
|
|
"""
|
|
A tuple containing objects for all the items on the board (several
|
|
:class:`LED` objects, a :class:`Buzzer`, and a :class:`Button`).
|
|
"""
|
|
return self._all
|
|
|
|
@property
|
|
def value(self):
|
|
"""
|
|
Returns a named-tuple containing values representing the states of
|
|
the LEDs, and the buzzer. This property can also be set to a 4-tuple
|
|
to update the state of all the board's components.
|
|
"""
|
|
return TrafficLightsBuzzerTuple(
|
|
self.lights.red.value,
|
|
self.lights.amber.value,
|
|
self.lights.green.value,
|
|
self.buzzer.value,
|
|
)
|
|
|
|
@value.setter
|
|
def value(self, value):
|
|
for i, v in zip(self.all, value):
|
|
i.value = v
|
|
|
|
def on(self):
|
|
"""
|
|
Turn all the board's components on.
|
|
"""
|
|
for thing in self.all:
|
|
thing.on()
|
|
|
|
def off(self):
|
|
"""
|
|
Turn all the board's components off.
|
|
"""
|
|
for thing in self.all:
|
|
thing.off()
|
|
|
|
def toggle(self):
|
|
"""
|
|
Toggle all the board's components. For each component, if it's on, turn
|
|
it off; if it's off, turn it on.
|
|
"""
|
|
for thing in self.all:
|
|
thing.toggle()
|
|
|
|
def blink(self, on_time=1, off_time=1, n=None, background=True):
|
|
"""
|
|
Make all the board's components turn on and off repeatedly.
|
|
|
|
:param float on_time:
|
|
Number of seconds on
|
|
|
|
:param float off_time:
|
|
Number of seconds off
|
|
|
|
:param int n:
|
|
Number of times to blink; ``None`` means forever
|
|
|
|
:param bool background:
|
|
If ``True``, start a background thread to continue blinking and
|
|
return immediately. If ``False``, only return when the blink is
|
|
finished (warning: the default value of *n* will result in this
|
|
method never returning).
|
|
"""
|
|
# XXX This isn't going to work for background=False
|
|
for thing in self._all:
|
|
thing.blink(on_time, off_time, n, background)
|
|
|
|
|
|
class FishDish(TrafficLightsBuzzer):
|
|
"""
|
|
Extends :class:`TrafficLightsBuzzer` for the Pi Supply FishDish: traffic
|
|
light LEDs, a button and a buzzer.
|
|
|
|
The FishDish pins are fixed and therefore there's no need to specify them
|
|
when constructing this class. The following example waits for the button
|
|
to be pressed on the FishDish, then turns on all the LEDs::
|
|
|
|
from gpiozero import FishDish
|
|
|
|
fish = FishDish()
|
|
fish.button.wait_for_press()
|
|
fish.lights.on()
|
|
|
|
:param bool pwm:
|
|
If ``True``, construct :class:`PWMLED` instances to represent each
|
|
LED. If ``False`` (the default), construct regular :class:`LED`
|
|
instances.
|
|
"""
|
|
def __init__(self, pwm=False):
|
|
super(FishDish, self).__init__(
|
|
TrafficLights(9, 22, 4, pwm=pwm),
|
|
Buzzer(8),
|
|
Button(7, pull_up=False),
|
|
)
|
|
|
|
|
|
class TrafficHat(TrafficLightsBuzzer):
|
|
"""
|
|
Extends :class:`TrafficLightsBuzzer` for the Ryanteck Traffic HAT: traffic
|
|
light LEDs, a button and a buzzer.
|
|
|
|
The Traffic HAT pins are fixed and therefore there's no need to specify
|
|
them when constructing this class. The following example waits for the
|
|
button to be pressed on the Traffic HAT, then turns on all the LEDs::
|
|
|
|
from gpiozero import TrafficHat
|
|
|
|
hat = TrafficHat()
|
|
hat.button.wait_for_press()
|
|
hat.lights.on()
|
|
|
|
:param bool pwm:
|
|
If ``True``, construct :class:`PWMLED` instances to represent each
|
|
LED. If ``False`` (the default), construct regular :class:`LED`
|
|
instances.
|
|
"""
|
|
def __init__(self, pwm=False):
|
|
super(TrafficHat, self).__init__(
|
|
TrafficLights(24, 23, 22, pwm=pwm),
|
|
Buzzer(5),
|
|
Button(25),
|
|
)
|
|
|
|
|
|
RobotTuple = namedtuple('RobotTuple', ('left', 'right'))
|
|
|
|
|
|
class Robot(SourceMixin, CompositeDevice):
|
|
"""
|
|
Extends :class:`CompositeDevice` to represent a generic dual-motor robot.
|
|
|
|
This class is constructed with two tuples representing the forward and
|
|
backward pins of the left and right controllers respectively. For example,
|
|
if the left motor's controller is connected to GPIOs 4 and 14, while the
|
|
right motor's controller is connected to GPIOs 17 and 18 then the following
|
|
example will turn the robot left::
|
|
|
|
from gpiozero import Robot
|
|
|
|
robot = Robot(left=(4, 14), right=(17, 18))
|
|
robot.left()
|
|
|
|
:param tuple left:
|
|
A tuple of two GPIO pins representing the forward and backward inputs
|
|
of the left motor's controller.
|
|
|
|
:param tuple right:
|
|
A tuple of two GPIO pins representing the forward and backward inputs
|
|
of the right motor's controller.
|
|
"""
|
|
def __init__(self, left=None, right=None):
|
|
if not all([left, right]):
|
|
raise OutputDeviceError(
|
|
'left and right motor pins must be provided'
|
|
)
|
|
super(Robot, self).__init__()
|
|
self._left = Motor(*left)
|
|
self._right = Motor(*right)
|
|
|
|
def close(self):
|
|
self._left.close()
|
|
self._right.close()
|
|
|
|
@property
|
|
def closed(self):
|
|
return self._left.closed and self._right.closed
|
|
|
|
@property
|
|
def left_motor(self):
|
|
"""
|
|
Returns the `Motor` device representing the robot's left motor.
|
|
"""
|
|
return self._left
|
|
|
|
@property
|
|
def right_motor(self):
|
|
"""
|
|
Returns the `Motor` device representing the robot's right motor.
|
|
"""
|
|
return self._right
|
|
|
|
@property
|
|
def value(self):
|
|
"""
|
|
Returns a tuple of two floating point values (-1 to 1) representing the
|
|
speeds of the robot's two motors (left and right). This property can
|
|
also be set to alter the speed of both motors.
|
|
"""
|
|
return RobotTuple(self._left.value, self._right.value)
|
|
|
|
@value.setter
|
|
def value(self, value):
|
|
self._left.value, self._right.value = value
|
|
|
|
def forward(self, speed=1):
|
|
"""
|
|
Drive the robot forward by running both motors forward.
|
|
|
|
:param float speed:
|
|
Speed at which to drive the motors, as a value between 0 (stopped)
|
|
and 1 (full speed). The default is 1.
|
|
"""
|
|
self._left.forward(speed)
|
|
self._right.forward(speed)
|
|
|
|
def backward(self, speed=1):
|
|
"""
|
|
Drive the robot backward by running both motors backward.
|
|
|
|
:param float speed:
|
|
Speed at which to drive the motors, as a value between 0 (stopped)
|
|
and 1 (full speed). The default is 1.
|
|
"""
|
|
self._left.backward(speed)
|
|
self._right.backward(speed)
|
|
|
|
def left(self, speed=1):
|
|
"""
|
|
Make the robot turn left by running the right motor forward and left
|
|
motor backward.
|
|
|
|
:param float speed:
|
|
Speed at which to drive the motors, as a value between 0 (stopped)
|
|
and 1 (full speed). The default is 1.
|
|
"""
|
|
self._right.forward(speed)
|
|
self._left.backward(speed)
|
|
|
|
def right(self, speed=1):
|
|
"""
|
|
Make the robot turn right by running the left motor forward and right
|
|
motor backward.
|
|
|
|
:param float speed:
|
|
Speed at which to drive the motors, as a value between 0 (stopped)
|
|
and 1 (full speed). The default is 1.
|
|
"""
|
|
self._left.forward(speed)
|
|
self._right.backward(speed)
|
|
|
|
def reverse(self):
|
|
"""
|
|
Reverse the robot's current motor directions. If the robot is currently
|
|
running full speed forward, it will run full speed backward. If the
|
|
robot is turning left at half-speed, it will turn right at half-speed.
|
|
If the robot is currently stopped it will remain stopped.
|
|
"""
|
|
self._left.value = -self._left.value
|
|
self._right.value = -self._right.value
|
|
|
|
def stop(self):
|
|
"""
|
|
Stop the robot.
|
|
"""
|
|
self._left.stop()
|
|
self._right.stop()
|
|
|
|
|
|
class RyanteckRobot(Robot):
|
|
"""
|
|
Extends :class:`Robot` for the Ryanteck MCB robot.
|
|
|
|
The Ryanteck MCB pins are fixed and therefore there's no need to specify
|
|
them when constructing this class. The following example turns the robot
|
|
left::
|
|
|
|
from gpiozero import RyanteckRobot
|
|
|
|
robot = RyanteckRobot()
|
|
robot.left()
|
|
"""
|
|
def __init__(self):
|
|
super(RyanteckRobot, self).__init__(left=(17, 18), right=(22, 23))
|
|
|
|
|
|
class CamJamKitRobot(Robot):
|
|
"""
|
|
Extends :class:`Robot` for the `CamJam #3 EduKit`_ robot controller.
|
|
|
|
The CamJam robot controller pins are fixed and therefore there's no need
|
|
to specify them when constructing this class. The following example turns
|
|
the robot left::
|
|
|
|
from gpiozero import CamJamKitRobot
|
|
|
|
robot = CamJamKitRobot()
|
|
robot.left()
|
|
|
|
.. _CamJam #3 EduKit: http://camjam.me/?page_id=1035
|
|
"""
|
|
def __init__(self):
|
|
super(CamJamKitRobot, self).__init__(left=(9, 10), right=(7, 8))
|
|
|