Merge pull request #569 from waveform80/pin-factory-docs

Fix #568, fix #572, fix #565
This commit is contained in:
Dave Jones
2017-07-14 16:47:55 +01:00
committed by GitHub
25 changed files with 265 additions and 121 deletions

View File

@@ -127,44 +127,30 @@ Like the ``GPIOZERO_PIN_FACTORY`` value, these can be exported from your
.. warning:: .. warning::
The astute and mischievous reader may note that it is possible to mix The astute and mischievous reader may note that it is possible to mix
strictly local pin implementations, e.g. using ``RPiGPIOPin`` for one pin, factories, e.g. using ``RPiGPIOFactory`` for one pin, and ``NativeFactory``
and ``NativePin`` for another. This is unsupported, and if it results in for another. This is unsupported, and if it results in your script
your script crashing, your components failing, or your Raspberry Pi turning crashing, your components failing, or your Raspberry Pi turning into an
into an actual raspberry pie, you have only yourself to blame. actual raspberry pie, you have only yourself to blame.
Sensible uses of multiple pin factories are given in :doc:`remote_gpio`. Sensible uses of multiple pin factories are given in :doc:`remote_gpio`.
RPi.GPIO Mock pins
======== =========
.. autoclass:: gpiozero.pins.rpigpio.RPiGPIOFactory There's also a :class:`gpiozero.pins.mock.MockFactory` which generates entirely
fake pins. This was originally intended for GPIO Zero developers who wish to
write tests for devices without having to have the physical device wired in to
their Pi. However, they have also proven relatively useful in developing GPIO
Zero scripts without having a Pi to hand. This pin factory will never be loaded
by default; it must be explicitly specified. For example:
.. autoclass:: gpiozero.pins.rpigpio.RPiGPIOPin .. literalinclude:: examples/mock_demo.py
Several sub-classes of mock pins exist for emulating various other things
RPIO (pins that do/don't support PWM, pins that are connected together, pins that
==== drive high after a delay, etc). Interested users are invited to read the GPIO
Zero test suite for further examples of usage.
.. autoclass:: gpiozero.pins.rpio.RPIOFactory
.. autoclass:: gpiozero.pins.rpio.RPIOPin
PiGPIO
======
.. autoclass:: gpiozero.pins.pigpio.PiGPIOFactory
.. autoclass:: gpiozero.pins.pigpio.PiGPIOPin
Native
======
.. autoclass:: gpiozero.pins.native.NativeFactory
.. autoclass:: gpiozero.pins.native.NativePin
Base classes Base classes
@@ -196,22 +182,62 @@ Base classes
:members: :members:
Utilities RPi.GPIO
========= ========
The pins module also contains a database of information about the various .. currentmodule:: gpiozero.pins.rpigpio
revisions of Raspberry Pi. This is used internally to raise warnings when
non-physical pins are used, or to raise exceptions when pull-downs are
requested on pins with physical pull-up resistors attached. The following
functions and classes can be used to query this database:
.. currentmodule:: gpiozero .. autoclass:: gpiozero.pins.rpigpio.RPiGPIOFactory
.. autofunction:: pi_info .. autoclass:: gpiozero.pins.rpigpio.RPiGPIOPin
.. autoclass:: PiBoardInfo
.. autoclass:: HeaderInfo RPIO
====
.. autoclass:: PinInfo .. currentmodule:: gpiozero.pins.rpio
.. autoclass:: gpiozero.pins.rpio.RPIOFactory
.. autoclass:: gpiozero.pins.rpio.RPIOPin
PiGPIO
======
.. currentmodule:: gpiozero.pins.pigpio
.. autoclass:: gpiozero.pins.pigpio.PiGPIOFactory
.. autoclass:: gpiozero.pins.pigpio.PiGPIOPin
Native
======
.. currentmodule:: gpiozero.pins.native
.. autoclass:: gpiozero.pins.native.NativeFactory
.. autoclass:: gpiozero.pins.native.NativePin
Mock
====
.. currentmodule:: gpiozero.pins.mock
.. autoclass:: gpiozero.pins.mock.MockFactory
:members:
.. autoclass:: gpiozero.pins.mock.MockPin
:members:
.. autoclass:: gpiozero.pins.mock.MockPWMPin
.. autoclass:: gpiozero.pins.mock.MockConnectedPin
.. autoclass:: gpiozero.pins.mock.MockChargingPin
.. autoclass:: gpiozero.pins.mock.MockTriggerPin

