0
# Pin Factory System
1
2
The pin factory system provides an abstracted interface for different GPIO backends, board information, and pin management. This enables GPIO Zero to work with multiple underlying GPIO libraries and provides comprehensive hardware abstraction.
3
4
## Core Factory Classes
5
6
### Factory
7
8
Abstract base class for all pin factories.
9
10
```python { .api }
11
class Factory:
12
def __init__(self):
13
"""
14
Abstract base class for pin factories.
15
"""
16
17
def close(self):
18
"""Close the factory and release all resources."""
19
20
def reset(self):
21
"""Reset the factory to its initial state."""
22
23
def pin(self, spec) -> 'Pin':
24
"""
25
Create a pin object for the specified pin.
26
27
Parameters:
28
- spec: Pin specification (int, str, or PinInfo)
29
30
Returns:
31
Pin object for the specified pin
32
"""
33
34
def spi(self, *, port=0, device=0) -> 'SPI':
35
"""
36
Create an SPI interface object.
37
38
Parameters:
39
- port: int - SPI port number
40
- device: int - SPI device (chip select) number
41
42
Returns:
43
SPI interface object
44
"""
45
46
def reserve_pins(self, requester, *pins):
47
"""Reserve pins for exclusive use by requester."""
48
49
def release_pins(self, requester, *pins):
50
"""Release pin reservations for requester."""
51
52
def release_all(self, requester):
53
"""Release all pin reservations for requester."""
54
55
@property
56
def board_info(self) -> 'BoardInfo':
57
"""Information about the current board."""
58
59
@property
60
def ticks(self) -> int:
61
"""Current system tick count."""
62
63
def ticks_diff(self, later: int, earlier: int) -> int:
64
"""Calculate difference between two tick counts."""
65
```
66
67
### Pin
68
69
Abstract base class representing a GPIO pin.
70
71
```python { .api }
72
class Pin:
73
def __init__(self, factory, info):
74
"""
75
Abstract base class for GPIO pins.
76
77
Parameters:
78
- factory: Factory that created this pin
79
- info: PinInfo object describing this pin
80
"""
81
82
def close(self):
83
"""Close the pin and release resources."""
84
85
def output_with_state(self, state: bool):
86
"""Configure pin as output and set initial state."""
87
88
def input_with_pull(self, pull: str):
89
"""Configure pin as input with pull resistor."""
90
91
@property
92
def number(self) -> int:
93
"""Pin number."""
94
95
@property
96
def info(self) -> 'PinInfo':
97
"""Pin information object."""
98
99
@property
100
def factory(self) -> Factory:
101
"""Factory that created this pin."""
102
103
@property
104
def function(self) -> str:
105
"""Current pin function ('input', 'output', 'alt0', etc.)."""
106
107
@function.setter
108
def function(self, value: str): ...
109
110
@property
111
def state(self) -> bool:
112
"""Current pin state (True=HIGH, False=LOW)."""
113
114
@state.setter
115
def state(self, value: bool): ...
116
117
@property
118
def pull(self) -> str:
119
"""Current pull resistor setting ('up', 'down', 'floating')."""
120
121
@pull.setter
122
def pull(self, value: str): ...
123
124
@property
125
def bounce(self) -> float:
126
"""Bounce time in seconds for edge detection."""
127
128
@bounce.setter
129
def bounce(self, value: float): ...
130
131
@property
132
def edges(self) -> str:
133
"""Edge detection setting ('none', 'falling', 'rising', 'both')."""
134
135
@edges.setter
136
def edges(self, value: str): ...
137
138
@property
139
def frequency(self) -> float:
140
"""PWM frequency in Hz."""
141
142
@frequency.setter
143
def frequency(self, value: float): ...
144
145
@property
146
def when_changed(self) -> callable:
147
"""Callback function for pin state changes."""
148
149
@when_changed.setter
150
def when_changed(self, value: callable): ...
151
```
152
153
### SPI
154
155
Abstract base class for SPI interfaces.
156
157
```python { .api }
158
class SPI:
159
def __init__(self, factory, port, device):
160
"""
161
Abstract base class for SPI interfaces.
162
163
Parameters:
164
- factory: Factory that created this interface
165
- port: SPI port number
166
- device: SPI device number
167
"""
168
169
def close(self):
170
"""Close the SPI interface."""
171
172
def transfer(self, data: list) -> list:
173
"""
174
Transfer data over SPI.
175
176
Parameters:
177
- data: List of bytes to send
178
179
Returns:
180
List of bytes received
181
"""
182
183
@property
184
def closed(self) -> bool:
185
"""Returns True if interface is closed."""
186
187
@property
188
def port(self) -> int:
189
"""SPI port number."""
190
191
@property
192
def device(self) -> int:
193
"""SPI device (chip select) number."""
194
```
195
196
## Board Information Classes
197
198
### BoardInfo
199
200
Information about a GPIO board.
201
202
```python { .api }
203
class BoardInfo:
204
def __init__(self, headers, **kwargs):
205
"""
206
Information about a GPIO board.
207
208
Parameters:
209
- headers: Dictionary of HeaderInfo objects
210
- **kwargs: Additional board properties
211
"""
212
213
def find_pin(self, spec) -> list:
214
"""
215
Find pin by specification.
216
217
Parameters:
218
- spec: Pin specification (number, name, or pattern)
219
220
Returns:
221
List of (header, pin_info) tuples matching specification
222
"""
223
224
@property
225
def headers(self) -> dict:
226
"""Dictionary of headers on this board."""
227
228
@property
229
def pins(self) -> dict:
230
"""Dictionary of all pins on this board."""
231
```
232
233
### HeaderInfo
234
235
Information about a pin header.
236
237
```python { .api }
238
class HeaderInfo:
239
def __init__(self, name, rows, columns, **kwargs):
240
"""
241
Information about a pin header.
242
243
Parameters:
244
- name: Header name
245
- rows: Number of rows
246
- columns: Number of columns
247
- **kwargs: Additional header properties
248
"""
249
250
@property
251
def name(self) -> str:
252
"""Header name."""
253
254
@property
255
def rows(self) -> int:
256
"""Number of rows in header."""
257
258
@property
259
def columns(self) -> int:
260
"""Number of columns in header."""
261
262
@property
263
def pins(self) -> dict:
264
"""Dictionary of pins in this header."""
265
```
266
267
### PinInfo
268
269
Information about a specific pin.
270
271
```python { .api }
272
class PinInfo:
273
def __init__(self, number, name, **kwargs):
274
"""
275
Information about a specific pin.
276
277
Parameters:
278
- number: Pin number
279
- name: Pin name
280
- **kwargs: Additional pin properties
281
"""
282
283
@property
284
def number(self) -> int:
285
"""Pin number."""
286
287
@property
288
def name(self) -> str:
289
"""Pin name."""
290
291
@property
292
def function(self) -> str:
293
"""Default pin function."""
294
295
@property
296
def pull(self) -> str:
297
"""Default pull resistor setting."""
298
299
@property
300
def row(self) -> int:
301
"""Header row position."""
302
303
@property
304
def col(self) -> int:
305
"""Header column position."""
306
```
307
308
## Raspberry Pi Specific Classes
309
310
### PiBoardInfo
311
312
Board information specific to Raspberry Pi.
313
314
```python { .api }
315
class PiBoardInfo(BoardInfo):
316
def __init__(self, revision=None, **kwargs):
317
"""
318
Raspberry Pi board information.
319
320
Parameters:
321
- revision: Pi revision string or None for auto-detect
322
- **kwargs: Additional board properties
323
"""
324
325
@property
326
def revision(self) -> str:
327
"""Pi board revision string."""
328
329
@property
330
def model(self) -> str:
331
"""Pi model name."""
332
333
@property
334
def pcb_revision(self) -> str:
335
"""PCB revision."""
336
337
@property
338
def memory(self) -> int:
339
"""Memory size in MB."""
340
341
@property
342
def manufacturer(self) -> str:
343
"""Board manufacturer."""
344
345
@property
346
def storage(self) -> str:
347
"""Storage type."""
348
349
@property
350
def usb(self) -> int:
351
"""Number of USB ports."""
352
353
@property
354
def ethernet(self) -> int:
355
"""Number of Ethernet ports."""
356
357
@property
358
def wifi(self) -> bool:
359
"""True if WiFi is available."""
360
361
@property
362
def bluetooth(self) -> bool:
363
"""True if Bluetooth is available."""
364
365
@property
366
def csi(self) -> int:
367
"""Number of CSI camera connectors."""
368
369
@property
370
def dsi(self) -> int:
371
"""Number of DSI display connectors."""
372
```
373
374
### pi_info Function
375
376
```python { .api }
377
def pi_info(revision=None) -> PiBoardInfo:
378
"""
379
Return board information for current or specified Pi revision.
380
381
Parameters:
382
- revision: str or None - Pi revision string or None for current Pi
383
384
Returns:
385
PiBoardInfo object for the specified Pi
386
"""
387
```
388
389
## Device Configuration
390
391
### Setting Pin Factory
392
393
```python { .api }
394
# Global pin factory configuration
395
from gpiozero import Device
396
from gpiozero.pins.pigpio import PiGPIOFactory
397
398
Device.pin_factory = PiGPIOFactory()
399
```
400
401
### Per-Device Pin Factory
402
403
```python { .api }
404
# Individual device pin factory
405
from gpiozero import LED
406
from gpiozero.pins.native import NativeFactory
407
408
led = LED(17, pin_factory=NativeFactory())
409
```
410
411
## Available Pin Factories
412
413
GPIO Zero includes several pin factory implementations:
414
415
### Default Factory (Auto-Detection)
416
417
The default factory automatically selects the best available backend:
418
419
1. **lgpio** - Preferred modern library
420
2. **RPi.GPIO** - Classic library
421
3. **pigpio** - High-performance library
422
4. **native** - Pure Python fallback
423
424
### Specific Factories
425
426
#### Native Factory
427
428
```python
429
from gpiozero.pins.native import NativeFactory
430
Device.pin_factory = NativeFactory()
431
```
432
433
Pure Python implementation, works on any Pi but limited functionality.
434
435
#### RPi.GPIO Factory
436
437
```python
438
from gpiozero.pins.rpigpio import RPiGPIOFactory
439
Device.pin_factory = RPiGPIOFactory()
440
```
441
442
Uses RPi.GPIO library, good compatibility but limited PWM.
443
444
#### pigpio Factory
445
446
```python
447
from gpiozero.pins.pigpio import PiGPIOFactory
448
Device.pin_factory = PiGPIOFactory()
449
```
450
451
High-performance library with accurate timing and hardware PWM.
452
453
#### lgpio Factory
454
455
```python
456
from gpiozero.pins.lgpio import LGPIOFactory
457
Device.pin_factory = LGPIOFactory()
458
```
459
460
Modern replacement for pigpio with similar features.
461
462
### Mock Factory
463
464
For testing and development without hardware:
465
466
```python
467
from gpiozero.pins.mock import MockFactory
468
Device.pin_factory = MockFactory()
469
```
470
471
## Usage Examples
472
473
### Board Information
474
475
```python
476
from gpiozero import Device
477
478
# Get current board info
479
board = Device.pin_factory.board_info
480
print(f"Board: {board.model}")
481
print(f"Revision: {board.revision}")
482
print(f"Memory: {board.memory}MB")
483
484
# Find pins by name
485
gpio17_pins = board.find_pin("GPIO17")
486
for header, pin_info in gpio17_pins:
487
print(f"Pin {pin_info.number}: {pin_info.name}")
488
489
# List all pins
490
for pin_num, pin_info in board.pins.items():
491
print(f"Pin {pin_num}: {pin_info.name}")
492
```
493
494
### Pin Factory Selection
495
496
```python
497
from gpiozero import LED, Device
498
from gpiozero.pins.pigpio import PiGPIOFactory
499
from gpiozero.pins.rpigpio import RPiGPIOFactory
500
501
# Set global pin factory
502
Device.pin_factory = PiGPIOFactory()
503
504
# All devices now use pigpio
505
led1 = LED(17)
506
led2 = LED(18)
507
508
# Override for specific device
509
led3 = LED(19, pin_factory=RPiGPIOFactory())
510
```
511
512
### Remote GPIO
513
514
```python
515
from gpiozero import LED
516
from gpiozero.pins.pigpio import PiGPIOFactory
517
518
# Connect to remote Pi
519
remote_factory = PiGPIOFactory(host='192.168.1.100', port=8888)
520
led = LED(17, pin_factory=remote_factory)
521
522
led.on()
523
```
524
525
### Mock Pin Testing
526
527
```python
528
from gpiozero import LED, Button
529
from gpiozero.pins.mock import MockFactory, MockPWMPin
530
531
# Set up mock factory
532
mock_factory = MockFactory()
533
Device.pin_factory = mock_factory
534
535
# Create devices (no hardware needed)
536
led = LED(17)
537
button = Button(2)
538
539
# Simulate hardware
540
mock_factory.pin(17).drive_high() # Simulate LED on
541
mock_factory.pin(2).drive_low() # Simulate button press
542
543
# Check device states
544
print(f"LED is {'on' if led.is_lit else 'off'}")
545
print(f"Button is {'pressed' if button.is_pressed else 'released'}")
546
```
547
548
### Custom Pin Factory
549
550
```python
551
from gpiozero.pins import Factory, Pin
552
from gpiozero import Device
553
554
class MyCustomFactory(Factory):
555
def __init__(self):
556
super().__init__()
557
# Initialize custom hardware interface
558
559
def pin(self, spec):
560
# Return custom pin implementation
561
return MyCustomPin(self, spec)
562
563
def _get_board_info(self):
564
# Return custom board information
565
return my_board_info
566
567
# Use custom factory
568
Device.pin_factory = MyCustomFactory()
569
```
570
571
### Pin Reservation
572
573
```python
574
from gpiozero import LED, Device
575
576
# Create device (pins are automatically reserved)
577
led = LED(17)
578
579
# Manual pin reservation
580
factory = Device.pin_factory
581
factory.reserve_pins(led, 17, 18, 19)
582
583
# Check reservations
584
try:
585
led2 = LED(17) # This will fail - pin already reserved
586
except GPIOPinInUse:
587
print("Pin 17 is already in use")
588
589
# Release reservations
590
led.close() # Automatically releases pin 17
591
factory.release_pins(led, 18, 19) # Manual release
592
```
593
594
### SPI Configuration
595
596
```python
597
from gpiozero import MCP3008
598
599
# Default SPI (port=0, device=0)
600
adc = MCP3008(channel=0)
601
602
# Custom SPI configuration
603
adc2 = MCP3008(channel=0, port=0, device=1) # Use CE1 instead of CE0
604
605
# Access underlying SPI interface
606
spi = Device.pin_factory.spi(port=0, device=0)
607
response = spi.transfer([0x01, 0x80, 0x00]) # Raw SPI transfer
608
spi.close()
609
```