mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Merge branch 'master' of github.com:rpi-distro/python-gpiozero
This commit is contained in:
		| @@ -16,6 +16,7 @@ from .exc import ( | ||||
|     GPIOPinInUse, | ||||
|     GPIOPinMissing, | ||||
|     GPIOBadQueueLen, | ||||
|     GPIOBadSampleWait, | ||||
|     InputDeviceError, | ||||
|     OutputDeviceError, | ||||
|     OutputDeviceBadValue, | ||||
| @@ -48,6 +49,7 @@ from .input_devices import ( | ||||
|     LineSensor, | ||||
|     MotionSensor, | ||||
|     LightSensor, | ||||
|     DistanceSensor, | ||||
|     AnalogInputDevice, | ||||
|     MCP3008, | ||||
|     MCP3004, | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| # vim: set fileencoding=utf-8: | ||||
|  | ||||
| from __future__ import ( | ||||
|     unicode_literals, | ||||
|     absolute_import, | ||||
| @@ -25,3 +27,27 @@ def isclose(a, b, rel_tol=1e-9, abs_tol=0.0): | ||||
|         (diff <= abs(rel_tol * a)) or | ||||
|         (diff <= abs_tol) | ||||
|         ) | ||||
|  | ||||
|  | ||||
| # Backported from py3.4 | ||||
| def mean(data): | ||||
|     if iter(data) is data: | ||||
|         data = list(data) | ||||
|     n = len(data) | ||||
|     if not n: | ||||
|         raise ValueError('cannot calculate mean of empty data') | ||||
|     return sum(data) / n | ||||
|  | ||||
|  | ||||
| # Backported from py3.4 | ||||
| def median(data): | ||||
|     data = sorted(data) | ||||
|     n = len(data) | ||||
|     if not n: | ||||
|         raise ValueError('cannot calculate median of empty data') | ||||
|     elif n % 2: | ||||
|         return data[n // 2] | ||||
|     else: | ||||
|         i = n // 2 | ||||
|         return (data[n - 1] + data[n]) / 2 | ||||
|  | ||||
|   | ||||
| @@ -12,12 +12,17 @@ import weakref | ||||
| from threading import Thread, Event, RLock | ||||
| from collections import deque | ||||
| from types import FunctionType | ||||
| try: | ||||
|     from statistics import median, mean | ||||
| except ImportError: | ||||
|     from .compat import median, mean | ||||
|  | ||||
| from .exc import ( | ||||
|     GPIOPinMissing, | ||||
|     GPIOPinInUse, | ||||
|     GPIODeviceClosed, | ||||
|     GPIOBadQueueLen, | ||||
|     GPIOBadSampleWait, | ||||
|     ) | ||||
|  | ||||
| # Get a pin implementation to use as the default; we prefer RPi.GPIO's here | ||||
| @@ -33,8 +38,12 @@ except ImportError: | ||||
|         from .pins.rpio import RPIOPin | ||||
|         DefaultPin = RPIOPin | ||||
|     except ImportError: | ||||
|         from .pins.native import NativePin | ||||
|         DefaultPin = NativePin | ||||
|         try: | ||||
|             from .pins.pigipod import PiGPIOPin | ||||
|             DefaultPin = PiGPIOPin | ||||
|         except ImportError: | ||||
|             from .pins.native import NativePin | ||||
|             DefaultPin = NativePin | ||||
|  | ||||
|  | ||||
| _THREADS = set() | ||||
| @@ -344,23 +353,29 @@ class GPIOThread(Thread): | ||||
|  | ||||
|  | ||||
| class GPIOQueue(GPIOThread): | ||||
|     def __init__(self, parent, queue_len=5, sample_wait=0.0, partial=False): | ||||
|     def __init__( | ||||
|             self, parent, queue_len=5, sample_wait=0.0, partial=False, | ||||
|             average=median): | ||||
|         assert isinstance(parent, GPIODevice) | ||||
|         assert callable(average) | ||||
|         super(GPIOQueue, self).__init__(target=self.fill) | ||||
|         if queue_len < 1: | ||||
|             raise GPIOBadQueueLen('queue_len must be at least one') | ||||
|         if sample_wait < 0: | ||||
|             raise GPIOBadSampleWait('sample_wait must be 0 or greater') | ||||
|         self.queue = deque(maxlen=queue_len) | ||||
|         self.partial = partial | ||||
|         self.sample_wait = sample_wait | ||||
|         self.full = Event() | ||||
|         self.parent = weakref.proxy(parent) | ||||
|         self.average = average | ||||
|  | ||||
|     @property | ||||
|     def value(self): | ||||
|         if not self.partial: | ||||
|             self.full.wait() | ||||
|         try: | ||||
|             return sum(self.queue) / len(self.queue) | ||||
|             return self.average(self.queue) | ||||
|         except ZeroDivisionError: | ||||
|             # No data == inactive value | ||||
|             return 0.0 | ||||
|   | ||||
| @@ -28,6 +28,9 @@ class GPIOPinMissing(GPIODeviceError, ValueError): | ||||
| class GPIOBadQueueLen(GPIODeviceError, ValueError): | ||||
|     "Error raised when non-positive queue length is specified" | ||||
|  | ||||
| class GPIOBadSampleWait(GPIODeviceError, ValueError): | ||||
|     "Error raised when a negative sampling wait period is specified" | ||||
|  | ||||
| class InputDeviceError(GPIODeviceError): | ||||
|     "Base class for errors specific to the InputDevice hierarchy" | ||||
|  | ||||
|   | ||||
| @@ -572,6 +572,194 @@ LightSensor.wait_for_light = LightSensor.wait_for_active | ||||
| LightSensor.wait_for_dark = LightSensor.wait_for_inactive | ||||
|  | ||||
|  | ||||
| class DistanceSensor(SmoothedInputDevice): | ||||
|     """ | ||||
|     Extends :class:`SmoothedInputDevice` and represents an HC-SR04 ultrasonic | ||||
|     distance sensor, as found in the `CamJam #3 EduKit`_. | ||||
|  | ||||
|     The distance sensor requires two GPIO pins: one for the *trigger* (marked | ||||
|     TRIG on the sensor) and another for the *echo* (marked ECHO on the sensor). | ||||
|     However, a voltage divider is required to ensure the 5V from the ECHO pin | ||||
|     doesn't damage the Pi. Wire your sensor according to the following | ||||
|     instructions: | ||||
|  | ||||
|     1. Connect the GND pin of the sensor to a ground pin on the Pi. | ||||
|  | ||||
|     2. Connect the TRIG pin of the sensor a GPIO pin. | ||||
|  | ||||
|     3. Connect a 330Ω resistor from the ECHO pin of the sensor to a different | ||||
|        GPIO pin. | ||||
|  | ||||
|     4. Connect a 470Ω resistor from ground to the ECHO GPIO pin. This forms | ||||
|        the required voltage divider. | ||||
|  | ||||
|     5. Finally, connect the VCC pin of the sensor to a 5V pin on the Pi. | ||||
|  | ||||
|     The following code will periodically report the distance measured by the | ||||
|     sensor in cm assuming the TRIG pin is connected to GPIO17, and the ECHO | ||||
|     pin to GPIO18:: | ||||
|  | ||||
|         from gpiozero import DistanceSensor | ||||
|         from time import sleep | ||||
|  | ||||
|         sensor = DistanceSensor(18, 17) | ||||
|         while True: | ||||
|             print('Distance: ', sensor.distance * 100) | ||||
|             sleep(1) | ||||
|  | ||||
|     :param int echo: | ||||
|         The GPIO pin which the ECHO pin is attached to. See :doc:`notes` for | ||||
|         valid pin numbers. | ||||
|  | ||||
|     :param int trigger: | ||||
|         The GPIO pin which the TRIG pin is attached to. See :doc:`notes` for | ||||
|         valid pin numbers. | ||||
|  | ||||
|     :param int queue_len: | ||||
|         The length of the queue used to store values read from the sensor. | ||||
|         This defaults to 30. | ||||
|  | ||||
|     :param float max_distance: | ||||
|         The :attr:`value` attribute reports a normalized value between 0 (too | ||||
|         close to measure) and 1 (maximum distance). This parameter specifies | ||||
|         the maximum distance expected in meters. This defaults to 1. | ||||
|  | ||||
|     :param float threshold_distance: | ||||
|         Defaults to 0.3. This is the distance (in meters) that will trigger the | ||||
|         ``in_range`` and ``out_of_range`` events when crossed. | ||||
|  | ||||
|     :param bool partial: | ||||
|         When ``False`` (the default), the object will not return a value for | ||||
|         :attr:`~SmoothedInputDevice.is_active` until the internal queue has | ||||
|         filled with values.  Only set this to ``True`` if you require values | ||||
|         immediately after object construction. | ||||
|  | ||||
|     .. _CamJam #3 EduKit: http://camjam.me/?page_id=1035 | ||||
|     """ | ||||
|     def __init__( | ||||
|             self, echo=None, trigger=None, queue_len=30, max_distance=1, | ||||
|             threshold_distance=0.3, partial=False): | ||||
|         if not (max_distance > 0): | ||||
|             raise ValueError('invalid maximum distance (must be positive)') | ||||
|         self._trigger = None | ||||
|         super(DistanceSensor, self).__init__( | ||||
|             echo, pull_up=False, threshold=threshold_distance / max_distance, | ||||
|             queue_len=queue_len, sample_wait=0.0, partial=partial | ||||
|         ) | ||||
|         try: | ||||
|             self.speed_of_sound = 343.26 # m/s | ||||
|             self._max_distance = max_distance | ||||
|             self._trigger = GPIODevice(trigger) | ||||
|             self._echo = Event() | ||||
|             self._trigger.pin.function = 'output' | ||||
|             self._trigger.pin.state = False | ||||
|             self.pin.edges = 'both' | ||||
|             self.pin.bounce = None | ||||
|             self.pin.when_changed = self._echo.set | ||||
|             self._queue.start() | ||||
|         except: | ||||
|             self.close() | ||||
|             raise | ||||
|  | ||||
|     def close(self): | ||||
|         try: | ||||
|             self._trigger.close() | ||||
|         except AttributeError: | ||||
|             if self._trigger is not None: | ||||
|                 raise | ||||
|         else: | ||||
|             self._trigger = None | ||||
|         super(DistanceSensor, self).close() | ||||
|  | ||||
|     @property | ||||
|     def max_distance(self): | ||||
|         """ | ||||
|         The maximum distance that the sensor will measure in meters. This value | ||||
|         is specified in the constructor and is used to provide the scaling | ||||
|         for the :attr:`value` attribute. When :attr:`distance` is equal to | ||||
|         :attr:`max_distance`, :attr:`value` will be 1. | ||||
|         """ | ||||
|         return self._max_distance | ||||
|  | ||||
|     @max_distance.setter | ||||
|     def max_distance(self, value): | ||||
|         if not (value > 0): | ||||
|             raise ValueError('invalid maximum distance (must be positive)') | ||||
|         t = self.threshold_distance | ||||
|         self._max_distance = value | ||||
|         self.threshold_distance = t | ||||
|  | ||||
|     @property | ||||
|     def threshold_distance(self): | ||||
|         """ | ||||
|         The distance, measured in meters, that will trigger the | ||||
|         :attr:`when_in_range` and :attr:`when_out_of_range` events when | ||||
|         crossed. This is simply a meter-scaled variant of the usual | ||||
|         :attr:`threshold` attribute. | ||||
|         """ | ||||
|         return self.threshold * self.max_distance | ||||
|  | ||||
|     @threshold_distance.setter | ||||
|     def threshold_distance(self, value): | ||||
|         self.threshold = value / self.max_distance | ||||
|  | ||||
|     @property | ||||
|     def distance(self): | ||||
|         """ | ||||
|         Returns the current distance measured by the sensor in meters. Note | ||||
|         that this property will have a value between 0 and | ||||
|         :attr:`max_distance`. | ||||
|         """ | ||||
|         return self.value * self._max_distance | ||||
|  | ||||
|     @property | ||||
|     def trigger(self): | ||||
|         """ | ||||
|         Returns the :class:`Pin` that the sensor's trigger is connected to. | ||||
|         """ | ||||
|         return self._trigger.pin | ||||
|  | ||||
|     @property | ||||
|     def echo(self): | ||||
|         """ | ||||
|         Returns the :class:`Pin` that the sensor's echo is connected to. This | ||||
|         is simply an alias for the usual :attr:`pin` attribute. | ||||
|         """ | ||||
|         return self.pin | ||||
|  | ||||
|     def _read(self): | ||||
|         # Make sure the echo event is clear | ||||
|         self._echo.clear() | ||||
|         # Fire the trigger | ||||
|         self._trigger.pin.state = True | ||||
|         sleep(0.00001) | ||||
|         self._trigger.pin.state = False | ||||
|         # Wait up to 1 second for the echo pin to rise | ||||
|         if self._echo.wait(1): | ||||
|             start = time() | ||||
|             self._echo.clear() | ||||
|             # Wait up to 40ms for the echo pin to fall (35ms is maximum pulse | ||||
|             # time so any longer means something's gone wrong). Calculate | ||||
|             # distance as time for echo multiplied by speed of sound divided by | ||||
|             # two to compensate for travel to and from the reflector | ||||
|             if self._echo.wait(0.04): | ||||
|                 distance = (time() - start) * self.speed_of_sound / 2.0 | ||||
|                 return min(1.0, distance / self._max_distance) | ||||
|             else: | ||||
|                 # If we only saw one edge it means we missed the echo because | ||||
|                 # it was too fast; report minimum distance | ||||
|                 return 0.0 | ||||
|         else: | ||||
|             # The echo pin never rose or fell; something's gone horribly | ||||
|             # wrong (XXX raise a warning?) | ||||
|             return 1.0 | ||||
|  | ||||
| DistanceSensor.when_out_of_range = DistanceSensor.when_activated | ||||
| DistanceSensor.when_in_range = DistanceSensor.when_deactivated | ||||
| DistanceSensor.wait_for_out_of_range = DistanceSensor.wait_for_active | ||||
| DistanceSensor.wait_for_in_range = DistanceSensor.wait_for_inactive | ||||
|  | ||||
|  | ||||
| class AnalogInputDevice(CompositeDevice): | ||||
|     """ | ||||
|     Represents an analog input device connected to SPI (serial interface). | ||||
|   | ||||
| @@ -156,6 +156,13 @@ class NativePin(Pin): | ||||
|         use any class which requests PWM will raise an exception. This | ||||
|         implementation is also experimental; we make no guarantees it will | ||||
|         not eat your Pi for breakfast! | ||||
|  | ||||
|     You can construct native pin instances manually like so:: | ||||
|  | ||||
|         from gpiozero.pins.native import NativePin | ||||
|         from gpiozero import LED | ||||
|  | ||||
|         led = LED(NativePin(12)) | ||||
|     """ | ||||
|  | ||||
|     _MEM = None | ||||
|   | ||||
							
								
								
									
										240
									
								
								gpiozero/pins/pigpiod.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								gpiozero/pins/pigpiod.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,240 @@ | ||||
| from __future__ import ( | ||||
|     unicode_literals, | ||||
|     absolute_import, | ||||
|     print_function, | ||||
|     division, | ||||
|     ) | ||||
| str = type('') | ||||
|  | ||||
| import pigpio | ||||
|  | ||||
| from . import Pin | ||||
| from ..exc import ( | ||||
|     PinInvalidFunction, | ||||
|     PinSetInput, | ||||
|     PinFixedPull, | ||||
|     ) | ||||
|  | ||||
|  | ||||
| class PiGPIOPin(Pin): | ||||
|     """ | ||||
|     Uses the `pigpio`_ library to interface to the Pi's GPIO pins. The pigpio | ||||
|     library relies on a daemon (``pigpiod``) to be running as root to provide | ||||
|     access to the GPIO pins, and communicates with this daemon over a network | ||||
|     socket. | ||||
|  | ||||
|     While this does mean only the daemon itself should control the pins, the | ||||
|     architecture does have several advantages: | ||||
|  | ||||
|     * Pins can be remote controlled from another machine (the other | ||||
|       machine doesn't even have to be a Raspberry Pi; it simply needs the | ||||
|       `pigpio`_ client library installed on it) | ||||
|     * The daemon supports hardware PWM via the DMA controller | ||||
|     * Your script itself doesn't require root privileges; it just needs to | ||||
|       be able to communicate with the daemon | ||||
|  | ||||
|     You can construct pigpiod pins manually like so:: | ||||
|  | ||||
|         from gpiozero.pins.pigpiod import PiGPIOPin | ||||
|         from gpiozero import LED | ||||
|  | ||||
|         led = LED(PiGPIOPin(12)) | ||||
|  | ||||
|     This is particularly useful for controlling pins on a remote machine. To | ||||
|     accomplish this simply specify the host (and optionally port) when | ||||
|     constructing the pin:: | ||||
|  | ||||
|         from gpiozero.pins.pigpiod import PiGPIOPin | ||||
|         from gpiozero import LED | ||||
|         from signal import pause | ||||
|  | ||||
|         led = LED(PiGPIOPin(12, host='192.168.0.2')) | ||||
|  | ||||
|     .. note:: | ||||
|  | ||||
|         In some circumstances, especially when playing with PWM, it does appear | ||||
|         to be possible to get the daemon into "unusual" states. We would be | ||||
|         most interested to hear any bug reports relating to this (it may be a | ||||
|         bug in our pin implementation). A workaround for now is simply to | ||||
|         restart the ``pigpiod`` daemon. | ||||
|  | ||||
|     .. _pigpio: http://abyz.co.uk/rpi/pigpio/ | ||||
|     """ | ||||
|  | ||||
|     _CONNECTIONS = {} | ||||
|     _PINS = {} | ||||
|  | ||||
|     GPIO_FUNCTIONS = { | ||||
|         'input':   pigpio.INPUT, | ||||
|         'output':  pigpio.OUTPUT, | ||||
|         'alt0':    pigpio.ALT0, | ||||
|         'alt1':    pigpio.ALT1, | ||||
|         'alt2':    pigpio.ALT2, | ||||
|         'alt3':    pigpio.ALT3, | ||||
|         'alt4':    pigpio.ALT4, | ||||
|         'alt5':    pigpio.ALT5, | ||||
|         } | ||||
|  | ||||
|     GPIO_PULL_UPS = { | ||||
|         'up':       pigpio.PUD_UP, | ||||
|         'down':     pigpio.PUD_DOWN, | ||||
|         'floating': pigpio.PUD_OFF, | ||||
|         } | ||||
|  | ||||
|     GPIO_EDGES = { | ||||
|         'both':    pigpio.EITHER_EDGE, | ||||
|         'rising':  pigpio.RISING_EDGE, | ||||
|         'falling': pigpio.FALLING_EDGE, | ||||
|         } | ||||
|  | ||||
|     GPIO_FUNCTION_NAMES = {v: k for (k, v) in GPIO_FUNCTIONS.items()} | ||||
|     GPIO_PULL_UP_NAMES = {v: k for (k, v) in GPIO_PULL_UPS.items()} | ||||
|     GPIO_EDGES_NAMES = {v: k for (k, v) in GPIO_EDGES.items()} | ||||
|  | ||||
|     def __new__(cls, number, host='localhost', port=8888): | ||||
|         try: | ||||
|             return cls._PINS[(host, port, number)] | ||||
|         except KeyError: | ||||
|             self = super(PiGPIOPin, cls).__new__(cls) | ||||
|             cls._PINS[(host, port, number)] = self | ||||
|             try: | ||||
|                 self._connection = cls._CONNECTIONS[(host, port)] | ||||
|             except KeyError: | ||||
|                 self._connection = pigpio.pi(host, port) | ||||
|                 cls._CONNECTIONS[(host, port)] = self._connection | ||||
|             self._host = host | ||||
|             self._port = port | ||||
|             self._number = number | ||||
|             self._pull = 'up' if number in (2, 3) else 'floating' | ||||
|             self._pwm = False | ||||
|             self._bounce = None | ||||
|             self._when_changed = None | ||||
|             self._callback = None | ||||
|             self._edges = pigpio.EITHER_EDGE | ||||
|             self._connection.set_mode(self._number, pigpio.INPUT) | ||||
|             self._connection.set_pull_up_down(self._number, self.GPIO_PULL_UPS[self._pull]) | ||||
|             self._connection.set_glitch_filter(self._number, 0) | ||||
|             self._connection.set_PWM_range(self._number, 255) | ||||
|             return self | ||||
|  | ||||
|     def __repr__(self): | ||||
|         if self._host == 'localhost': | ||||
|             return "GPIO%d" % self._number | ||||
|         else: | ||||
|             return "GPIO%d on %s:%d" % (self._host, self._port) | ||||
|  | ||||
|     @property | ||||
|     def host(self): | ||||
|         return self._host | ||||
|  | ||||
|     @property | ||||
|     def port(self): | ||||
|         return self._port | ||||
|  | ||||
|     @property | ||||
|     def number(self): | ||||
|         return self._number | ||||
|  | ||||
|     def close(self): | ||||
|         # If we're shutting down, the connection may have disconnected itself | ||||
|         # already. Unfortunately, the connection's "connected" property is | ||||
|         # rather buggy - disconnecting doesn't set it to False! So we're | ||||
|         # naughty and check an internal variable instead... | ||||
|         if self._connection.sl.s is not None: | ||||
|             self.frequency = None | ||||
|             self.when_changed = None | ||||
|             self.function = 'input' | ||||
|             self.pull = 'floating' | ||||
|  | ||||
|     def _get_function(self): | ||||
|         return self.GPIO_FUNCTION_NAMES[self._connection.get_mode(self._number)] | ||||
|  | ||||
|     def _set_function(self, value): | ||||
|         if value != 'input': | ||||
|             self._pull = 'floating' | ||||
|         try: | ||||
|             self._connection.set_mode(self._number, self.GPIO_FUNCTIONS[value]) | ||||
|         except KeyError: | ||||
|             raise PinInvalidFunction('invalid function "%s" for pin %r' % (value, self)) | ||||
|  | ||||
|     def _get_state(self): | ||||
|         if self._pwm: | ||||
|             return self._connection.get_PWM_dutycycle(self._number) / 255 | ||||
|         else: | ||||
|             return bool(self._connection.read(self._number)) | ||||
|  | ||||
|     def _set_state(self, value): | ||||
|         if self._pwm: | ||||
|             try: | ||||
|                 self._connection.set_PWM_dutycycle(self._number, int(value * 255)) | ||||
|             except pigpio.error: | ||||
|                 raise PinInvalidValue('invalid state "%s" for pin %r' % (value, self)) | ||||
|         elif self.function == 'input': | ||||
|             raise PinSetInput('cannot set state of pin %r' % self) | ||||
|         else: | ||||
|             # write forces pin to OUTPUT, hence the check above | ||||
|             self._connection.write(self._number, bool(value)) | ||||
|  | ||||
|     def _get_pull(self): | ||||
|         return self._pull | ||||
|  | ||||
|     def _set_pull(self, value): | ||||
|         if self.function != 'input': | ||||
|             raise PinFixedPull('cannot set pull on non-input pin %r' % self) | ||||
|         if value != 'up' and self._number in (2, 3): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             self._connection.set_pull_up_down(self._number, self.GPIO_PULL_UPS[value]) | ||||
|             self._pull = value | ||||
|         except KeyError: | ||||
|             raise PinInvalidPull('invalid pull "%s" for pin %r' % (value, self)) | ||||
|  | ||||
|     def _get_frequency(self): | ||||
|         if self._pwm: | ||||
|             return self._connection.get_PWM_frequency(self._number) | ||||
|         return None | ||||
|  | ||||
|     def _set_frequency(self, value): | ||||
|         if not self._pwm and value is not None: | ||||
|             self._connection.set_PWM_frequency(self._number, value) | ||||
|             self._connection.set_PWM_dutycycle(self._number, 0) | ||||
|             self._pwm = True | ||||
|         elif self._pwm and value is not None: | ||||
|             self._connection.set_PWM_frequency(self._number, value) | ||||
|         elif self._pwm and value is None: | ||||
|             self._connection.set_PWM_dutycycle(self._number, 0) | ||||
|             self._pwm = False | ||||
|  | ||||
|     def _get_bounce(self): | ||||
|         return None if not self._bounce else self._bounce / 1000000 | ||||
|  | ||||
|     def _set_bounce(self, value): | ||||
|         if value is None: | ||||
|             value = 0 | ||||
|         self._connection.set_glitch_filter(self._number, int(value * 1000000)) | ||||
|  | ||||
|     def _get_edges(self): | ||||
|         return self.GPIO_EDGES_NAMES[self._edges] | ||||
|  | ||||
|     def _set_edges(self, value): | ||||
|         f = self.when_changed | ||||
|         self.when_changed = None | ||||
|         try: | ||||
|             self._edges = self.GPIO_EDGES[value] | ||||
|         finally: | ||||
|             self.when_changed = f | ||||
|  | ||||
|     def _get_when_changed(self): | ||||
|         if self._callback is None: | ||||
|             return None | ||||
|         return self._callback.callb.func | ||||
|  | ||||
|     def _set_when_changed(self, value): | ||||
|         if self._callback is not None: | ||||
|             self._callback.cancel() | ||||
|             self._callback = None | ||||
|         if value is not None: | ||||
|             self._callback = self._connection.callback( | ||||
|                     self._number, self._edges, | ||||
|                     lambda gpio, level, tick: value()) | ||||
|  | ||||
| @@ -22,6 +22,20 @@ class RPiGPIOPin(Pin): | ||||
|     the default pin implementation if the RPi.GPIO library is installed. | ||||
|     Supports all features including PWM (via software). | ||||
|  | ||||
|     Because this is the default pin implementation you can use it simply by | ||||
|     specifying an integer number for the pin in most operations, e.g.:: | ||||
|  | ||||
|         from gpiozero import LED | ||||
|  | ||||
|         led = LED(12) | ||||
|  | ||||
|     However, you can also construct RPi.GPIO pins manually if you wish:: | ||||
|  | ||||
|         from gpiozero.pins.rpigpio import RPiGPIOPin | ||||
|         from gpiozero import LED | ||||
|  | ||||
|         led = LED(RPiGPIOPin(12)) | ||||
|  | ||||
|     .. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO | ||||
|     """ | ||||
|  | ||||
|   | ||||
| @@ -32,6 +32,13 @@ class RPIOPin(Pin): | ||||
|         Pi 1's; the Raspberry Pi 2 Model B is *not* supported. Also note that | ||||
|         root access is required so scripts must typically be run with ``sudo``. | ||||
|  | ||||
|     You can construct RPIO pins manually like so:: | ||||
|  | ||||
|         from gpiozero.pins.rpio import RPIOPin | ||||
|         from gpiozero import LED | ||||
|  | ||||
|         led = LED(RPIOPin(12)) | ||||
|  | ||||
|     .. _RPIO: https://pythonhosted.org/RPIO/ | ||||
|     """ | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user