20
docs/api_utils.rst Normal file
View File

@@ -0,0 +1,20 @@
=========
Utilities
=========
.. currentmodule:: gpiozero
The GPIO Zero library also contains a database of information about the various
revisions of Raspberry Pi. This is used internally to raise warnings when
non-physical pins are used, or to raise exceptions when pull-downs are
requested on pins with physical pull-up resistors attached. The following
functions and classes can be used to query this database:
.. autofunction:: pi_info
.. autoclass:: PiBoardInfo
.. autoclass:: HeaderInfo
.. autoclass:: PinInfo

View File

@@ -1,9 +1,11 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from signal import pause from signal import pause
factory = PiGPIOFactory(host='192.168.1.3')
button = Button(2) button = Button(2)
led = LED(PiGPIOPin(17, host='192.168.1.3')) led = LED(17, pin_factory=factory)
led.source = button.values led.source = button.values

View File

@@ -1,11 +1,14 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from gpiozero.tools import all_values from gpiozero.tools import all_values
from signal import pause from signal import pause
factory3 = PiGPIOFactory(host='192.168.1.3')
factory4 = PiGPIOFactory(host='192.168.1.4')
led = LED(17) led = LED(17)
button_1 = Button(PiGPIOPin(17, host='192.168.1.3')) button_1 = Button(17, pin_factory=factory3)
button_2 = Button(PiGPIOPin(17, host='192.168.1.4')) button_2 = Button(17, pin_factory=factory4)
led.source = all_values(button_1.values, button_2.values) led.source = all_values(button_1.values, button_2.values)

View File

@@ -1,8 +1,9 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep from time import sleep
led = LED(PiGPIOPin(17, host='192.168.1.3')) factory = PiGPIOFactory(host='192.168.1.3')
led = LED(17, pin_factory=factory)
while True: while True:
led.on() led.on()

View File

@@ -1,9 +1,11 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep from time import sleep
led_1 = LED(PiGPIOPin(17, host='192.168.1.3')) factory3 = PiGPIOFactory(host='192.168.1.3')
led_2 = LED(PiGPIOPin(17, host='192.168.1.4')) factory4 = PiGPIOFactory(host='192.168.1.4')
led_1 = LED(17, pin_factory=factory3)
led_2 = LED(17, pin_factory=factory4)
while True: while True:
led_1.on() led_1.on()

View File

@@ -1,9 +1,10 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep from time import sleep
remote_factory = PiGPIOFactory(host='192.168.1.3')
led_1 = LED(17) # local pin led_1 = LED(17) # local pin
led_2 = LED(PiGPIOPin(17, host='192.168.1.3')) # remote pin led_2 = LED(17, pin_factory=remote_factory) # remote pin
while True: while True:
led_1.on() led_1.on()

View File

@@ -1,8 +1,9 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.rpigpio import RPiGPIOPin from gpiozero.pins.rpigpio import RPiGPIOFactory
from time import sleep from time import sleep
led_1 = LED(RPiGPIOPin(17)) # local pin local_factory = RPiGPIOFactory()
led_1 = LED(17, pin_factory=local_factory) # local pin
led_2 = LED(17) # remote pin led_2 = LED(17) # remote pin
while True: while True:

View File

@@ -1,10 +1,13 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep from time import sleep
factory3 = PiGPIOFactory(host='192.168.1.3')
factory4 = PiGPIOFactory(host='192.168.1.4')
led_1 = LED(17) # local pin led_1 = LED(17) # local pin
led_2 = LED(PiGPIOPin(17, host='192.168.1.3')) # remote pin on one pi led_2 = LED(17, pin_factory=factory3) # remote pin on one pi
led_3 = LED(PiGPIOPin(17, host='192.168.1.4')) # remote pin on another pi led_3 = LED(17, pin_factory=factory4) # remote pin on another pi
while True: while True:
led_1.on() led_1.on()

