0
# Composite Devices
1
2
Pre-built configurations for commercial GPIO boards, LED collections, and robotic platforms. Composite devices combine multiple individual devices into cohesive units with simplified control interfaces.
3
4
## Base Classes
5
6
### CompositeDevice
7
8
Base class for devices composed of multiple sub-devices.
9
10
```python { .api }
11
class CompositeDevice(Device):
12
def __init__(self, *, pin_factory=None):
13
"""
14
Base class for composite devices.
15
16
Parameters:
17
- pin_factory: Factory or None - Pin factory for advanced usage
18
"""
19
20
def close(self):
21
"""Close the device and all sub-devices."""
22
23
@property
24
def closed(self) -> bool:
25
"""Returns True if device is closed."""
26
27
@property
28
def value(self) -> tuple:
29
"""Tuple of all sub-device values."""
30
31
@value.setter
32
def value(self, values): ...
33
```
34
35
### CompositeOutputDevice
36
37
Base class for composite output devices.
38
39
```python { .api }
40
class CompositeOutputDevice(ValuesMixin, SourceMixin, CompositeDevice):
41
def __init__(self, *, initial_value=False, pin_factory=None):
42
"""
43
Base class for composite output devices.
44
45
Parameters:
46
- initial_value: Initial state for all outputs
47
- pin_factory: Factory or None - Pin factory for advanced usage
48
"""
49
50
def on(self):
51
"""Turn on all outputs."""
52
53
def off(self):
54
"""Turn off all outputs."""
55
56
def toggle(self):
57
"""Toggle all outputs."""
58
59
def pulse(self, fade_in_time: float = 1, fade_out_time: float = 1, n: int = None, background: bool = True):
60
"""Pulse all outputs."""
61
62
def blink(self, on_time: float = 1, off_time: float = 1, n: int = None, background: bool = True):
63
"""Blink all outputs."""
64
65
@property
66
def is_active(self) -> bool:
67
"""Returns True if any output is active."""
68
```
69
70
## LED Collections
71
72
### LEDBoard
73
74
Collection of LEDs indexed by name.
75
76
```python { .api }
77
class LEDBoard(CompositeOutputDevice):
78
def __init__(self, **named_pins):
79
"""
80
Collection of LEDs with named access.
81
82
Parameters:
83
- **named_pins: Named pin assignments (e.g., red=17, green=18, blue=19)
84
"""
85
86
def __getitem__(self, key) -> LED:
87
"""Access LED by name."""
88
89
def __setitem__(self, key, value):
90
"""Set LED state by name."""
91
92
@property
93
def leds(self) -> dict:
94
"""Dictionary of all LEDs by name."""
95
```
96
97
### LEDBarGraph
98
99
Bar graph representation using multiple LEDs.
100
101
```python { .api }
102
class LEDBarGraph(LEDBoard):
103
def __init__(self, *pins, pwm=False, active_high=True, initial_value=0, pin_factory=None):
104
"""
105
LED bar graph for displaying values.
106
107
Parameters:
108
- *pins: Pin numbers for LEDs (in order from low to high)
109
- pwm: bool - True for PWM LEDs, False for simple LEDs
110
- active_high: bool - True if LEDs are on when pins are HIGH
111
- initial_value: float - Initial value to display (0.0-1.0)
112
- pin_factory: Factory or None - Pin factory for advanced usage
113
"""
114
115
@property
116
def value(self) -> float:
117
"""Current bar graph value (0.0-1.0)."""
118
119
@value.setter
120
def value(self, value: float): ...
121
122
@property
123
def lit_count(self) -> int:
124
"""Number of currently lit LEDs."""
125
```
126
127
### LEDCharDisplay
128
129
7-segment character display.
130
131
```python { .api }
132
class LEDCharDisplay(CompositeOutputDevice):
133
def __init__(self, a, b, c, d, e, f, g, *, dp=None, active_high=True, initial_value=' ', pin_factory=None):
134
"""
135
7-segment character display.
136
137
Parameters:
138
- a, b, c, d, e, f, g: Pin numbers for segments
139
- dp: Pin number for decimal point (optional)
140
- active_high: bool - True if segments are on when pins are HIGH
141
- initial_value: str - Initial character to display
142
- pin_factory: Factory or None - Pin factory for advanced usage
143
"""
144
145
@property
146
def char(self) -> str:
147
"""Current displayed character."""
148
149
@char.setter
150
def char(self, value: str): ...
151
152
def display_hex(self, value: int):
153
"""Display hexadecimal digit (0-F)."""
154
155
def display_decimal(self, value: int):
156
"""Display decimal digit (0-9)."""
157
```
158
159
### LEDMultiCharDisplay
160
161
Multi-character 7-segment display.
162
163
```python { .api }
164
class LEDMultiCharDisplay(CompositeOutputDevice):
165
def __init__(self, *chars, active_high=True, initial_value=' ', pin_factory=None):
166
"""
167
Multi-character 7-segment display.
168
169
Parameters:
170
- *chars: LEDCharDisplay objects for each digit position
171
- active_high: bool - True if segments are on when pins are HIGH
172
- initial_value: str - Initial text to display
173
- pin_factory: Factory or None - Pin factory for advanced usage
174
"""
175
176
@property
177
def text(self) -> str:
178
"""Current displayed text."""
179
180
@text.setter
181
def text(self, value: str): ...
182
183
def display_int(self, value: int):
184
"""Display integer value."""
185
186
def display_float(self, value: float, decimal_places: int = 1):
187
"""Display floating point value."""
188
```
189
190
## Robot Classes
191
192
### Robot
193
194
Generic two-wheeled robot with differential drive.
195
196
```python { .api }
197
class Robot(CompositeDevice, SourceMixin):
198
def __init__(self, left=None, right=None, *, pwm=True, pin_factory=None):
199
"""
200
Two-wheeled robot with differential drive.
201
202
Parameters:
203
- left: Motor pins for left wheel (forward, backward) or Motor object
204
- right: Motor pins for right wheel (forward, backward) or Motor object
205
- pwm: bool - True for PWM speed control
206
- pin_factory: Factory or None - Pin factory for advanced usage
207
"""
208
209
def forward(self, speed: float = 1):
210
"""Move forward at specified speed (0.0-1.0)."""
211
212
def backward(self, speed: float = 1):
213
"""Move backward at specified speed (0.0-1.0)."""
214
215
def left(self, speed: float = 1):
216
"""Turn left at specified speed."""
217
218
def right(self, speed: float = 1):
219
"""Turn right at specified speed."""
220
221
def stop(self):
222
"""Stop all movement."""
223
224
def reverse(self):
225
"""Reverse current movement direction."""
226
227
@property
228
def value(self) -> tuple:
229
"""Current movement as (left_speed, right_speed) tuple."""
230
231
@value.setter
232
def value(self, speeds: tuple): ...
233
234
@property
235
def is_active(self) -> bool:
236
"""Returns True if either motor is active."""
237
238
@property
239
def left_motor(self) -> Motor:
240
"""Left motor object."""
241
242
@property
243
def right_motor(self) -> Motor:
244
"""Right motor object."""
245
```
246
247
### CamJamKitRobot
248
249
Robot configuration for CamJam EduKit #3.
250
251
```python { .api }
252
class CamJamKitRobot(Robot):
253
def __init__(self, *, pwm=True, pin_factory=None):
254
"""
255
CamJam EduKit robot with predefined pin configuration.
256
257
Parameters:
258
- pwm: bool - True for PWM speed control
259
- pin_factory: Factory or None - Pin factory for advanced usage
260
"""
261
```
262
263
### RyanteckRobot
264
265
Robot configuration for Ryanteck MCB robot.
266
267
```python { .api }
268
class RyanteckRobot(Robot):
269
def __init__(self, *, pwm=True, pin_factory=None):
270
"""
271
Ryanteck MCB robot with predefined pin configuration.
272
273
Parameters:
274
- pwm: bool - True for PWM speed control
275
- pin_factory: Factory or None - Pin factory for advanced usage
276
"""
277
```
278
279
### PololuDRV8835Robot
280
281
Robot using Pololu DRV8835 motor controller.
282
283
```python { .api }
284
class PololuDRV8835Robot(Robot):
285
def __init__(self, *, pwm=True, pin_factory=None):
286
"""
287
Pololu DRV8835 robot with predefined pin configuration.
288
289
Parameters:
290
- pwm: bool - True for PWM speed control
291
- pin_factory: Factory or None - Pin factory for advanced usage
292
"""
293
```
294
295
## Commercial GPIO Boards
296
297
### TrafficLights
298
299
Generic traffic light board (red, amber, green).
300
301
```python { .api }
302
class TrafficLights(CompositeOutputDevice):
303
def __init__(self, red=None, amber=None, green=None, *, pwm=False, initial_value=False, pin_factory=None):
304
"""
305
Traffic light control board.
306
307
Parameters:
308
- red: int or str - Red LED pin
309
- amber: int or str - Amber LED pin
310
- green: int or str - Green LED pin
311
- pwm: bool - True for PWM LEDs
312
- initial_value: Initial state
313
- pin_factory: Factory or None - Pin factory for advanced usage
314
"""
315
316
@property
317
def red(self) -> LED:
318
"""Red LED."""
319
320
@property
321
def amber(self) -> LED:
322
"""Amber LED."""
323
324
@property
325
def green(self) -> LED:
326
"""Green LED."""
327
328
def red_on(self):
329
"""Turn on red light, turn off others."""
330
331
def amber_on(self):
332
"""Turn on amber light, turn off others."""
333
334
def green_on(self):
335
"""Turn on green light, turn off others."""
336
```
337
338
### PiTraffic
339
340
Low Voltage Labs PiTraffic board with fixed pins.
341
342
```python { .api }
343
class PiTraffic(TrafficLights):
344
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
345
"""
346
PiTraffic board with predefined pins (9, 10, 11).
347
348
Parameters:
349
- pwm: bool - True for PWM LEDs
350
- initial_value: Initial state
351
- pin_factory: Factory or None - Pin factory for advanced usage
352
"""
353
```
354
355
### PiStop
356
357
PiHardware PiStop traffic lights.
358
359
```python { .api }
360
class PiStop(TrafficLights):
361
def __init__(self, location=None, *, pwm=False, initial_value=False, pin_factory=None):
362
"""
363
PiStop traffic lights for different GPIO locations.
364
365
Parameters:
366
- location: str - Board location ('A', 'B', 'C', 'D') or None for auto-detect
367
- pwm: bool - True for PWM LEDs
368
- initial_value: Initial state
369
- pin_factory: Factory or None - Pin factory for advanced usage
370
"""
371
```
372
373
### LEDBoard Variants
374
375
#### PiLiter
376
377
Ciseco PiLiter 8-LED board.
378
379
```python { .api }
380
class PiLiter(LEDBoard):
381
def __init__(self, *, pwm=False, active_high=True, initial_value=False, pin_factory=None):
382
"""
383
PiLiter 8-LED board with predefined pins.
384
385
Parameters:
386
- pwm: bool - True for PWM LEDs
387
- active_high: bool - True if LEDs are on when pins are HIGH
388
- initial_value: Initial state
389
- pin_factory: Factory or None - Pin factory for advanced usage
390
"""
391
```
392
393
#### PiHutXmasTree
394
395
Pi Hut 3D Christmas tree LED board.
396
397
```python { .api }
398
class PiHutXmasTree(LEDBoard):
399
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
400
"""
401
Pi Hut 3D Christmas tree with 24 LEDs.
402
403
Parameters:
404
- pwm: bool - True for PWM LEDs
405
- initial_value: Initial state
406
- pin_factory: Factory or None - Pin factory for advanced usage
407
"""
408
409
def on(self, *, led_count: int = None):
410
"""Turn on LEDs (optionally specify count)."""
411
412
def off(self):
413
"""Turn off all LEDs."""
414
```
415
416
### Button Boards
417
418
#### ButtonBoard
419
420
Collection of buttons with event handling.
421
422
```python { .api }
423
class ButtonBoard(CompositeDevice):
424
def __init__(self, **named_pins):
425
"""
426
Collection of buttons with named access.
427
428
Parameters:
429
- **named_pins: Named pin assignments for buttons
430
"""
431
432
def __getitem__(self, key) -> Button:
433
"""Access button by name."""
434
435
@property
436
def buttons(self) -> dict:
437
"""Dictionary of all buttons by name."""
438
439
@property
440
def when_pressed(self) -> callable:
441
"""Callback for any button press."""
442
443
@when_pressed.setter
444
def when_pressed(self, value: callable): ...
445
446
@property
447
def when_released(self) -> callable:
448
"""Callback for any button release."""
449
450
@when_released.setter
451
def when_released(self, value: callable): ...
452
```
453
454
### Specialized Boards
455
456
#### Energenie
457
458
Energenie power control sockets.
459
460
```python { .api }
461
class Energenie(CompositeOutputDevice):
462
def __init__(self, socket=None, *, initial_value=False, pin_factory=None):
463
"""
464
Energenie power control sockets.
465
466
Parameters:
467
- socket: int - Socket number (1-4) or None for all
468
- initial_value: Initial state
469
- pin_factory: Factory or None - Pin factory for advanced usage
470
"""
471
472
def __getitem__(self, socket: int) -> OutputDevice:
473
"""Access socket by number."""
474
475
def on(self, socket: int = None):
476
"""Turn on socket (or all if None)."""
477
478
def off(self, socket: int = None):
479
"""Turn off socket (or all if None)."""
480
```
481
482
## Usage Examples
483
484
### LED Board Control
485
486
```python
487
from gpiozero import LEDBoard
488
from time import sleep
489
490
# Create named LED board
491
leds = LEDBoard(red=2, green=3, blue=4, yellow=5)
492
493
# Individual LED control
494
leds.red.on()
495
leds.green.blink()
496
497
# Access by name
498
leds['blue'].on()
499
sleep(1)
500
leds['blue'].off()
501
502
# All LEDs
503
leds.on()
504
sleep(1)
505
leds.off()
506
507
# Sequence
508
for led_name in ['red', 'green', 'blue', 'yellow']:
509
leds[led_name].on()
510
sleep(0.5)
511
leds[led_name].off()
512
```
513
514
### LED Bar Graph
515
516
```python
517
from gpiozero import LEDBarGraph, MCP3008
518
from signal import pause
519
520
# 8-LED bar graph
521
bar = LEDBarGraph(2, 3, 4, 5, 6, 7, 8, 9, pwm=True)
522
sensor = MCP3008(channel=0)
523
524
# Bar graph follows sensor reading
525
bar.source = sensor
526
527
pause()
528
```
529
530
### Robot Control
531
532
```python
533
from gpiozero import Robot
534
from time import sleep
535
536
# Custom robot configuration
537
robot = Robot(left=(7, 8), right=(9, 10))
538
539
# Basic movements
540
robot.forward()
541
sleep(2)
542
robot.backward()
543
sleep(2)
544
robot.left()
545
sleep(1)
546
robot.right()
547
sleep(1)
548
robot.stop()
549
550
# Speed control
551
robot.forward(0.5) # Half speed
552
sleep(2)
553
robot.stop()
554
555
# Manual wheel control
556
robot.value = (1, 0.5) # Left full, right half
557
sleep(2)
558
robot.value = (0, 0) # Stop
559
```
560
561
### Traffic Light Sequence
562
563
```python
564
from gpiozero import TrafficLights
565
from time import sleep
566
567
lights = TrafficLights(red=2, amber=3, green=4)
568
569
def traffic_sequence():
570
"""Standard UK traffic light sequence."""
571
lights.green_on()
572
sleep(5)
573
574
lights.amber_on()
575
sleep(2)
576
577
lights.red_on()
578
sleep(5)
579
580
# Red + Amber (UK style)
581
lights.red.on()
582
lights.amber.on()
583
lights.green.off()
584
sleep(2)
585
586
# Run sequence
587
while True:
588
traffic_sequence()
589
```
590
591
### Button Board with LEDs
592
593
```python
594
from gpiozero import ButtonBoard, LEDBoard
595
from signal import pause
596
597
buttons = ButtonBoard(a=2, b=3, c=4, d=5)
598
leds = LEDBoard(red=17, green=18, blue=19, yellow=20)
599
600
# Map buttons to LEDs
601
buttons['a'].when_pressed = leds.red.toggle
602
buttons['b'].when_pressed = leds.green.toggle
603
buttons['c'].when_pressed = leds.blue.toggle
604
buttons['d'].when_pressed = leds.yellow.toggle
605
606
# Global button handler
607
def any_button_pressed():
608
print("A button was pressed!")
609
610
buttons.when_pressed = any_button_pressed
611
612
pause()
613
```
614
615
### 7-Segment Display
616
617
```python
618
from gpiozero import LEDCharDisplay
619
from time import sleep
620
621
# 7-segment display (a, b, c, d, e, f, g segments)
622
display = LEDCharDisplay(2, 3, 4, 5, 6, 7, 8, dp=9)
623
624
# Display digits
625
for digit in "0123456789":
626
display.char = digit
627
sleep(0.5)
628
629
# Display hex digits
630
for digit in "0123456789ABCDEF":
631
display.char = digit
632
sleep(0.3)
633
634
# Display some letters
635
for char in "HELLO":
636
display.char = char
637
sleep(0.5)
638
```
639
640
### Robot with Sensors
641
642
```python
643
from gpiozero import Robot, DistanceSensor, Button
644
from signal import pause
645
646
robot = Robot(left=(7, 8), right=(9, 10))
647
distance = DistanceSensor(echo=24, trigger=23, threshold_distance=0.3)
648
stop_button = Button(2)
649
650
def obstacle_detected():
651
robot.stop()
652
print("Obstacle detected! Stopping.")
653
654
def path_clear():
655
robot.forward(0.5)
656
print("Path clear, moving forward.")
657
658
def emergency_stop():
659
robot.stop()
660
print("Emergency stop!")
661
662
# Connect sensors to robot
663
distance.when_in_range = obstacle_detected
664
distance.when_out_of_range = path_clear
665
stop_button.when_pressed = emergency_stop
666
667
# Start moving
668
robot.forward(0.5)
669
pause()
670
```
671
672
## Additional Board Classes
673
674
### LEDCharFont
675
676
Font management for character displays.
677
678
```python { .api }
679
class LEDCharFont(MutableMapping):
680
def __init__(self, font_file):
681
"""
682
Font for character displays.
683
684
Parameters:
685
- font_file: str - Path to font definition file
686
"""
687
```
688
689
### LedBorg
690
691
LedBorg RGB LED board.
692
693
```python { .api }
694
class LedBorg(RGBLED):
695
def __init__(self, *, pwm=True, pin_factory=None):
696
"""
697
LedBorg RGB LED board interface.
698
699
Parameters:
700
- pwm: bool - Enable PWM for color control (default: True)
701
- pin_factory: Factory or None - Pin factory for advanced usage
702
"""
703
```
704
705
### PiLiterBarGraph
706
707
PiLiter bar graph variant.
708
709
```python { .api }
710
class PiLiterBarGraph(LEDBarGraph):
711
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
712
"""
713
PiLiter bar graph LED board.
714
715
Parameters:
716
- pwm: bool - Enable PWM brightness control (default: False)
717
- initial_value: bool - Initial state for all LEDs
718
- pin_factory: Factory or None - Pin factory for advanced usage
719
"""
720
```
721
722
### StatusZero
723
724
StatusZero LED board.
725
726
```python { .api }
727
class StatusZero(LEDBoard):
728
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
729
"""
730
StatusZero RGB LED board interface.
731
732
Parameters:
733
- pwm: bool - Enable PWM brightness control (default: False)
734
- initial_value: bool - Initial state for all LEDs
735
- pin_factory: Factory or None - Pin factory for advanced usage
736
"""
737
```
738
739
### StatusBoard
740
741
Generic status board interface.
742
743
```python { .api }
744
class StatusBoard(CompositeOutputDevice):
745
def __init__(self, **named_pins):
746
"""
747
Generic status board with named LED outputs.
748
749
Parameters:
750
- named_pins: Named GPIO pins for LEDs
751
"""
752
```
753
754
### SnowPi
755
756
SnowPi LED board.
757
758
```python { .api }
759
class SnowPi(LEDBoard):
760
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
761
"""
762
SnowPi LED board interface with snowflake pattern.
763
764
Parameters:
765
- pwm: bool - Enable PWM brightness control (default: False)
766
- initial_value: bool - Initial state for all LEDs
767
- pin_factory: Factory or None - Pin factory for advanced usage
768
"""
769
```
770
771
### TrafficLightsBuzzer
772
773
Traffic lights with integrated buzzer.
774
775
```python { .api }
776
class TrafficLightsBuzzer(CompositeOutputDevice):
777
def __init__(self, red=None, amber=None, green=None, buzzer=None, *, pin_factory=None):
778
"""
779
Traffic lights with buzzer for audio signals.
780
781
Parameters:
782
- red: int or str - GPIO pin for red LED
783
- amber: int or str - GPIO pin for amber LED
784
- green: int or str - GPIO pin for green LED
785
- buzzer: int or str - GPIO pin for buzzer
786
- pin_factory: Factory or None - Pin factory for advanced usage
787
"""
788
```
789
790
### FishDish
791
792
FishDish LED board.
793
794
```python { .api }
795
class FishDish(CompositeOutputDevice):
796
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
797
"""
798
FishDish LED board with fish-shaped pattern.
799
800
Parameters:
801
- pwm: bool - Enable PWM brightness control (default: False)
802
- initial_value: bool - Initial state for all LEDs
803
- pin_factory: Factory or None - Pin factory for advanced usage
804
"""
805
```
806
807
### TrafficHat
808
809
Traffic HAT board.
810
811
```python { .api }
812
class TrafficHat(CompositeOutputDevice):
813
def __init__(self, *, pin_factory=None):
814
"""
815
Traffic HAT board with LEDs and buzzer.
816
817
Parameters:
818
- pin_factory: Factory or None - Pin factory for advanced usage
819
"""
820
```
821
822
### TrafficpHat
823
824
Traffic pHAT board.
825
826
```python { .api }
827
class TrafficpHat(TrafficLights):
828
def __init__(self, *, pin_factory=None):
829
"""
830
Traffic pHAT board with traffic light LEDs.
831
832
Parameters:
833
- pin_factory: Factory or None - Pin factory for advanced usage
834
"""
835
```
836
837
### PhaseEnableRobot
838
839
Robot using phase/enable motor control.
840
841
```python { .api }
842
class PhaseEnableRobot(SourceMixin, CompositeDevice):
843
def __init__(self, left=None, right=None, *, pin_factory=None):
844
"""
845
Robot with phase/enable motor control.
846
847
Parameters:
848
- left: tuple - (phase_pin, enable_pin) for left motor
849
- right: tuple - (phase_pin, enable_pin) for right motor
850
- pin_factory: Factory or None - Pin factory for advanced usage
851
"""
852
```
853
854
### PumpkinPi
855
856
PumpkinPi LED board.
857
858
```python { .api }
859
class PumpkinPi(LEDBoard):
860
def __init__(self, *, pwm=False, initial_value=False, pin_factory=None):
861
"""
862
PumpkinPi LED board with pumpkin-shaped pattern.
863
864
Parameters:
865
- pwm: bool - Enable PWM brightness control (default: False)
866
- initial_value: bool - Initial state for all LEDs
867
- pin_factory: Factory or None - Pin factory for advanced usage
868
"""
869
```
870
871
### JamHat
872
873
Jam HAT board.
874
875
```python { .api }
876
class JamHat(CompositeOutputDevice):
877
def __init__(self, *, pin_factory=None):
878
"""
879
Jam HAT board with LEDs, buzzer, and button inputs.
880
881
Parameters:
882
- pin_factory: Factory or None - Pin factory for advanced usage
883
"""
884
```
885
886
### Pibrella
887
888
Pibrella board.
889
890
```python { .api }
891
class Pibrella(CompositeOutputDevice):
892
def __init__(self, *, pin_factory=None):
893
"""
894
Pibrella board with LEDs, buzzer, and button inputs.
895
896
Parameters:
897
- pin_factory: Factory or None - Pin factory for advanced usage
898
"""
899
```