mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			221 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			221 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from __future__ import (
 | |
|     unicode_literals,
 | |
|     absolute_import,
 | |
|     print_function,
 | |
|     division,
 | |
|     )
 | |
| str = type('')
 | |
| 
 | |
| import warnings
 | |
| from RPi import GPIO
 | |
| 
 | |
| from .local import LocalPiFactory, LocalPiPin
 | |
| from ..exc import (
 | |
|     PinInvalidFunction,
 | |
|     PinSetInput,
 | |
|     PinFixedPull,
 | |
|     PinInvalidPull,
 | |
|     PinInvalidState,
 | |
|     PinInvalidBounce,
 | |
|     PinPWMFixedValue,
 | |
|     )
 | |
| 
 | |
| 
 | |
| class RPiGPIOFactory(LocalPiFactory):
 | |
|     """
 | |
|     Uses the `RPi.GPIO`_ library to interface to the Pi's GPIO pins. This is
 | |
|     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 RPiGPIOFactory
 | |
|         from gpiozero import LED
 | |
| 
 | |
|         led = LED(RPiGPIOPin(12))
 | |
| 
 | |
|     .. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO
 | |
|     """
 | |
| 
 | |
|     def __init__(self):
 | |
|         super(RPiGPIOFactory, self).__init__()
 | |
|         GPIO.setmode(GPIO.BCM)
 | |
|         GPIO.setwarnings(False)
 | |
|         self.pin_class = RPiGPIOPin
 | |
| 
 | |
|     def close(self):
 | |
|         super(RPiGPIOFactory, self).close()
 | |
|         GPIO.cleanup()
 | |
| 
 | |
| 
 | |
| class RPiGPIOPin(LocalPiPin):
 | |
|     GPIO_FUNCTIONS = {
 | |
|         'input':   GPIO.IN,
 | |
|         'output':  GPIO.OUT,
 | |
|         'i2c':     GPIO.I2C,
 | |
|         'spi':     GPIO.SPI,
 | |
|         'pwm':     GPIO.HARD_PWM,
 | |
|         'serial':  GPIO.SERIAL,
 | |
|         'unknown': GPIO.UNKNOWN,
 | |
|         }
 | |
| 
 | |
|     GPIO_PULL_UPS = {
 | |
|         'up':       GPIO.PUD_UP,
 | |
|         'down':     GPIO.PUD_DOWN,
 | |
|         'floating': GPIO.PUD_OFF,
 | |
|         }
 | |
| 
 | |
|     GPIO_EDGES = {
 | |
|         'both':    GPIO.BOTH,
 | |
|         'rising':  GPIO.RISING,
 | |
|         'falling': GPIO.FALLING,
 | |
|         }
 | |
| 
 | |
|     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 __init__(self, factory, number):
 | |
|         super(RPiGPIOPin, self).__init__(factory, number)
 | |
|         self._pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | |
|         self._pwm = None
 | |
|         self._frequency = None
 | |
|         self._duty_cycle = None
 | |
|         self._bounce = -666
 | |
|         self._when_changed = None
 | |
|         self._edges = GPIO.BOTH
 | |
|         GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[self._pull])
 | |
| 
 | |
|     def close(self):
 | |
|         self.frequency = None
 | |
|         self.when_changed = None
 | |
|         GPIO.cleanup(self.number)
 | |
| 
 | |
|     def output_with_state(self, state):
 | |
|         self._pull = 'floating'
 | |
|         GPIO.setup(self.number, GPIO.OUT, initial=state)
 | |
| 
 | |
|     def input_with_pull(self, pull):
 | |
|         if pull != 'up' and self.factory.pi_info.pulled_up(self.address[-1]):
 | |
|             raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | |
|         try:
 | |
|             GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[pull])
 | |
|             self._pull = pull
 | |
|         except KeyError:
 | |
|             raise PinInvalidPull('invalid pull "%s" for pin %r' % (pull, self))
 | |
| 
 | |
|     def _get_function(self):
 | |