View File

@@ -0,0 +1,28 @@
from gpiozero.pins.mock import MockFactory
from gpiozero import Device, Button, LED
from time import sleep
# Set the default pin factory to a mock factory
Device.pin_factory = MockFactory()
# Construct a couple of devices attached to mock pins 16 and 17, and link the
# devices
led = LED(17)
btn = Button(16)
led.source = btn.values
# Here the button isn't "pushed" so the LED's value should be False
print(led.value)
# Get a reference to mock pin 16 (used by the button)
btn_pin = Device.pin_factory.pin(16)
# Drive the pin low (this is what would happen eletrically when the button is
# pushed)
btn_pin.drive_low()
sleep(0.1) # give source some time to re-read the button state
print(led.value)
btn_pin.drive_high()
sleep(0.1)
print(led.value)

View File

@@ -1,8 +1,9 @@
from gpiozero import LED from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from signal import pause from signal import pause
led = LED(PiGPIOPin(17, host='raspberrypi.local')) factory = PiGPIOFactory(host='raspberrypi.local')
led = LED(17, pin_factory=factory)
led.blink() led.blink()

View File

@@ -1,8 +1,9 @@
from gpiozero import MotionSensor from gpiozero import MotionSensor
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from sense_hat import SenseHat from sense_hat import SenseHat
pir = MotionSensor(PiGPIOPin(4, host='192.168.1.4')) # remote motion sensor remote_factory = PiGPIOFactory(host='192.198.1.4')
pir = MotionSensor(4, pin_factory=remote_factory) # remote motion sensor
sense = SenseHat() # local sense hat sense = SenseHat() # local sense hat
while True: while True:

View File

@@ -1,8 +1,9 @@
from gpiozero import LightSensor from gpiozero import LightSensor
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from sense_hat import SenseHat from sense_hat import SenseHat
light = LightSensor(PiGPIOPin(4, host='192.168.1.4')) # remote motion sensor remote_factory = PiGPIOFactory(host='192.168.1.4')
light = LightSensor(4, pin_factory=remote_factory) # remote motion sensor
sense = SenseHat() # local sense hat sense = SenseHat() # local sense hat
blue = (0, 0, 255) blue = (0, 0, 255)

View File

@@ -3,5 +3,5 @@ from gpiozero import TrafficHat
from gpiozero.pins.pigpio import PiGPIOFactory from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep from time import sleep
gpiozero.Device._set_pin_factory(PiGPIOFactory(host='192.168.1.3')) gpiozero.Device.pin_factory = PiGPIOFactory(host='192.168.1.3')
th = TrafficHat() # traffic hat on 192.168.1.3 using remote pins th = TrafficHat() # traffic hat on 192.168.1.3 using remote pins

View File

@@ -3,6 +3,7 @@ from gpiozero import TrafficHat
from gpiozero.pins.pigpio import PiGPIOFactory from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep from time import sleep
remote_factory = PiGPIOFactory(host='192.168.1.3')
th_1 = TrafficHat() # traffic hat using local pins th_1 = TrafficHat() # traffic hat using local pins
gpiozero.Device._set_pin_factory(PiGPIOFactory(host='192.168.1.3')) th_2 = TrafficHat(pin_factory=remote_factory) # traffic hat on 192.168.1.3 using remote pins
th_2 = TrafficHat() # traffic hat on 192.168.1.3 using remote pins

View File

@@ -17,6 +17,7 @@ Table of Contents
api_generic api_generic
api_tools api_tools
api_pins api_pins
api_utils
api_exc api_exc
cli_tools cli_tools
source_values source_values

View File

