mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	| @@ -25,35 +25,46 @@ integer number instead, it uses one of the following classes to provide the | ||||
| 4. :class:`gpiozero.pins.native.NativePin` | ||||
|  | ||||
| You can change the default pin implementation by over-writing the | ||||
| ``DefaultPin`` global in the ``devices`` module like so:: | ||||
| ``pin_factory`` global in the ``devices`` module like so:: | ||||
|  | ||||
|     from gpiozero.pins.native import NativePin | ||||
|     import gpiozero.devices | ||||
|     # Force the default pin implementation to be NativePin | ||||
|     gpiozero.devices.DefaultPin = NativePin | ||||
|     gpiozero.devices.pin_factory = NativePin | ||||
|  | ||||
|     from gpiozero import LED | ||||
|  | ||||
|     # This will now use NativePin instead of RPiGPIOPin | ||||
|     led = LED(16) | ||||
|  | ||||
| ``pin_factory`` is simply a callable that accepts a single argument: the number | ||||
| of the pin to be constructed (this prototype *may* be expanded in future). This | ||||
| means you can define it as a function that provides additional parameters to an | ||||
| underlying class. For example, to default to creating pins with | ||||
| :class:`gpiozero.pins.pigpiod.PiGPIOPin` on a remote pi called ``remote-pi``:: | ||||
|  | ||||
|     from gpiozero.pins.pigpiod import PiGPIOPin | ||||
|     import gpiozero.devices | ||||
|  | ||||
|     def my_pin_factory(number): | ||||
|         return PiGPIOPin(number, host='remote-pi') | ||||
|  | ||||
|     gpiozero.devices.pin_factory = my_pin_factory | ||||
|  | ||||
|     from gpiozero import TrafficLights | ||||
|  | ||||
|     # This will now use pins on remote-pi (assuming it has the | ||||
|     # pigpiod daemon installed and running) | ||||
|     tl = TrafficLights(13, 19, 26) | ||||
|  | ||||
| Alternatively, instead of passing an integer to the device constructor, you | ||||
| can pass a :class:`Pin` object itself:: | ||||
| can pass an object derived from :class:`Pin` itself:: | ||||
|  | ||||
|     from gpiozero.pins.native import NativePin | ||||
|     from gpiozero import LED | ||||
|  | ||||
|     led = LED(NativePin(16)) | ||||
|  | ||||
| This is particularly useful with implementations that can take extra parameters | ||||
| such as :class:`~gpiozero.pins.pigpiod.PiGPIOPin` which can address pins on | ||||
| remote machines:: | ||||
|  | ||||
|     from gpiozero.pins.pigpiod import PiGPIOPin | ||||
|     from gpiozero import LED | ||||
|  | ||||
|     led = LED(PiGPIOPin(16, host='my_other_pi')) | ||||
|  | ||||
| In future, this separation of pins and devices should also permit the library | ||||
| to utilize pins that are part of IO extender chips. For example:: | ||||
|  | ||||
|   | ||||
| @@ -36,18 +36,18 @@ from .exc import ( | ||||
| from .pins import _pins_shutdown | ||||
| try: | ||||
|     from .pins.rpigpio import RPiGPIOPin | ||||
|     DefaultPin = RPiGPIOPin | ||||
|     pin_factory = RPiGPIOPin | ||||
| except ImportError: | ||||
|     try: | ||||
|         from .pins.rpio import RPIOPin | ||||
|         DefaultPin = RPIOPin | ||||
|         pin_factory = RPIOPin | ||||
|     except ImportError: | ||||
|         try: | ||||
|             from .pins.pigipod import PiGPIOPin | ||||
|             DefaultPin = PiGPIOPin | ||||
|             pin_factory = PiGPIOPin | ||||
|         except ImportError: | ||||
|             from .pins.native import NativePin | ||||
|             DefaultPin = NativePin | ||||
|             pin_factory = NativePin | ||||
|  | ||||
|  | ||||
| _PINS = set() | ||||
| @@ -365,7 +365,7 @@ class GPIODevice(Device): | ||||
|         if pin is None: | ||||
|             raise GPIOPinMissing('No pin given') | ||||
|         if isinstance(pin, int): | ||||
|             pin = DefaultPin(pin) | ||||
|             pin = pin_factory(pin) | ||||
|         with _PINS_LOCK: | ||||
|             if pin in _PINS: | ||||
|                 raise GPIOPinInUse( | ||||
|   | ||||
| @@ -243,29 +243,28 @@ CM_SODIMM = { | ||||
|  | ||||
| PI_REVISIONS = { | ||||
|     # rev     model    pcb_rev released soc        manufacturer ram   storage    usb eth wifi   bt     csi dsi headers | ||||
|     'beta':   ('B',    '?',   '2012Q1', 'BCM2835', '?',         256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     '0002':   ('B',    '1.0', '2012Q1', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     '0003':   ('B',    '1.0', '2012Q3', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     '0004':   ('B',    '2.0', '2012Q3', 'BCM2835', 'Sony',      256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0005':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Qisda',     256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0006':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0007':   ('A',    '2.0', '2013Q1', 'BCM2835', 'Egoman',    256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0008':   ('A',    '2.0', '2013Q1', 'BCM2835', 'Sony',      256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0009':   ('A',    '2.0', '2013Q1', 'BCM2835', 'Qisda',     256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '000d':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '000e':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Sony',      512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '000f':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0010':   ('B+',   '1.2', '2014Q3', 'BCM2835', 'Sony',      512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '0011':   ('CM',   '1.2', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    0,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     '0012':   ('A+',   '1.2', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '0013':   ('B+',   '1.2', '2015Q1', 'BCM2835', 'Egoman',    512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '0014':   ('CM',   '1.1', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    0,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     '0015':   ('A+',   '1.1', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     'a01041': ('2B',   '1.1', '2015Q1', 'BCM2836', 'Sony',      1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     'a21041': ('2B',   '1.1', '2015Q1', 'BCM2836', 'Embest',    1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '900092': ('Zero', '1.2', '2015Q4', 'BCM2835', 'Sony',      512,  'MicroSD', 1,  0,  False, False, 0,  0,  {'P1': PLUS_P1},               ), | ||||
|     'a02082': ('3B',   '1.2', '2016Q1', 'BCM2837', 'Sony',      1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     'a22082': ('3B',   '1.2', '2016Q1', 'BCM2837', 'Embest',    1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x2:      ('B',    '1.0', '2012Q1', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     0x3:      ('B',    '1.0', '2012Q3', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     0x4:      ('B',    '2.0', '2012Q3', 'BCM2835', 'Sony',      256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x5:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Qisda',     256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x6:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x7:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Egoman',    256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x8:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Sony',      256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x9:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Qisda',     256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0xd:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0xe:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Sony',      512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0xf:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x10:     ('B+',   '1.2', '2014Q3', 'BCM2835', 'Sony',      512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x11:     ('CM',   '1.2', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    0,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     0x12:     ('A+',   '1.2', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x13:     ('B+',   '1.2', '2015Q1', 'BCM2835', 'Egoman',    512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x14:     ('CM',   '1.1', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    0,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     0x15:     ('A+',   '1.1', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0xa01041: ('2B',   '1.1', '2015Q1', 'BCM2836', 'Sony',      1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0xa21041: ('2B',   '1.1', '2015Q1', 'BCM2836', 'Embest',    1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x900092: ('Zero', '1.2', '2015Q4', 'BCM2835', 'Sony',      512,  'MicroSD', 1,  0,  False, False, 0,  0,  {'P1': PLUS_P1},               ), | ||||
|     0xa02082: ('3B',   '1.2', '2016Q1', 'BCM2837', 'Sony',      1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0xa22082: ('3B',   '1.2', '2016Q1', 'BCM2837', 'Embest',    1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -513,9 +512,8 @@ def _parse_pi_revision(revision): | ||||
|     # PPPP     - Processor (0=2835, 1=2836, 2=2837) | ||||
|     # TTTTTTTT - Type (0=A, 1=B, 2=A+, 3=B+, 4=2B, 5=Alpha (??), 6=CM, 8=3B, 9=Zero) | ||||
|     # RRRR     - Revision (0, 1, or 2) | ||||
|     i = int(revision, base=16) | ||||
|     if not (i & 0x800000): | ||||
|         raise ValueError('cannot parse "%s"; this is not a new-style revision' % revision) | ||||
|     if not (revision & 0x800000): | ||||
|         raise ValueError('cannot parse "%x"; this is not a new-style revision' % revision) | ||||
|     try: | ||||
|         model = { | ||||
|             0: 'A', | ||||
| @@ -526,15 +524,15 @@ def _parse_pi_revision(revision): | ||||
|             6: 'CM', | ||||
|             8: '3B', | ||||
|             9: 'Zero', | ||||
|             }[(i & 0xff0) >> 4] | ||||
|             }[(revision & 0xff0) >> 4] | ||||
|         if model in ('A', 'B'): | ||||
|             pcb_revision = { | ||||
|                 0: '1.0', # is this right? | ||||
|                 1: '1.0', | ||||
|                 2: '2.0', | ||||
|                 }[i & 0x0f] | ||||
|                 }[revision & 0x0f] | ||||
|         else: | ||||
|             pcb_revision = '1.%d' % (i & 0x0f) | ||||
|             pcb_revision = '1.%d' % (revision & 0x0f) | ||||
|         released = { | ||||
|             'A':    '2013Q1', | ||||
|             'B':    '2012Q1' if pcb_revision == '1.0' else '2012Q4', | ||||
| @@ -549,17 +547,17 @@ def _parse_pi_revision(revision): | ||||
|             0: 'BCM2835', | ||||
|             1: 'BCM2836', | ||||
|             2: 'BCM2837', | ||||
|             }[(i & 0xf000) >> 12] | ||||
|             }[(revision & 0xf000) >> 12] | ||||
|         manufacturer = { | ||||
|             0: 'Sony', | ||||
|             1: 'Egoman', | ||||
|             2: 'Embest', | ||||
|             }[(i & 0xf0000) >> 16] | ||||
|             }[(revision & 0xf0000) >> 16] | ||||
|         memory = { | ||||
|             0: 256, | ||||
|             1: 512, | ||||
|             2: 1024, | ||||
|             }[(i & 0x700000) >> 20] | ||||
|             }[(revision & 0x700000) >> 20] | ||||
|         storage = { | ||||
|             'A': 'SD', | ||||
|             'B': 'SD', | ||||
| @@ -595,7 +593,7 @@ def _parse_pi_revision(revision): | ||||
|             'CM': {'SODIMM': CM_SODIMM}, | ||||
|             }.get(model, {'P1': PLUS_P1}) | ||||
|     except KeyError: | ||||
|         raise ValueError('unable to parse new-style revision "%s"' % revision) | ||||
|         raise ValueError('unable to parse new-style revision "%x"' % revision) | ||||
|     else: | ||||
|         return ( | ||||
|             model, | ||||
| @@ -635,6 +633,10 @@ def pi_info(revision=None): | ||||
|             except IOError: | ||||
|                 _PI_REVISION = 'unknown' | ||||
|         revision = _PI_REVISION | ||||
|     try: | ||||
|         revision_int = int(revision, base=16) | ||||
|     except ValueError: | ||||
|         raise PinUnknownPi('unknown RPi revision "%s"' % revision) | ||||
|     try: | ||||
|         ( | ||||
|             model, | ||||
| @@ -651,7 +653,7 @@ def pi_info(revision=None): | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|             ) = PI_REVISIONS[revision] | ||||
|             ) = PI_REVISIONS[revision_int] | ||||
|     except KeyError: | ||||
|         try: | ||||
|             ( | ||||
| @@ -669,7 +671,7 @@ def pi_info(revision=None): | ||||
|                 csi, | ||||
|                 dsi, | ||||
|                 headers, | ||||
|                 ) = _parse_pi_revision(revision) | ||||
|                 ) = _parse_pi_revision(revision_int) | ||||
|         except ValueError: | ||||
|             raise PinUnknownPi('unknown RPi revision "%s"' % revision) | ||||
|     headers = { | ||||
|   | ||||
| @@ -98,25 +98,20 @@ class PiGPIOPin(Pin): | ||||
|     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()} | ||||
|  | ||||
|     PI_INFO = None | ||||
|  | ||||
|     def __new__(cls, number, host='localhost', port=8888): | ||||
|         # XXX What about remote pins? This should probably be instance | ||||
|         # specific rather than class specific for pigpio. Need to check how | ||||
|         # to query remote info though... | ||||
|         if cls.PI_INFO is None: | ||||
|             cls.PI_INFO = pi_info() | ||||
|         try: | ||||
|             return cls._PINS[(host, port, number)] | ||||
|         except KeyError: | ||||
|             self = super(PiGPIOPin, cls).__new__(cls) | ||||
|             try: | ||||
|                 self._connection = cls._CONNECTIONS[(host, port)] | ||||
|                 self._connection, self._pi_info = cls._CONNECTIONS[(host, port)] | ||||
|             except KeyError: | ||||
|                 self._connection = pigpio.pi(host, port) | ||||
|                 cls._CONNECTIONS[(host, port)] = self._connection | ||||
|                 revision = hex(self._connection.get_hardware_revision())[2:] | ||||
|                 self._pi_info = pi_info(revision) | ||||
|                 cls._CONNECTIONS[(host, port)] = (self._connection, self._pi_info) | ||||
|             try: | ||||
|                 cls.PI_INFO.physical_pin('GPIO%d' % number) | ||||
|                 self._pi_info.physical_pin('GPIO%d' % number) | ||||
|             except PinNoPins: | ||||
|                 warnings.warn( | ||||
|                     PinNonPhysical( | ||||
| @@ -124,7 +119,7 @@ class PiGPIOPin(Pin): | ||||
|             self._host = host | ||||
|             self._port = port | ||||
|             self._number = number | ||||
|             self._pull = 'up' if cls.PI_INFO.pulled_up('GPIO%d' % number) else 'floating' | ||||
|             self._pull = 'up' if self._pi_info.pulled_up('GPIO%d' % number) else 'floating' | ||||
|             self._pwm = False | ||||
|             self._bounce = None | ||||
|             self._when_changed = None | ||||
| @@ -167,7 +162,7 @@ class PiGPIOPin(Pin): | ||||
|             self.frequency = None | ||||
|             self.when_changed = None | ||||
|             self.function = 'input' | ||||
|             self.pull = 'up' if self.PI_INFO.pulled_up('GPIO%d' % self.number) else 'floating' | ||||
|             self.pull = 'up' if self._pi_info.pulled_up('GPIO%d' % self.number) else 'floating' | ||||
|  | ||||
|     def _get_function(self): | ||||
|         return self.GPIO_FUNCTION_NAMES[self._connection.get_mode(self._number)] | ||||
| @@ -204,7 +199,7 @@ class PiGPIOPin(Pin): | ||||
|     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.PI_INFO.pulled_up('GPIO%d' % self._number): | ||||
|         if value != 'up' and self._pi_info.pulled_up('GPIO%d' % self._number): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             self._connection.set_pull_up_down(self._number, self.GPIO_PULL_UPS[value]) | ||||
|   | ||||
| @@ -19,9 +19,9 @@ def setup_function(function): | ||||
|     import gpiozero.devices | ||||
|     # dirty, but it does the job | ||||
|     if function.__name__ in ('test_robot', 'test_ryanteck_robot', 'test_camjam_kit_robot'): | ||||
|         gpiozero.devices.DefaultPin = MockPWMPin | ||||
|         gpiozero.devices.pin_factory = MockPWMPin | ||||
|     else: | ||||
|         gpiozero.devices.DefaultPin = MockPin | ||||
|         gpiozero.devices.pin_factory = MockPin | ||||
|  | ||||
| def teardown_function(function): | ||||
|     MockPin.clear_pins() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user