|         return self.GPIO_FUNCTION_NAMES[GPIO.gpio_function(self.number)]
 | |
| 
 | |
|     def _set_function(self, value):
 | |
|         if value != 'input':
 | |
|             self._pull = 'floating'
 | |
|         if value in ('input', 'output') and value in self.GPIO_FUNCTIONS:
 | |
|             GPIO.setup(self.number, self.GPIO_FUNCTIONS[value], self.GPIO_PULL_UPS[self._pull])
 | |
|         else:
 | |
|             raise PinInvalidFunction('invalid function "%s" for pin %r' % (value, self))
 | |
| 
 | |
|     def _get_state(self):
 | |
|         if self._pwm:
 | |
|             return self._duty_cycle
 | |
|         else:
 | |
|             return GPIO.input(self.number)
 | |
| 
 | |
|     def _set_state(self, value):
 | |
|         if self._pwm:
 | |
|             try:
 | |
|                 self._pwm.ChangeDutyCycle(value * 100)
 | |
|             except ValueError:
 | |
|                 raise PinInvalidState('invalid state "%s" for pin %r' % (value, self))
 | |
|             self._duty_cycle = value
 | |
|         else:
 | |
|             try:
 | |
|                 GPIO.output(self.number, value)
 | |
|             except ValueError:
 | |
|                 raise PinInvalidState('invalid state "%s" for pin %r' % (value, self))
 | |
|             except RuntimeError:
 | |
|                 raise PinSetInput('cannot set state of pin %r' % self)
 | |
| 
 | |
|     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.factory.pi_info.pulled_up(self.address[-1]):
 | |
|             raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | |
|         try:
 | |
|             GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[value])
 | |
|             self._pull = value
 | |
|         except KeyError:
 | |
|             raise PinInvalidPull('invalid pull "%s" for pin %r' % (value, self))
 | |
| 
 | |
|     def _get_frequency(self):
 | |
|         return self._frequency
 | |
| 
 | |
|     def _set_frequency(self, value):
 | |
|         if self._frequency is None and value is not None:
 | |
|             try:
 | |
|                 self._pwm = GPIO.PWM(self.number, value)
 | |
|             except RuntimeError:
 | |
|                 raise PinPWMFixedValue('cannot start PWM on pin %r' % self)
 | |
|             self._pwm.start(0)
 | |
|             self._duty_cycle = 0
 | |
|             self._frequency = value
 | |
|         elif self._frequency is not None and value is not None:
 | |
|             self._pwm.ChangeFrequency(value)
 | |
|             self._frequency = value
 | |
|         elif self._frequency is not None and value is None:
 | |
|             self._pwm.stop()
 | |
|             self._pwm = None
 | |
|             self._duty_cycle = None
 | |
|             self._frequency = None
 | |
| 
 | |
|     def _get_bounce(self):
 | |
|         return None if self._bounce == -666 else (self._bounce / 1000)
 | |
| 
 | |
|     def _set_bounce(self, value):
 | |
|         if value is not None and value < 0:
 | |
|             raise PinInvalidBounce('bounce must be 0 or greater')
 | |
|         f = self.when_changed
 | |
|         self.when_changed = None
 | |
|         try:
 | |
|             self._bounce = -666 if value is None else int(value * 1000)
 | |
|         finally:
 | |
|             self.when_changed = f
 | |
| 
 | |
|     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):
 | |
|         return self._when_changed
 | |
| 
 | |
|     def _set_when_changed(self, value):
 | |
|         if self._when_changed is None and value is not None:
 | |
|             self._when_changed = value
 | |
|             GPIO.add_event_detect(
 | |
|                 self.number, self._edges,
 | |
|                 callback=lambda channel: self._when_changed(),
 | |
|                 bouncetime=self._bounce)
 | |
|         elif self._when_changed is not None and value is None:
 | |
|             GPIO.remove_event_detect(self.number)
 | |
|             self._when_changed = None
 | |
|         else:
 | |
|             self._when_changed = value
 | |
| 
 |