@@ -12,8 +12,8 @@ documentation page.
One of the pin libraries supported, `pigpio`_, provides the ability to control One of the pin libraries supported, `pigpio`_, provides the ability to control
GPIO pins remotely over the network, which means you can use GPIO Zero to GPIO pins remotely over the network, which means you can use GPIO Zero to
control devices connected to a Raspberry Pi on the network. You can do this from control devices connected to a Raspberry Pi on the network. You can do this
another Raspberry Pi, or even from a PC. from another Raspberry Pi, or even from a PC.
See the :doc:`recipes_remote_gpio` page for examples on how remote pins can be See the :doc:`recipes_remote_gpio` page for examples on how remote pins can be
used. used.
@@ -22,8 +22,8 @@ Preparing the Raspberry Pi
========================== ==========================
If you're using Raspbian Jessie (desktop - not Jessie Lite) then you have If you're using Raspbian Jessie (desktop - not Jessie Lite) then you have
everything you need to use the remote GPIO feature. If you're using Jessie Lite, everything you need to use the remote GPIO feature. If you're using Jessie
or another distribution, you'll need to install pigpio: Lite, or another distribution, you'll need to install pigpio:
.. code-block:: console .. code-block:: console
@@ -52,7 +52,9 @@ example:
$ sudo pigpiod -n localhost -n 192.168.1.65 # allow localhost and 192.168.1.65 only $ sudo pigpiod -n localhost -n 192.168.1.65 # allow localhost and 192.168.1.65 only
You will need to launch the pigpio daemon every time you wish to use this You will need to launch the pigpio daemon every time you wish to use this
feature. To automate running the daemon at boot time:: feature. To automate running the daemon at boot time:
.. code-block:: console
$ sudo systemctl enable pigpiod $ sudo systemctl enable pigpiod
@@ -181,17 +183,18 @@ following:
If you are running this from a PC (not a Raspberry Pi) with gpiozero and the If you are running this from a PC (not a Raspberry Pi) with gpiozero and the
pigpio Python library installed, this will work with no further configuration. pigpio Python library installed, this will work with no further configuration.
However, if you are running this from a Raspberry Pi, you will also need to However, if you are running this from a Raspberry Pi, you will also need to
ensure the default pin factory is set to ``PiGPIOPin``. If ``RPi.GPIO`` is ensure the default pin factory is set to ``PiGPIOFactory``. If ``RPi.GPIO`` is
installed, this will be selected as the default pin factory, so either uninstall installed, this will be selected as the default pin factory, so either
it, or use another environment variable to set it to ``PiGPIOPin``: uninstall it, or use another environment variable to set it to
``PiGPIOFactory``:
.. code-block:: console .. code-block:: console
$ GPIOZERO_PIN_FACTORY=pigpio PIGPIO_ADDR=192.168.1.3 python3 hello.py $ GPIOZERO_PIN_FACTORY=pigpio PIGPIO_ADDR=192.168.1.3 python3 hello.py
This usage will set the pin factory to :class:`PiGPIOPin` with a default host of This usage will set the pin factory to :class:`PiGPIOFactory` with a default
``192.168.1.3``. The pin factory can be changed inline in the code, as seen in host of ``192.168.1.3``. The pin factory can be changed inline in the code, as
the following sections. seen in the following sections.
With this usage, you can write gpiozero code like you would on a Raspberry Pi, With this usage, you can write gpiozero code like you would on a Raspberry Pi,
with no modifications needed. For example: with no modifications needed. For example:
@@ -218,9 +221,9 @@ Pin objects
=========== ===========
An alternative (or additional) method of configuring gpiozero objects to use An alternative (or additional) method of configuring gpiozero objects to use
remote pins is to create instances of :class:PiGPIOPin objects, and remote pins is to create instances of :class:`PiGPIOFactory` objects, and use
instantiating device objects with those pin objects, rather than just numbers. them when instantiating device objects. For example, with no environment
For example, with no environment variables set: variables set:
.. literalinclude:: examples/led_remote_1.py .. literalinclude:: examples/led_remote_1.py
@@ -230,8 +233,8 @@ This allows devices on multiple Raspberry Pis to be used in the same script:
You can, of course, continue to create gpiozero device objects as normal, and You can, of course, continue to create gpiozero device objects as normal, and
create others using remote pins. For example, if run on a Raspberry Pi, the create others using remote pins. For example, if run on a Raspberry Pi, the
following script will flash an LED on the host Pi, and also on another Pi on the following script will flash an LED on the host Pi, and also on another Pi on
network: the network:
.. literalinclude:: examples/led_remote_3.py .. literalinclude:: examples/led_remote_3.py
@@ -249,7 +252,8 @@ Note that these examples use the :class:`LED` class, which takes a ``pin``
argument to initialise. Some classes, particularly those representing HATs and argument to initialise. Some classes, particularly those representing HATs and
other add-on boards, do not require their pin numbers to be specified. However, other add-on boards, do not require their pin numbers to be specified. However,
it is still possible to use remote pins with these devices, either using it is still possible to use remote pins with these devices, either using
environment variables, or by using :meth:`~Device._set_pin_factory`: environment variables, :attr:`Device.pin_factory`, or the ``pin_factory``
keyword argument:
.. literalinclude:: examples/traffichat_remote_1.py .. literalinclude:: examples/traffichat_remote_1.py
@@ -299,10 +303,10 @@ from the computer, referencing the host by its hostname, like so:
.. note:: .. note::
When running code directly on a Raspberry Pi, any pin type can be used When running code directly on a Raspberry Pi, any pin factory can be used
(assuming the relevant library is installed), but when a device is used (assuming the relevant library is installed), but when a device is used
remotely, only :class:`PiGPIOPin` can be used, as pigpio is the only pin remotely, only :class:`PiGPIOFactory` can be used, as pigpio is the only
library which supports remote GPIO. pin library which supports remote GPIO.
.. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO .. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO

View File

@@ -448,7 +448,7 @@ def _default_pin_factory(name=os.getenv('GPIOZERO_PIN_FACTORY', None)):
except Exception as e: except Exception as e:
warnings.warn( warnings.warn(
PinFactoryFallback( PinFactoryFallback(
'Failed to load factory %s: %s' % (name, str(e)))) 'Falling back from %s: %s' % (name, str(e))))
raise BadPinFactory('Unable to load any default pin factory!') raise BadPinFactory('Unable to load any default pin factory!')
else: else:
for factory in pkg_resources.iter_entry_points(group, name.lower()): for factory in pkg_resources.iter_entry_points(group, name.lower()):

View File

@@ -30,15 +30,9 @@ from ..exc import (
class Factory(object): class Factory(object):
""" """
Generates pins, SPI, and I2C interfaces for devices. This is an abstract Generates pins and SPI interfaces for devices. This is an abstract
base class for pin factories. Descendents *must* override the following base class for pin factories. Descendents *may* override the following
methods: methods, if applicable:
* :meth:`_get_address`
* :meth:`pin_address`
Descendents *may* additionally override the following methods, if
applicable:
* :meth:`close` * :meth:`close`
* :meth:`reserve_pins` * :meth:`reserve_pins`
@@ -129,9 +123,6 @@ class Factory(object):
""" """
raise PinSPIUnsupported('SPI not supported by this pin factory') raise PinSPIUnsupported('SPI not supported by this pin factory')
def _get_address(self):
raise NotImplementedError
def _get_pi_info(self): def _get_pi_info(self):
return None return None

View File

@@ -216,7 +216,7 @@ class MockChargingPin(MockPin):
class MockTriggerPin(MockPin): class MockTriggerPin(MockPin):
""" """
This derivative of :class:`MockPin` is intended to be used with another This derivative of :class:`MockPin` is intended to be used with another
:class:`MockPin` to emulate a distance sensor. Set :attr:`echo_pin` to the :class:`MockPin` to emulate a distance sensor. Set *echo_pin* to the
corresponding pin instance. When this pin is driven high it will trigger corresponding pin instance. When this pin is driven high it will trigger
the echo pin to drive high for the echo time. the echo pin to drive high for the echo time.
""" """
@@ -410,6 +410,14 @@ class MockSPIDevice(object):
class MockFactory(LocalPiFactory): class MockFactory(LocalPiFactory):
"""
Factory for generating mock pins. The *revision* parameter specifies what
revision of Pi the mock factory pretends to be (this affects the result of
the :attr:`pi_info` attribute as well as where pull-ups are assumed to be).
The *pin_class* attribute specifies which mock pin class will be generated
by the :meth:`pin` method by default. This can be changed after
construction by modifying the :attr:`pin_class` attribute.
"""
def __init__( def __init__(
self, revision=os.getenv('GPIOZERO_MOCK_REVISION', 'a02082'), self, revision=os.getenv('GPIOZERO_MOCK_REVISION', 'a02082'),
pin_class=os.getenv('GPIOZERO_MOCK_PIN_CLASS', MockPin)): pin_class=os.getenv('GPIOZERO_MOCK_PIN_CLASS', MockPin)):
@@ -427,10 +435,22 @@ class MockFactory(LocalPiFactory):
return self._revision return self._revision
def reset(self): def reset(self):
"""
Clears the pins and reservations sets. This is primarily useful in
test suites to ensure the pin factory is back in a "clean" state before
the next set of tests are run.
"""
self.pins.clear() self.pins.clear()
self._reservations.clear() self._reservations.clear()
def pin(self, spec, pin_class=None, **kwargs): def pin(self, spec, pin_class=None, **kwargs):
"""
The pin method for :class:`MockFactory` additionally takes a *pin_class*
attribute which can be used to override the class' :attr:`pin_class`
attribute. Any additional keyword arguments will be passed along to the
pin constructor (useful with things like :class:`MockConnectedPin` which
expect to be constructed with another pin).
"""
if pin_class is None: if pin_class is None:
pin_class = self.pin_class pin_class = self.pin_class
n = self._to_gpio(spec) n = self._to_gpio(spec)

View File

@@ -161,10 +161,11 @@ class NativeFactory(LocalPiFactory):
You can construct native pin instances manually like so:: You can construct native pin instances manually like so::
from gpiozero.pins.native import NativePin from gpiozero.pins.native import NativeFactory
from gpiozero import LED from gpiozero import LED
led = LED(NativePin(12)) factory = NativeFactory()
led = LED(12, pin_factory=factory)
""" """
def __init__(self): def __init__(self):
super(NativeFactory, self).__init__() super(NativeFactory, self).__init__()
@@ -177,6 +178,9 @@ class NativeFactory(LocalPiFactory):
class NativePin(LocalPiPin): class NativePin(LocalPiPin):
"""
Native pin implementation. See :class:`NativeFactory` for more information.
"""
GPIO_FUNCTIONS = { GPIO_FUNCTIONS = {
'input': 0b000, 'input': 0b000,
'output': 0b001, 'output': 0b001,

View File

@@ -238,11 +238,11 @@ class PiPin(Pin):
self._when_changed = None self._when_changed = None
self._number = number self._number = number
try: try:
factory.pi_info.physical_pin('GPIO%d' % self.number) factory.pi_info.physical_pin(repr(self))
except PinNoPins: except PinNoPins:
warnings.warn( warnings.warn(
PinNonPhysical( PinNonPhysical(
'no physical pins exist for GPIO%d' % self.number)) 'no physical pins exist for %s' % repr(self)))
@property @property
def number(self): def number(self):

View File

@@ -46,20 +46,21 @@ class PiGPIOFactory(PiFactory):
You can construct pigpio pins manually like so:: You can construct pigpio pins manually like so::
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from gpiozero import LED from gpiozero import LED
led = LED(PiGPIOPin(12)) factory = PiGPIOFactory()
led = LED(12, pin_factory=factory)
This is particularly useful for controlling pins on a remote machine. To This is particularly useful for controlling pins on a remote machine. To
accomplish this simply specify the host (and optionally port) when accomplish this simply specify the host (and optionally port) when
constructing the pin:: constructing the pin::
from gpiozero.pins.pigpio import PiGPIOPin from gpiozero.pins.pigpio import PiGPIOFactory
from gpiozero import LED from gpiozero import LED
from signal import pause
led = LED(PiGPIOPin(12, host='192.168.0.2')) factory = PiGPIOFactory(host='192.168.0.2')
led = LED(12, pin_factory=factory)
.. note:: .. note::
@@ -132,6 +133,12 @@ class PiGPIOFactory(PiFactory):
class PiGPIOPin(PiPin): class PiGPIOPin(PiPin):
"""
Pin implementation for the `pigpio`_ library. See :class:`PiGPIOFactory`
for more information.
.. _pigpio: http://abyz.co.uk/rpi/pigpio/
"""
_CONNECTIONS = {} # maps (host, port) to (connection, pi_info) _CONNECTIONS = {} # maps (host, port) to (connection, pi_info)
GPIO_FUNCTIONS = { GPIO_FUNCTIONS = {
'input': pigpio.INPUT, 'input': pigpio.INPUT,
@@ -162,7 +169,7 @@ class PiGPIOPin(PiPin):
def __init__(self, factory, number): def __init__(self, factory, number):
super(PiGPIOPin, self).__init__(factory, number) super(PiGPIOPin, self).__init__(factory, number)
self._pull = 'up' if factory.pi_info.pulled_up(repr(self)) else 'floating' self._pull = 'up' if self.factory.pi_info.pulled_up(repr(self)) else 'floating'
self._pwm = False self._pwm = False
self._bounce = None self._bounce = None
self._callback = None self._callback = None
@@ -289,6 +296,12 @@ class PiGPIOPin(PiPin):
class PiGPIOHardwareSPI(SPI, Device): class PiGPIOHardwareSPI(SPI, Device):
"""
Hardware SPI implementation for the `pigpio`_ library. Uses the ``spi_*``
functions from the pigpio API.
.. _pigpio: http://abyz.co.uk/rpi/pigpio/
"""
def __init__(self, factory, port, device): def __init__(self, factory, port, device):
self._port = port self._port = port
self._device = device self._device = device
@@ -385,6 +398,12 @@ class PiGPIOHardwareSPI(SPI, Device):
class PiGPIOSoftwareSPI(SPI, Device): class PiGPIOSoftwareSPI(SPI, Device):
"""
Software SPI implementation for the `pigpio`_ library. Uses the ``bb_spi_*``
functions from the pigpio API.
.. _pigpio: http://abyz.co.uk/rpi/pigpio/
"""
def __init__(self, factory, clock_pin, mosi_pin, miso_pin, select_pin): def __init__(self, factory, clock_pin, mosi_pin, miso_pin, select_pin):
self._closed = True self._closed = True
self._select_pin = select_pin self._select_pin = select_pin

View File

@@ -40,7 +40,8 @@ class RPiGPIOFactory(LocalPiFactory):
from gpiozero.pins.rpigpio import RPiGPIOFactory from gpiozero.pins.rpigpio import RPiGPIOFactory
from gpiozero import LED from gpiozero import LED
led = LED(RPiGPIOPin(12)) factory = RPiGPIOFactory()
led = LED(12, pin_factory=factory)
.. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO .. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO
""" """
@@ -57,6 +58,12 @@ class RPiGPIOFactory(LocalPiFactory):
class RPiGPIOPin(LocalPiPin): class RPiGPIOPin(LocalPiPin):
"""
Pin implementation for the `RPi.GPIO`_ library. See :class:`RPiGPIOFactory`
for more information.
.. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO
"""
GPIO_FUNCTIONS = { GPIO_FUNCTIONS = {
'input': GPIO.IN, 'input': GPIO.IN,
'output': GPIO.OUT, 'output': GPIO.OUT,
@@ -85,7 +92,7 @@ class RPiGPIOPin(LocalPiPin):
def __init__(self, factory, number): def __init__(self, factory, number):
super(RPiGPIOPin, self).__init__(factory, number) super(RPiGPIOPin, self).__init__(factory, number)
self._pull = 'up' if self.factory.pi_info.pulled_up(self.address[-1]) else 'floating' self._pull = 'up' if self.factory.pi_info.pulled_up(repr(self)) else 'floating'
self._pwm = None self._pwm = None
self._frequency = None self._frequency = None
self._duty_cycle = None self._duty_cycle = None
@@ -103,7 +110,7 @@ class RPiGPIOPin(LocalPiPin):
GPIO.setup(self.number, GPIO.OUT, initial=state) GPIO.setup(self.number, GPIO.OUT, initial=state)
def input_with_pull(self, pull): def input_with_pull(self, pull):
if pull != 'up' and self.factory.pi_info.pulled_up(self.address[-1]): if pull != 'up' and self.factory.pi_info.pulled_up(repr(self)):
raise PinFixedPull('%r has a physical pull-up resistor' % self) raise PinFixedPull('%r has a physical pull-up resistor' % self)
try: try:
GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[pull]) GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[pull])
@@ -149,7 +156,7 @@ class RPiGPIOPin(LocalPiPin):
def _set_pull(self, value): def _set_pull(self, value):
if self.function != 'input': if self.function != 'input':
raise PinFixedPull('cannot set pull on non-input pin %r' % self) raise PinFixedPull('cannot set pull on non-input pin %r' % self)
if value != 'up' and self.factory.pi_info.pulled_up(self.address[-1]): if value != 'up' and self.factory.pi_info.pulled_up(repr(self)):
raise PinFixedPull('%r has a physical pull-up resistor' % self) raise PinFixedPull('%r has a physical pull-up resistor' % self)
try: try:
GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[value]) GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[value])

View File

@@ -40,10 +40,11 @@ class RPIOFactory(LocalPiFactory):
You can construct RPIO pins manually like so:: You can construct RPIO pins manually like so::
from gpiozero.pins.rpio import RPIOPin from gpiozero.pins.rpio import RPIOFactory
from gpiozero import LED from gpiozero import LED
led = LED(RPIOPin(12)) factory = RPIOFactory()
led = LED(12, pin_factory=factory)
.. _RPIO: https://pythonhosted.org/RPIO/ .. _RPIO: https://pythonhosted.org/RPIO/
""" """
@@ -63,6 +64,12 @@ class RPIOFactory(LocalPiFactory):
class RPIOPin(LocalPiPin): class RPIOPin(LocalPiPin):
"""
Pin implementation for the `RPIO`_ library. See :class:`RPIOFactory` for
more information.
.. _RPIO: https://pythonhosted.org/RPIO/
"""
GPIO_FUNCTIONS = { GPIO_FUNCTIONS = {
'input': RPIO.IN, 'input': RPIO.IN,
'output': RPIO.OUT, 'output': RPIO.OUT,
@@ -80,7 +87,7 @@ class RPIOPin(LocalPiPin):
def __init__(self, factory, number): def __init__(self, factory, number):
super(RPIOPin, self).__init__(factory, number) super(RPIOPin, self).__init__(factory, number)
self._pull = 'up' if self.factory.pi_info.pulled_up(self.address[-1]) else 'floating' self._pull = 'up' if self.factory.pi_info.pulled_up(repr(self)) else 'floating'
self._pwm = False self._pwm = False
self._duty_cycle = None self._duty_cycle = None
self._bounce = None self._bounce = None
@@ -138,7 +145,7 @@ class RPIOPin(LocalPiPin):
def _set_pull(self, value): def _set_pull(self, value):
if self.function != 'input': if self.function != 'input':
raise PinFixedPull('cannot set pull on non-input pin %r' % self) raise PinFixedPull('cannot set pull on non-input pin %r' % self)
if value != 'up' and self.factory.pi_info.pulled_up(self.address[-1]): if value != 'up' and self.factory.pi_info.pulled_up(repr(self)):
raise PinFixedPull('%r has a physical pull-up resistor' % self) raise PinFixedPull('%r has a physical pull-up resistor' % self)
try: try:
RPIO.setup(self.number, RPIO.IN, self.GPIO_PULL_UPS[value]) RPIO.setup(self.number, RPIO.IN, self.GPIO_PULL_UPS[value])