Coverage for /usr/lib/python3/dist-packages/gpiozero/output_devices.py: 20%

525 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-02-10 12:38 +0000

1# vim: set fileencoding=utf-8: 

2# 

3# GPIO Zero: a library for controlling the Raspberry Pi's GPIO pins 

4# 

5# Copyright (c) 2015-2021 Dave Jones <dave@waveform.org.uk> 

6# Copyright (c) 2015-2020 Ben Nuttall <ben@bennuttall.com> 

7# Copyright (c) 2019 tuftii <3215045+tuftii@users.noreply.github.com> 

8# Copyright (c) 2019 tuftii <pi@raspberrypi> 

9# Copyright (c) 2019 Yisrael Dov Lebow 🐻 <lebow@lebowtech.com> 

10# Copyright (c) 2019 Kosovan Sofiia <sofiia.kosovan@gmail.com> 

11# Copyright (c) 2016-2019 Andrew Scheller <github@loowis.durge.org> 

12# Copyright (c) 2016 Ian Harcombe <ian.harcombe@gmail.com> 

13# 

14# SPDX-License-Identifier: BSD-3-Clause 

15 

16from __future__ import ( 

17 unicode_literals, 

18 print_function, 

19 absolute_import, 

20 division, 

21) 

22str = type('') 

23 

24from threading import Lock 

25from itertools import repeat, cycle, chain 

26from colorzero import Color 

27from collections import OrderedDict 

28try: 

29 from math import log2 

30except ImportError: 

31 from .compat import log2 

32import warnings 

33 

34from .exc import ( 

35 OutputDeviceBadValue, 

36 GPIOPinMissing, 

37 PWMSoftwareFallback, 

38 DeviceClosed, 

39) 

40from .devices import GPIODevice, Device, CompositeDevice 

41from .mixins import SourceMixin 

42from .threads import GPIOThread 

43from .tones import Tone 

44try: 

45 from .pins.pigpio import PiGPIOFactory 

46except ImportError: 

47 PiGPIOFactory = None 

48 

49class OutputDevice(SourceMixin, GPIODevice): 

50 """ 

51 Represents a generic GPIO output device. 

52 

53 This class extends :class:`GPIODevice` to add facilities common to GPIO 

54 output devices: an :meth:`on` method to switch the device on, a 

55 corresponding :meth:`off` method, and a :meth:`toggle` method. 

56 

57 :type pin: int or str 

58 :param pin: 

59 The GPIO pin that the device is connected to. See :ref:`pin-numbering` 

60 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

61 will be raised. 

62 

63 :param bool active_high: 

64 If :data:`True` (the default), the :meth:`on` method will set the GPIO 

65 to HIGH. If :data:`False`, the :meth:`on` method will set the GPIO to 

66 LOW (the :meth:`off` method always does the opposite). 

67 

68 :type initial_value: bool or None 

69 :param initial_value: 

70 If :data:`False` (the default), the device will be off initially. If 

71 :data:`None`, the device will be left in whatever state the pin is 

72 found in when configured for output (warning: this can be on). If 

73 :data:`True`, the device will be switched on initially. 

74 

75 :type pin_factory: Factory or None 

76 :param pin_factory: 

77 See :doc:`api_pins` for more information (this is an advanced feature 

78 which most users can ignore). 

79 """ 

80 def __init__( 

81 self, pin=None, active_high=True, initial_value=False, 

82 pin_factory=None): 

83 super(OutputDevice, self).__init__(pin, pin_factory=pin_factory) 

84 self._lock = Lock() 

85 self.active_high = active_high 

86 if initial_value is None: 

87 self.pin.function = 'output' 

88 else: 

89 self.pin.output_with_state(self._value_to_state(initial_value)) 

90 

91 def _value_to_state(self, value): 

92 return bool(self._active_state if value else self._inactive_state) 

93 

94 def _write(self, value): 

95 try: 

96 self.pin.state = self._value_to_state(value) 

97 except AttributeError: 

98 self._check_open() 

99 raise 

100 

101 def on(self): 

102 """ 

103 Turns the device on. 

104 """ 

105 self._write(True) 

106 

107 def off(self): 

108 """ 

109 Turns the device off. 

110 """ 

111 self._write(False) 

112 

113 def toggle(self): 

114 """ 

115 Reverse the state of the device. If it's on, turn it off; if it's off, 

116 turn it on. 

117 """ 

118 with self._lock: 

119 if self.is_active: 

120 self.off() 

121 else: 

122 self.on() 

123 

124 @property 

125 def value(self): 

126 """ 

127 Returns 1 if the device is currently active and 0 otherwise. Setting 

128 this property changes the state of the device. 

129 """ 

130 return super(OutputDevice, self).value 

131 

132 @value.setter 

133 def value(self, value): 

134 self._write(value) 

135 

136 @property 

137 def active_high(self): 

138 """ 

139 When :data:`True`, the :attr:`value` property is :data:`True` when the 

140 device's :attr:`~GPIODevice.pin` is high. When :data:`False` the 

141 :attr:`value` property is :data:`True` when the device's pin is low 

142 (i.e. the value is inverted). 

143 

144 This property can be set after construction; be warned that changing it 

145 will invert :attr:`value` (i.e. changing this property doesn't change 

146 the device's pin state - it just changes how that state is 

147 interpreted). 

148 """ 

149 return self._active_state 

150 

151 @active_high.setter 

152 def active_high(self, value): 

153 self._active_state = True if value else False 

154 self._inactive_state = False if value else True 

155 

156 def __repr__(self): 

157 try: 

158 return '<gpiozero.%s object on pin %r, active_high=%s, is_active=%s>' % ( 

159 self.__class__.__name__, self.pin, self.active_high, self.is_active) 

160 except: 

161 return super(OutputDevice, self).__repr__() 

162 

163 

164class DigitalOutputDevice(OutputDevice): 

165 """ 

166 Represents a generic output device with typical on/off behaviour. 

167 

168 This class extends :class:`OutputDevice` with a :meth:`blink` method which 

169 uses an optional background thread to handle toggling the device state 

170 without further interaction. 

171 

172 :type pin: int or str 

173 :param pin: 

174 The GPIO pin that the device is connected to. See :ref:`pin-numbering` 

175 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

176 will be raised. 

177 

178 :param bool active_high: 

179 If :data:`True` (the default), the :meth:`on` method will set the GPIO 

180 to HIGH. If :data:`False`, the :meth:`on` method will set the GPIO to 

181 LOW (the :meth:`off` method always does the opposite). 

182 

183 :type initial_value: bool or None 

184 :param initial_value: 

185 If :data:`False` (the default), the device will be off initially. If 

186 :data:`None`, the device will be left in whatever state the pin is 

187 found in when configured for output (warning: this can be on). If 

188 :data:`True`, the device will be switched on initially. 

189 

190 :type pin_factory: Factory or None 

191 :param pin_factory: 

192 See :doc:`api_pins` for more information (this is an advanced feature 

193 which most users can ignore). 

194 """ 

195 def __init__( 

196 self, pin=None, active_high=True, initial_value=False, 

197 pin_factory=None): 

198 self._blink_thread = None 

199 self._controller = None 

200 super(DigitalOutputDevice, self).__init__( 

201 pin, active_high, initial_value, pin_factory=pin_factory 

202 ) 

203 

204 @property 

205 def value(self): 

206 return super(DigitalOutputDevice, self).value 

207 

208 @value.setter 

209 def value(self, value): 

210 self._stop_blink() 

211 self._write(value) 

212 

213 def close(self): 

214 self._stop_blink() 

215 super(DigitalOutputDevice, self).close() 

216 

217 def on(self): 

218 self._stop_blink() 

219 self._write(True) 

220 

221 def off(self): 

222 self._stop_blink() 

223 self._write(False) 

224 

225 def blink(self, on_time=1, off_time=1, n=None, background=True): 

226 """ 

227 Make the device turn on and off repeatedly. 

228 

229 :param float on_time: 

230 Number of seconds on. Defaults to 1 second. 

231 

232 :param float off_time: 

233 Number of seconds off. Defaults to 1 second. 

234 

235 :type n: int or None 

236 :param n: 

237 Number of times to blink; :data:`None` (the default) means forever. 

238 

239 :param bool background: 

240 If :data:`True` (the default), start a background thread to 

241 continue blinking and return immediately. If :data:`False`, only 

242 return when the blink is finished (warning: the default value of 

243 *n* will result in this method never returning). 

244 """ 

245 self._stop_blink() 

246 self._blink_thread = GPIOThread( 

247 self._blink_device, (on_time, off_time, n) 

248 ) 

249 self._blink_thread.start() 

250 if not background: 

251 self._blink_thread.join() 

252 self._blink_thread = None 

253 

254 def _stop_blink(self): 

255 if getattr(self, '_controller', None): 

256 self._controller._stop_blink(self) 

257 self._controller = None 

258 if getattr(self, '_blink_thread', None): 

259 self._blink_thread.stop() 

260 self._blink_thread = None 

261 

262 def _blink_device(self, on_time, off_time, n): 

263 iterable = repeat(0) if n is None else repeat(0, n) 

264 for _ in iterable: 

265 self._write(True) 

266 if self._blink_thread.stopping.wait(on_time): 

267 break 

268 self._write(False) 

269 if self._blink_thread.stopping.wait(off_time): 

270 break 

271 

272 

273class LED(DigitalOutputDevice): 

274 """ 

275 Extends :class:`DigitalOutputDevice` and represents a light emitting diode 

276 (LED). 

277 

278 Connect the cathode (short leg, flat side) of the LED to a ground pin; 

279 connect the anode (longer leg) to a limiting resistor; connect the other 

280 side of the limiting resistor to a GPIO pin (the limiting resistor can be 

281 placed either side of the LED). 

282 

283 The following example will light the LED:: 

284 

285 from gpiozero import LED 

286 

287 led = LED(17) 

288 led.on() 

289 

290 :type pin: int or str 

291 :param pin: 

292 The GPIO pin which the LED is connected to. See :ref:`pin-numbering` 

293 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

294 will be raised. 

295 

296 :param bool active_high: 

297 If :data:`True` (the default), the LED will operate normally with the 

298 circuit described above. If :data:`False` you should wire the cathode 

299 to the GPIO pin, and the anode to a 3V3 pin (via a limiting resistor). 

300 

301 :type initial_value: bool or None 

302 :param initial_value: 

303 If :data:`False` (the default), the LED will be off initially. If 

304 :data:`None`, the LED will be left in whatever state the pin is found 

305 in when configured for output (warning: this can be on). If 

306 :data:`True`, the LED will be switched on initially. 

307 

308 :type pin_factory: Factory or None 

309 :param pin_factory: 

310 See :doc:`api_pins` for more information (this is an advanced feature 

311 which most users can ignore). 

312 """ 

313 pass 

314 

315LED.is_lit = LED.is_active 

316 

317 

318class Buzzer(DigitalOutputDevice): 

319 """ 

320 Extends :class:`DigitalOutputDevice` and represents a digital buzzer 

321 component. 

322 

323 .. note:: 

324 

325 This interface is only capable of simple on/off commands, and is not 

326 capable of playing a variety of tones (see :class:`TonalBuzzer`). 

327 

328 Connect the cathode (negative pin) of the buzzer to a ground pin; connect 

329 the other side to any GPIO pin. 

330 

331 The following example will sound the buzzer:: 

332 

333 from gpiozero import Buzzer 

334 

335 bz = Buzzer(3) 

336 bz.on() 

337 

338 :type pin: int or str 

339 :param pin: 

340 The GPIO pin which the buzzer is connected to. See :ref:`pin-numbering` 

341 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

342 will be raised. 

343 

344 :param bool active_high: 

345 If :data:`True` (the default), the buzzer will operate normally with 

346 the circuit described above. If :data:`False` you should wire the 

347 cathode to the GPIO pin, and the anode to a 3V3 pin. 

348 

349 :type initial_value: bool or None 

350 :param initial_value: 

351 If :data:`False` (the default), the buzzer will be silent initially. If 

352 :data:`None`, the buzzer will be left in whatever state the pin is 

353 found in when configured for output (warning: this can be on). If 

354 :data:`True`, the buzzer will be switched on initially. 

355 

356 :type pin_factory: Factory or None 

357 :param pin_factory: 

358 See :doc:`api_pins` for more information (this is an advanced feature 

359 which most users can ignore). 

360 """ 

361 pass 

362 

363Buzzer.beep = Buzzer.blink 

364 

365 

366class PWMOutputDevice(OutputDevice): 

367 """ 

368 Generic output device configured for pulse-width modulation (PWM). 

369 

370 :type pin: int or str 

371 :param pin: 

372 The GPIO pin that the device is connected to. See :ref:`pin-numbering` 

373 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

374 will be raised. 

375 

376 :param bool active_high: 

377 If :data:`True` (the default), the :meth:`on` method will set the GPIO 

378 to HIGH. If :data:`False`, the :meth:`on` method will set the GPIO to 

379 LOW (the :meth:`off` method always does the opposite). 

380 

381 :param float initial_value: 

382 If 0 (the default), the device's duty cycle will be 0 initially. 

383 Other values between 0 and 1 can be specified as an initial duty cycle. 

384 Note that :data:`None` cannot be specified (unlike the parent class) as 

385 there is no way to tell PWM not to alter the state of the pin. 

386 

387 :param int frequency: 

388 The frequency (in Hz) of pulses emitted to drive the device. Defaults 

389 to 100Hz. 

390 

391 :type pin_factory: Factory or None 

392 :param pin_factory: 

393 See :doc:`api_pins` for more information (this is an advanced feature 

394 which most users can ignore). 

395 """ 

396 def __init__( 

397 self, pin=None, active_high=True, initial_value=0, frequency=100, 

398 pin_factory=None): 

399 self._blink_thread = None 

400 self._controller = None 

401 if not 0 <= initial_value <= 1: 

402 raise OutputDeviceBadValue("initial_value must be between 0 and 1") 

403 super(PWMOutputDevice, self).__init__( 

404 pin, active_high, initial_value=None, pin_factory=pin_factory 

405 ) 

406 try: 

407 # XXX need a way of setting these together 

408 self.pin.frequency = frequency 

409 self.value = initial_value 

410 except: 

411 self.close() 

412 raise 

413 

414 def close(self): 

415 try: 

416 self._stop_blink() 

417 except AttributeError: 

418 pass 

419 try: 

420 self.pin.frequency = None 

421 except AttributeError: 

422 # If the pin's already None, ignore the exception 

423 pass 

424 super(PWMOutputDevice, self).close() 

425 

426 def _state_to_value(self, state): 

427 return float(state if self.active_high else 1 - state) 

428 

429 def _value_to_state(self, value): 

430 return float(value if self.active_high else 1 - value) 

431 

432 def _write(self, value): 

433 if not 0 <= value <= 1: 

434 raise OutputDeviceBadValue("PWM value must be between 0 and 1") 

435 super(PWMOutputDevice, self)._write(value) 

436 

437 @property 

438 def value(self): 

439 """ 

440 The duty cycle of the PWM device. 0.0 is off, 1.0 is fully on. Values 

441 in between may be specified for varying levels of power in the device. 

442 """ 

443 return super(PWMOutputDevice, self).value 

444 

445 @value.setter 

446 def value(self, value): 

447 self._stop_blink() 

448 self._write(value) 

449 

450 def on(self): 

451 self._stop_blink() 

452 self._write(1) 

453 

454 def off(self): 

455 self._stop_blink() 

456 self._write(0) 

457 

458 def toggle(self): 

459 """ 

460 Toggle the state of the device. If the device is currently off 

461 (:attr:`value` is 0.0), this changes it to "fully" on (:attr:`value` is 

462 1.0). If the device has a duty cycle (:attr:`value`) of 0.1, this will 

463 toggle it to 0.9, and so on. 

464 """ 

465 self._stop_blink() 

466 self.value = 1 - self.value 

467 

468 @property 

469 def is_active(self): 

470 """ 

471 Returns :data:`True` if the device is currently active (:attr:`value` 

472 is non-zero) and :data:`False` otherwise. 

473 """ 

474 return self.value != 0 

475 

476 @property 

477 def frequency(self): 

478 """ 

479 The frequency of the pulses used with the PWM device, in Hz. The 

480 default is 100Hz. 

481 """ 

482 return self.pin.frequency 

483 

484 @frequency.setter 

485 def frequency(self, value): 

486 self.pin.frequency = value 

487 

488 def blink( 

489 self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, 

490 n=None, background=True): 

491 """ 

492 Make the device turn on and off repeatedly. 

493 

494 :param float on_time: 

495 Number of seconds on. Defaults to 1 second. 

496 

497 :param float off_time: 

498 Number of seconds off. Defaults to 1 second. 

499 

500 :param float fade_in_time: 

501 Number of seconds to spend fading in. Defaults to 0. 

502 

503 :param float fade_out_time: 

504 Number of seconds to spend fading out. Defaults to 0. 

505 

506 :type n: int or None 

507 :param n: 

508 Number of times to blink; :data:`None` (the default) means forever. 

509 

510 :param bool background: 

511 If :data:`True` (the default), start a background thread to 

512 continue blinking and return immediately. If :data:`False`, only 

513 return when the blink is finished (warning: the default value of 

514 *n* will result in this method never returning). 

515 """ 

516 self._stop_blink() 

517 self._blink_thread = GPIOThread( 

518 self._blink_device, 

519 (on_time, off_time, fade_in_time, fade_out_time, n) 

520 ) 

521 self._blink_thread.start() 

522 if not background: 

523 self._blink_thread.join() 

524 self._blink_thread = None 

525 

526 def pulse(self, fade_in_time=1, fade_out_time=1, n=None, background=True): 

527 """ 

528 Make the device fade in and out repeatedly. 

529 

530 :param float fade_in_time: 

531 Number of seconds to spend fading in. Defaults to 1. 

532 

533 :param float fade_out_time: 

534 Number of seconds to spend fading out. Defaults to 1. 

535 

536 :type n: int or None 

537 :param n: 

538 Number of times to pulse; :data:`None` (the default) means forever. 

539 

540 :param bool background: 

541 If :data:`True` (the default), start a background thread to 

542 continue pulsing and return immediately. If :data:`False`, only 

543 return when the pulse is finished (warning: the default value of 

544 *n* will result in this method never returning). 

545 """ 

546 on_time = off_time = 0 

547 self.blink( 

548 on_time, off_time, fade_in_time, fade_out_time, n, background 

549 ) 

550 

551 def _stop_blink(self): 

552 if self._controller: 

553 self._controller._stop_blink(self) 

554 self._controller = None 

555 if self._blink_thread: 

556 self._blink_thread.stop() 

557 self._blink_thread = None 

558 

559 def _blink_device( 

560 self, on_time, off_time, fade_in_time, fade_out_time, n, fps=25): 

561 sequence = [] 

562 if fade_in_time > 0: 

563 sequence += [ 

564 (i * (1 / fps) / fade_in_time, 1 / fps) 

565 for i in range(int(fps * fade_in_time)) 

566 ] 

567 sequence.append((1, on_time)) 

568 if fade_out_time > 0: 

569 sequence += [ 

570 (1 - (i * (1 / fps) / fade_out_time), 1 / fps) 

571 for i in range(int(fps * fade_out_time)) 

572 ] 

573 sequence.append((0, off_time)) 

574 sequence = ( 

575 cycle(sequence) if n is None else 

576 chain.from_iterable(repeat(sequence, n)) 

577 ) 

578 for value, delay in sequence: 

579 self._write(value) 

580 if self._blink_thread.stopping.wait(delay): 

581 break 

582 

583 

584class TonalBuzzer(SourceMixin, CompositeDevice): 

585 """ 

586 Extends :class:`CompositeDevice` and represents a tonal buzzer. 

587 

588 :type pin: int or str 

589 :param pin: 

590 The GPIO pin which the buzzer is connected to. See :ref:`pin-numbering` 

591 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

592 will be raised. 

593 

594 :param float initial_value: 

595 If :data:`None` (the default), the buzzer will be off initially. Values 

596 between -1 and 1 can be specified as an initial value for the buzzer. 

597 

598 :type mid_tone: int or str 

599 :param mid_tone: 

600 The tone which is represented the device's middle value (0). The 

601 default is "A4" (MIDI note 69). 

602 

603 :param int octaves: 

604 The number of octaves to allow away from the base note. The default is 

605 1, meaning a value of -1 goes one octave below the base note, and one 

606 above, i.e. from A3 to A5 with the default base note of A4. 

607 

608 :type pin_factory: Factory or None 

609 :param pin_factory: 

610 See :doc:`api_pins` for more information (this is an advanced feature 

611 which most users can ignore). 

612 

613 .. note:: 

614 

615 Note that this class does not currently work with 

616 :class:`~gpiozero.pins.pigpio.PiGPIOFactory`. 

617 """ 

618 

619 def __init__(self, pin=None, initial_value=None, mid_tone=Tone("A4"), 

620 octaves=1, pin_factory=None): 

621 self._mid_tone = None 

622 super(TonalBuzzer, self).__init__( 

623 pwm_device=PWMOutputDevice( 

624 pin=pin, pin_factory=pin_factory 

625 ), pin_factory=pin_factory) 

626 try: 

627 self._mid_tone = Tone(mid_tone) 

628 if not (0 < octaves <= 9): 

629 raise ValueError('octaves must be between 1 and 9') 

630 self._octaves = octaves 

631 try: 

632 self.min_tone.note 

633 except ValueError: 

634 raise ValueError( 

635 '%r is too low for %d octaves' % 

636 (self._mid_tone, self._octaves)) 

637 try: 

638 self.max_tone.note 

639 except ValueError: 

640 raise ValueError( 

641 '%r is too high for %d octaves' % 

642 (self._mid_tone, self._octaves)) 

643 self.value = initial_value 

644 except: 

645 self.close() 

646 raise 

647 

648 def __repr__(self): 

649 try: 

650 self._check_open() 

651 if self.value is None: 

652 return '<gpiozero.TonalBuzzer object on pin %r, silent>' % ( 

653 self.pwm_device.pin,) 

654 else: 

655 return '<gpiozero.TonalBuzzer object on pin %r, playing %s>' % ( 

656 self.pwm_device.pin, self.tone.note) 

657 except DeviceClosed: 

658 return super(TonalBuzzer, self).__repr__() 

659 

660 def play(self, tone): 

661 """ 

662 Play the given *tone*. This can either be an instance of 

663 :class:`~gpiozero.tones.Tone` or can be anything that could be used to 

664 construct an instance of :class:`~gpiozero.tones.Tone`. 

665 

666 For example:: 

667 

668 >>> from gpiozero import TonalBuzzer 

669 >>> from gpiozero.tones import Tone 

670 >>> b = TonalBuzzer(17) 

671 >>> b.play(Tone("A4")) 

672 >>> b.play(Tone(220.0)) # Hz 

673 >>> b.play(Tone(60)) # middle C in MIDI notation 

674 >>> b.play("A4") 

675 >>> b.play(220.0) 

676 >>> b.play(60) 

677 """ 

678 if tone is None: 

679 self.value = None 

680 else: 

681 if not isinstance(tone, Tone): 

682 tone = Tone(tone) 

683 freq = tone.frequency 

684 if self.min_tone.frequency <= tone <= self.max_tone.frequency: 

685 self.pwm_device.pin.frequency = freq 

686 self.pwm_device.value = 0.5 

687 else: 

688 raise ValueError("tone is out of the device's range") 

689 

690 def stop(self): 

691 """ 

692 Turn the buzzer off. This is equivalent to setting :attr:`value` to 

693 :data:`None`. 

694 """ 

695 self.value = None 

696 

697 @property 

698 def tone(self): 

699 """ 

700 Returns the :class:`~gpiozero.tones.Tone` that the buzzer is currently 

701 playing, or :data:`None` if the buzzer is silent. This property can 

702 also be set to play the specified tone. 

703 """ 

704 if self.pwm_device.pin.frequency is None: 

705 return None 

706 else: 

707 return Tone.from_frequency(self.pwm_device.pin.frequency) 

708 

709 @tone.setter 

710 def tone(self, value): 

711 self.play(value) 

712 

713 @property 

714 def value(self): 

715 """ 

716 Represents the state of the buzzer as a value between -1 (representing 

717 the minimum tone) and 1 (representing the maximum tone). This can also 

718 be the special value :data:`None` indicating that the buzzer is 

719 currently silent. 

720 """ 

721 if self.pwm_device.pin.frequency is None: 

722 return None 

723 else: 

724 # Can't have zero-division here; zero-frequency Tone cannot be 

725 # generated and self.octaves cannot be zero either 

726 return log2( 

727 self.pwm_device.pin.frequency / self.mid_tone.frequency 

728 ) / self.octaves 

729 

730 @value.setter 

731 def value(self, value): 

732 if value is None: 

733 self.pwm_device.pin.frequency = None 

734 elif -1 <= value <= 1: 

735 freq = self.mid_tone.frequency * 2 ** (self.octaves * value) 

736 self.pwm_device.pin.frequency = freq 

737 self.pwm_device.value = 0.5 

738 else: 

739 raise OutputDeviceBadValue( 

740 'TonalBuzzer value must be between -1 and 1, or None') 

741 

742 @property 

743 def is_active(self): 

744 """ 

745 Returns :data:`True` if the buzzer is currently playing, otherwise 

746 :data:`False`. 

747 """ 

748 return self.value is not None 

749 

750 @property 

751 def octaves(self): 

752 """ 

753 The number of octaves available (above and below mid_tone). 

754 """ 

755 return self._octaves 

756 

757 @property 

758 def min_tone(self): 

759 """ 

760 The lowest tone that the buzzer can play, i.e. the tone played 

761 when :attr:`value` is -1. 

762 """ 

763 return self._mid_tone.down(12 * self.octaves) 

764 

765 @property 

766 def mid_tone(self): 

767 """ 

768 The middle tone available, i.e. the tone played when :attr:`value` is 

769 0. 

770 """ 

771 return self._mid_tone 

772 

773 @property 

774 def max_tone(self): 

775 """ 

776 The highest tone that the buzzer can play, i.e. the tone played when 

777 :attr:`value` is 1. 

778 """ 

779 return self._mid_tone.up(12 * self.octaves) 

780 

781 

782class PWMLED(PWMOutputDevice): 

783 """ 

784 Extends :class:`PWMOutputDevice` and represents a light emitting diode 

785 (LED) with variable brightness. 

786 

787 A typical configuration of such a device is to connect a GPIO pin to the 

788 anode (long leg) of the LED, and the cathode (short leg) to ground, with 

789 an optional resistor to prevent the LED from burning out. 

790 

791 :type pin: int or str 

792 :param pin: 

793 The GPIO pin which the LED is connected to. See :ref:`pin-numbering` 

794 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

795 will be raised. 

796 

797 :param bool active_high: 

798 If :data:`True` (the default), the :meth:`on` method will set the GPIO 

799 to HIGH. If :data:`False`, the :meth:`on` method will set the GPIO to 

800 LOW (the :meth:`off` method always does the opposite). 

801 

802 :param float initial_value: 

803 If ``0`` (the default), the LED will be off initially. Other values 

804 between 0 and 1 can be specified as an initial brightness for the LED. 

805 Note that :data:`None` cannot be specified (unlike the parent class) as 

806 there is no way to tell PWM not to alter the state of the pin. 

807 

808 :param int frequency: 

809 The frequency (in Hz) of pulses emitted to drive the LED. Defaults 

810 to 100Hz. 

811 

812 :type pin_factory: Factory or None 

813 :param pin_factory: 

814 See :doc:`api_pins` for more information (this is an advanced feature 

815 which most users can ignore). 

816 """ 

817 pass 

818 

819PWMLED.is_lit = PWMLED.is_active 

820 

821 

822class RGBLED(SourceMixin, Device): 

823 """ 

824 Extends :class:`Device` and represents a full color LED component (composed 

825 of red, green, and blue LEDs). 

826 

827 Connect the common cathode (longest leg) to a ground pin; connect each of 

828 the other legs (representing the red, green, and blue anodes) to any GPIO 

829 pins. You should use three limiting resistors (one per anode). 

830 

831 The following code will make the LED yellow:: 

832 

833 from gpiozero import RGBLED 

834 

835 led = RGBLED(2, 3, 4) 

836 led.color = (1, 1, 0) 

837 

838 The `colorzero`_ library is also supported:: 

839 

840 from gpiozero import RGBLED 

841 from colorzero import Color 

842 

843 led = RGBLED(2, 3, 4) 

844 led.color = Color('yellow') 

845 

846 :type red: int or str 

847 :param red: 

848 The GPIO pin that controls the red component of the RGB LED. See 

849 :ref:`pin-numbering` for valid pin numbers. If this is :data:`None` a 

850 :exc:`GPIODeviceError` will be raised. 

851 

852 :type green: int or str 

853 :param green: 

854 The GPIO pin that controls the green component of the RGB LED. 

855 

856 :type blue: int or str 

857 :param blue: 

858 The GPIO pin that controls the blue component of the RGB LED. 

859 

860 :param bool active_high: 

861 Set to :data:`True` (the default) for common cathode RGB LEDs. If you 

862 are using a common anode RGB LED, set this to :data:`False`. 

863 

864 :type initial_value: ~colorzero.Color or tuple 

865 :param initial_value: 

866 The initial color for the RGB LED. Defaults to black ``(0, 0, 0)``. 

867 

868 :param bool pwm: 

869 If :data:`True` (the default), construct :class:`PWMLED` instances for 

870 each component of the RGBLED. If :data:`False`, construct regular 

871 :class:`LED` instances, which prevents smooth color graduations. 

872 

873 :type pin_factory: Factory or None 

874 :param pin_factory: 

875 See :doc:`api_pins` for more information (this is an advanced feature 

876 which most users can ignore). 

877 

878 .. _colorzero: https://colorzero.readthedocs.io/ 

879 """ 

880 def __init__( 

881 self, red=None, green=None, blue=None, active_high=True, 

882 initial_value=(0, 0, 0), pwm=True, pin_factory=None): 

883 self._leds = () 

884 self._blink_thread = None 

885 if not all(p is not None for p in [red, green, blue]): 

886 raise GPIOPinMissing('red, green, and blue pins must be provided') 

887 LEDClass = PWMLED if pwm else LED 

888 super(RGBLED, self).__init__(pin_factory=pin_factory) 

889 self._leds = tuple( 

890 LEDClass(pin, active_high, pin_factory=pin_factory) 

891 for pin in (red, green, blue) 

892 ) 

893 self.value = initial_value 

894 

895 def close(self): 

896 if getattr(self, '_leds', None): 

897 self._stop_blink() 

898 for led in self._leds: 

899 led.close() 

900 self._leds = () 

901 super(RGBLED, self).close() 

902 

903 @property 

904 def closed(self): 

905 return len(self._leds) == 0 

906 

907 @property 

908 def value(self): 

909 """ 

910 Represents the color of the LED as an RGB 3-tuple of ``(red, green, 

911 blue)`` where each value is between 0 and 1 if *pwm* was :data:`True` 

912 when the class was constructed (and only 0 or 1 if not). 

913 

914 For example, red would be ``(1, 0, 0)`` and yellow would be ``(1, 1, 

915 0)``, while orange would be ``(1, 0.5, 0)``. 

916 """ 

917 return tuple(led.value for led in self._leds) 

918 

919 @value.setter 

920 def value(self, value): 

921 for component in value: 

922 if not 0 <= component <= 1: 

923 raise OutputDeviceBadValue( 

924 'each RGB color component must be between 0 and 1') 

925 if isinstance(self._leds[0], LED): 

926 if component not in (0, 1): 

927 raise OutputDeviceBadValue( 

928 'each RGB color component must be 0 or 1 with non-PWM ' 

929 'RGBLEDs') 

930 self._stop_blink() 

931 for led, v in zip(self._leds, value): 

932 led.value = v 

933 

934 @property 

935 def is_active(self): 

936 """ 

937 Returns :data:`True` if the LED is currently active (not black) and 

938 :data:`False` otherwise. 

939 """ 

940 return self.value != (0, 0, 0) 

941 

942 is_lit = is_active 

943 

944 @property 

945 def color(self): 

946 """ 

947 Represents the color of the LED as a :class:`~colorzero.Color` object. 

948 """ 

949 return Color(*self.value) 

950 

951 @color.setter 

952 def color(self, value): 

953 self.value = value 

954 

955 @property 

956 def red(self): 

957 """ 

958 Represents the red element of the LED as a :class:`~colorzero.Red` 

959 object. 

960 """ 

961 return self.color.red 

962 

963 @red.setter 

964 def red(self, value): 

965 self._stop_blink() 

966 r, g, b = self.value 

967 self.value = value, g, b 

968 

969 @property 

970 def green(self): 

971 """ 

972 Represents the green element of the LED as a :class:`~colorzero.Green` 

973 object. 

974 """ 

975 return self.color.green 

976 

977 @green.setter 

978 def green(self, value): 

979 self._stop_blink() 

980 r, g, b = self.value 

981 self.value = r, value, b 

982 

983 @property 

984 def blue(self): 

985 """ 

986 Represents the blue element of the LED as a :class:`~colorzero.Blue` 

987 object. 

988 """ 

989 return self.color.blue 

990 

991 @blue.setter 

992 def blue(self, value): 

993 self._stop_blink() 

994 r, g, b = self.value 

995 self.value = r, g, value 

996 

997 def on(self): 

998 """ 

999 Turn the LED on. This equivalent to setting the LED color to white 

1000 ``(1, 1, 1)``. 

1001 """ 

1002 self.value = (1, 1, 1) 

1003 

1004 def off(self): 

1005 """ 

1006 Turn the LED off. This is equivalent to setting the LED color to black 

1007 ``(0, 0, 0)``. 

1008 """ 

1009 self.value = (0, 0, 0) 

1010 

1011 def toggle(self): 

1012 """ 

1013 Toggle the state of the device. If the device is currently off 

1014 (:attr:`value` is ``(0, 0, 0)``), this changes it to "fully" on 

1015 (:attr:`value` is ``(1, 1, 1)``). If the device has a specific color, 

1016 this method inverts the color. 

1017 """ 

1018 r, g, b = self.value 

1019 self.value = (1 - r, 1 - g, 1 - b) 

1020 

1021 def blink( 

1022 self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, 

1023 on_color=(1, 1, 1), off_color=(0, 0, 0), n=None, background=True): 

1024 """ 

1025 Make the device turn on and off repeatedly. 

1026 

1027 :param float on_time: 

1028 Number of seconds on. Defaults to 1 second. 

1029 

1030 :param float off_time: 

1031 Number of seconds off. Defaults to 1 second. 

1032 

1033 :param float fade_in_time: 

1034 Number of seconds to spend fading in. Defaults to 0. Must be 0 if 

1035 *pwm* was :data:`False` when the class was constructed 

1036 (:exc:`ValueError` will be raised if not). 

1037 

1038 :param float fade_out_time: 

1039 Number of seconds to spend fading out. Defaults to 0. Must be 0 if 

1040 *pwm* was :data:`False` when the class was constructed 

1041 (:exc:`ValueError` will be raised if not). 

1042 

1043 :type on_color: ~colorzero.Color or tuple 

1044 :param on_color: 

1045 The color to use when the LED is "on". Defaults to white. 

1046 

1047 :type off_color: ~colorzero.Color or tuple 

1048 :param off_color: 

1049 The color to use when the LED is "off". Defaults to black. 

1050 

1051 :type n: int or None 

1052 :param n: 

1053 Number of times to blink; :data:`None` (the default) means forever. 

1054 

1055 :param bool background: 

1056 If :data:`True` (the default), start a background thread to 

1057 continue blinking and return immediately. If :data:`False`, only 

1058 return when the blink is finished (warning: the default value of 

1059 *n* will result in this method never returning). 

1060 """ 

1061 if isinstance(self._leds[0], LED): 

1062 if fade_in_time: 

1063 raise ValueError('fade_in_time must be 0 with non-PWM RGBLEDs') 

1064 if fade_out_time: 

1065 raise ValueError('fade_out_time must be 0 with non-PWM RGBLEDs') 

1066 self._stop_blink() 

1067 self._blink_thread = GPIOThread( 

1068 self._blink_device, 

1069 ( 

1070 on_time, off_time, fade_in_time, fade_out_time, 

1071 on_color, off_color, n 

1072 ) 

1073 ) 

1074 self._blink_thread.start() 

1075 if not background: 

1076 self._blink_thread.join() 

1077 self._blink_thread = None 

1078 

1079 def pulse( 

1080 self, fade_in_time=1, fade_out_time=1, 

1081 on_color=(1, 1, 1), off_color=(0, 0, 0), n=None, background=True): 

1082 """ 

1083 Make the device fade in and out repeatedly. 

1084 

1085 :param float fade_in_time: 

1086 Number of seconds to spend fading in. Defaults to 1. 

1087 

1088 :param float fade_out_time: 

1089 Number of seconds to spend fading out. Defaults to 1. 

1090 

1091 :type on_color: ~colorzero.Color or tuple 

1092 :param on_color: 

1093 The color to use when the LED is "on". Defaults to white. 

1094 

1095 :type off_color: ~colorzero.Color or tuple 

1096 :param off_color: 

1097 The color to use when the LED is "off". Defaults to black. 

1098 

1099 :type n: int or None 

1100 :param n: 

1101 Number of times to pulse; :data:`None` (the default) means forever. 

1102 

1103 :param bool background: 

1104 If :data:`True` (the default), start a background thread to 

1105 continue pulsing and return immediately. If :data:`False`, only 

1106 return when the pulse is finished (warning: the default value of 

1107 *n* will result in this method never returning). 

1108 """ 

1109 on_time = off_time = 0 

1110 self.blink( 

1111 on_time, off_time, fade_in_time, fade_out_time, 

1112 on_color, off_color, n, background 

1113 ) 

1114 

1115 def _stop_blink(self, led=None): 

1116 # If this is called with a single led, we stop all blinking anyway 

1117 if self._blink_thread: 

1118 self._blink_thread.stop() 

1119 self._blink_thread = None 

1120 

1121 def _blink_device( 

1122 self, on_time, off_time, fade_in_time, fade_out_time, on_color, 

1123 off_color, n, fps=25): 

1124 # Define a simple lambda to perform linear interpolation between 

1125 # off_color and on_color 

1126 lerp = lambda t, fade_in: tuple( 

1127 (1 - t) * off + t * on 

1128 if fade_in else 

1129 (1 - t) * on + t * off 

1130 for off, on in zip(off_color, on_color) 

1131 ) 

1132 sequence = [] 

1133 if fade_in_time > 0: 

1134 sequence += [ 

1135 (lerp(i * (1 / fps) / fade_in_time, True), 1 / fps) 

1136 for i in range(int(fps * fade_in_time)) 

1137 ] 

1138 sequence.append((on_color, on_time)) 

1139 if fade_out_time > 0: 

1140 sequence += [ 

1141 (lerp(i * (1 / fps) / fade_out_time, False), 1 / fps) 

1142 for i in range(int(fps * fade_out_time)) 

1143 ] 

1144 sequence.append((off_color, off_time)) 

1145 sequence = ( 

1146 cycle(sequence) if n is None else 

1147 chain.from_iterable(repeat(sequence, n)) 

1148 ) 

1149 for l in self._leds: 

1150 l._controller = self 

1151 for value, delay in sequence: 

1152 for l, v in zip(self._leds, value): 

1153 l._write(v) 

1154 if self._blink_thread.stopping.wait(delay): 

1155 break 

1156 

1157 

1158class Motor(SourceMixin, CompositeDevice): 

1159 """ 

1160 Extends :class:`CompositeDevice` and represents a generic motor 

1161 connected to a bi-directional motor driver circuit (i.e. an `H-bridge`_). 

1162 

1163 Attach an `H-bridge`_ motor controller to your Pi; connect a power source 

1164 (e.g. a battery pack or the 5V pin) to the controller; connect the outputs 

1165 of the controller board to the two terminals of the motor; connect the 

1166 inputs of the controller board to two GPIO pins. 

1167 

1168 .. _H-bridge: https://en.wikipedia.org/wiki/H_bridge 

1169 

1170 The following code will make the motor turn "forwards":: 

1171 

1172 from gpiozero import Motor 

1173 

1174 motor = Motor(17, 18) 

1175 motor.forward() 

1176 

1177 :type forward: int or str 

1178 :param forward: 

1179 The GPIO pin that the forward input of the motor driver chip is 

1180 connected to. See :ref:`pin-numbering` for valid pin numbers. If this 

1181 is :data:`None` a :exc:`GPIODeviceError` will be raised. 

1182 

1183 :type backward: int or str 

1184 :param backward: 

1185 The GPIO pin that the backward input of the motor driver chip is 

1186 connected to. See :ref:`pin-numbering` for valid pin numbers. If this 

1187 is :data:`None` a :exc:`GPIODeviceError` will be raised. 

1188 

1189 :type enable: int or str or None 

1190 :param enable: 

1191 The GPIO pin that enables the motor. Required for *some* motor 

1192 controller boards. See :ref:`pin-numbering` for valid pin numbers. 

1193 

1194 :param bool pwm: 

1195 If :data:`True` (the default), construct :class:`PWMOutputDevice` 

1196 instances for the motor controller pins, allowing both direction and 

1197 variable speed control. If :data:`False`, construct 

1198 :class:`DigitalOutputDevice` instances, allowing only direction 

1199 control. 

1200 

1201 :type pin_factory: Factory or None 

1202 :param pin_factory: 

1203 See :doc:`api_pins` for more information (this is an advanced feature 

1204 which most users can ignore). 

1205 """ 

1206 def __init__(self, forward=None, backward=None, enable=None, pwm=True, 

1207 pin_factory=None): 

1208 if not all(p is not None for p in [forward, backward]): 

1209 raise GPIOPinMissing( 

1210 'forward and backward pins must be provided' 

1211 ) 

1212 PinClass = PWMOutputDevice if pwm else DigitalOutputDevice 

1213 devices = OrderedDict(( 

1214 ('forward_device', PinClass(forward, pin_factory=pin_factory)), 

1215 ('backward_device', PinClass(backward, pin_factory=pin_factory)), 

1216 )) 

1217 if enable is not None: 

1218 devices['enable_device'] = DigitalOutputDevice( 

1219 enable, 

1220 initial_value=True, 

1221 pin_factory=pin_factory 

1222 ) 

1223 super(Motor, self).__init__(_order=devices.keys(), **devices) 

1224 

1225 @property 

1226 def value(self): 

1227 """ 

1228 Represents the speed of the motor as a floating point value between -1 

1229 (full speed backward) and 1 (full speed forward), with 0 representing 

1230 stopped. 

1231 """ 

1232 return self.forward_device.value - self.backward_device.value 

1233 

1234 @value.setter 

1235 def value(self, value): 

1236 if not -1 <= value <= 1: 

1237 raise OutputDeviceBadValue("Motor value must be between -1 and 1") 

1238 if value > 0: 

1239 try: 

1240 self.forward(value) 

1241 except ValueError as e: 

1242 raise OutputDeviceBadValue(e) 

1243 elif value < 0: 

1244 try: 

1245 self.backward(-value) 

1246 except ValueError as e: 

1247 raise OutputDeviceBadValue(e) 

1248 else: 

1249 self.stop() 

1250 

1251 @property 

1252 def is_active(self): 

1253 """ 

1254 Returns :data:`True` if the motor is currently running and 

1255 :data:`False` otherwise. 

1256 """ 

1257 return self.value != 0 

1258 

1259 def forward(self, speed=1): 

1260 """ 

1261 Drive the motor forwards. 

1262 

1263 :param float speed: 

1264 The speed at which the motor should turn. Can be any value between 

1265 0 (stopped) and the default 1 (maximum speed) if *pwm* was 

1266 :data:`True` when the class was constructed (and only 0 or 1 if 

1267 not). 

1268 """ 

1269 if not 0 <= speed <= 1: 

1270 raise ValueError('forward speed must be between 0 and 1') 

1271 if isinstance(self.forward_device, DigitalOutputDevice): 

1272 if speed not in (0, 1): 

1273 raise ValueError( 

1274 'forward speed must be 0 or 1 with non-PWM Motors') 

1275 self.backward_device.off() 

1276 self.forward_device.value = speed 

1277 

1278 def backward(self, speed=1): 

1279 """ 

1280 Drive the motor backwards. 

1281 

1282 :param float speed: 

1283 The speed at which the motor should turn. Can be any value between 

1284 0 (stopped) and the default 1 (maximum speed) if *pwm* was 

1285 :data:`True` when the class was constructed (and only 0 or 1 if 

1286 not). 

1287 """ 

1288 if not 0 <= speed <= 1: 

1289 raise ValueError('backward speed must be between 0 and 1') 

1290 if isinstance(self.backward_device, DigitalOutputDevice): 

1291 if speed not in (0, 1): 

1292 raise ValueError( 

1293 'backward speed must be 0 or 1 with non-PWM Motors') 

1294 self.forward_device.off() 

1295 self.backward_device.value = speed 

1296 

1297 def reverse(self): 

1298 """ 

1299 Reverse the current direction of the motor. If the motor is currently 

1300 idle this does nothing. Otherwise, the motor's direction will be 

1301 reversed at the current speed. 

1302 """ 

1303 self.value = -self.value 

1304 

1305 def stop(self): 

1306 """ 

1307 Stop the motor. 

1308 """ 

1309 self.forward_device.off() 

1310 self.backward_device.off() 

1311 

1312 

1313class PhaseEnableMotor(SourceMixin, CompositeDevice): 

1314 """ 

1315 Extends :class:`CompositeDevice` and represents a generic motor connected 

1316 to a Phase/Enable motor driver circuit; the phase of the driver controls 

1317 whether the motor turns forwards or backwards, while enable controls the 

1318 speed with PWM. 

1319 

1320 The following code will make the motor turn "forwards":: 

1321 

1322 from gpiozero import PhaseEnableMotor 

1323 motor = PhaseEnableMotor(12, 5) 

1324 motor.forward() 

1325 

1326 :type phase: int or str 

1327 :param phase: 

1328 The GPIO pin that the phase (direction) input of the motor driver chip 

1329 is connected to. See :ref:`pin-numbering` for valid pin numbers. If 

1330 this is :data:`None` a :exc:`GPIODeviceError` will be raised. 

1331 

1332 :type enable: int or str 

1333 :param enable: 

1334 The GPIO pin that the enable (speed) input of the motor driver chip 

1335 is connected to. See :ref:`pin-numbering` for valid pin numbers. If 

1336 this is :data:`None` a :exc:`GPIODeviceError` will be raised. 

1337 

1338 :param bool pwm: 

1339 If :data:`True` (the default), construct :class:`PWMOutputDevice` 

1340 instances for the motor controller pins, allowing both direction and 

1341 variable speed control. If :data:`False`, construct 

1342 :class:`DigitalOutputDevice` instances, allowing only direction 

1343 control. 

1344 

1345 :type pin_factory: Factory or None 

1346 :param pin_factory: 

1347 See :doc:`api_pins` for more information (this is an advanced feature 

1348 which most users can ignore). 

1349 """ 

1350 def __init__(self, phase=None, enable=None, pwm=True, pin_factory=None): 

1351 if not all([phase, enable]): 

1352 raise GPIOPinMissing('phase and enable pins must be provided') 

1353 PinClass = PWMOutputDevice if pwm else DigitalOutputDevice 

1354 super(PhaseEnableMotor, self).__init__( 

1355 phase_device=DigitalOutputDevice(phase, pin_factory=pin_factory), 

1356 enable_device=PinClass(enable, pin_factory=pin_factory), 

1357 _order=('phase_device', 'enable_device'), 

1358 pin_factory=pin_factory 

1359 ) 

1360 

1361 @property 

1362 def value(self): 

1363 """ 

1364 Represents the speed of the motor as a floating point value between -1 

1365 (full speed backward) and 1 (full speed forward). 

1366 """ 

1367 return ( 

1368 -self.enable_device.value 

1369 if self.phase_device.is_active else 

1370 self.enable_device.value 

1371 ) 

1372 

1373 @value.setter 

1374 def value(self, value): 

1375 if not -1 <= value <= 1: 

1376 raise OutputDeviceBadValue("Motor value must be between -1 and 1") 

1377 if value > 0: 

1378 self.forward(value) 

1379 elif value < 0: 

1380 self.backward(-value) 

1381 else: 

1382 self.stop() 

1383 

1384 @property 

1385 def is_active(self): 

1386 """ 

1387 Returns :data:`True` if the motor is currently running and 

1388 :data:`False` otherwise. 

1389 """ 

1390 return self.value != 0 

1391 

1392 def forward(self, speed=1): 

1393 """ 

1394 Drive the motor forwards. 

1395 

1396 :param float speed: 

1397 The speed at which the motor should turn. Can be any value between 

1398 0 (stopped) and the default 1 (maximum speed). 

1399 """ 

1400 if isinstance(self.enable_device, DigitalOutputDevice): 

1401 if speed not in (0, 1): 

1402 raise ValueError( 

1403 'forward speed must be 0 or 1 with non-PWM Motors') 

1404 self.enable_device.off() 

1405 self.phase_device.off() 

1406 self.enable_device.value = speed 

1407 

1408 def backward(self, speed=1): 

1409 """ 

1410 Drive the motor backwards. 

1411 

1412 :param float speed: 

1413 The speed at which the motor should turn. Can be any value between 

1414 0 (stopped) and the default 1 (maximum speed). 

1415 """ 

1416 if isinstance(self.enable_device, DigitalOutputDevice): 

1417 if speed not in (0, 1): 

1418 raise ValueError( 

1419 'backward speed must be 0 or 1 with non-PWM Motors') 

1420 self.enable_device.off() 

1421 self.phase_device.on() 

1422 self.enable_device.value = speed 

1423 

1424 def reverse(self): 

1425 """ 

1426 Reverse the current direction of the motor. If the motor is currently 

1427 idle this does nothing. Otherwise, the motor's direction will be 

1428 reversed at the current speed. 

1429 """ 

1430 self.value = -self.value 

1431 

1432 def stop(self): 

1433 """ 

1434 Stop the motor. 

1435 """ 

1436 self.enable_device.off() 

1437 

1438 

1439class Servo(SourceMixin, CompositeDevice): 

1440 """ 

1441 Extends :class:`CompositeDevice` and represents a PWM-controlled servo 

1442 motor connected to a GPIO pin. 

1443 

1444 Connect a power source (e.g. a battery pack or the 5V pin) to the power 

1445 cable of the servo (this is typically colored red); connect the ground 

1446 cable of the servo (typically colored black or brown) to the negative of 

1447 your battery pack, or a GND pin; connect the final cable (typically colored 

1448 white or orange) to the GPIO pin you wish to use for controlling the servo. 

1449 

1450 The following code will make the servo move between its minimum, maximum, 

1451 and mid-point positions with a pause between each:: 

1452 

1453 from gpiozero import Servo 

1454 from time import sleep 

1455 

1456 servo = Servo(17) 

1457 

1458 while True: 

1459 servo.min() 

1460 sleep(1) 

1461 servo.mid() 

1462 sleep(1) 

1463 servo.max() 

1464 sleep(1) 

1465 

1466 You can also use the :attr:`value` property to move the servo to a 

1467 particular position, on a scale from -1 (min) to 1 (max) where 0 is the 

1468 mid-point:: 

1469 

1470 from gpiozero import Servo 

1471 

1472 servo = Servo(17) 

1473 

1474 servo.value = 0.5 

1475 

1476 .. note:: 

1477 

1478 To reduce servo jitter, use the pigpio pin driver rather than the default 

1479 RPi.GPIO driver (pigpio uses DMA sampling for much more precise edge 

1480 timing). See :ref:`changing-pin-factory` for further information. 

1481 

1482 :type pin: int or str 

1483 :param pin: 

1484 The GPIO pin that the servo is connected to. See :ref:`pin-numbering` 

1485 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

1486 will be raised. 

1487 

1488 :param float initial_value: 

1489 If ``0`` (the default), the device's mid-point will be set initially. 

1490 Other values between -1 and +1 can be specified as an initial position. 

1491 :data:`None` means to start the servo un-controlled (see 

1492 :attr:`value`). 

1493 

1494 :param float min_pulse_width: 

1495 The pulse width corresponding to the servo's minimum position. This 

1496 defaults to 1ms. 

1497 

1498 :param float max_pulse_width: 

1499 The pulse width corresponding to the servo's maximum position. This 

1500 defaults to 2ms. 

1501 

1502 :param float frame_width: 

1503 The length of time between servo control pulses measured in seconds. 

1504 This defaults to 20ms which is a common value for servos. 

1505 

1506 :type pin_factory: Factory or None 

1507 :param pin_factory: 

1508 See :doc:`api_pins` for more information (this is an advanced feature 

1509 which most users can ignore). 

1510 """ 

1511 def __init__( 

1512 self, pin=None, initial_value=0.0, 

1513 min_pulse_width=1/1000, max_pulse_width=2/1000, 

1514 frame_width=20/1000, pin_factory=None): 

1515 if min_pulse_width >= max_pulse_width: 

1516 raise ValueError('min_pulse_width must be less than max_pulse_width') 

1517 if max_pulse_width >= frame_width: 

1518 raise ValueError('max_pulse_width must be less than frame_width') 

1519 self._frame_width = frame_width 

1520 self._min_dc = min_pulse_width / frame_width 

1521 self._dc_range = (max_pulse_width - min_pulse_width) / frame_width 

1522 self._min_value = -1 

1523 self._value_range = 2 

1524 super(Servo, self).__init__( 

1525 pwm_device=PWMOutputDevice( 

1526 pin, frequency=int(1 / frame_width), pin_factory=pin_factory 

1527 ), 

1528 pin_factory=pin_factory 

1529 ) 

1530 

1531 if PiGPIOFactory is None or not isinstance(self.pin_factory, PiGPIOFactory): 

1532 warnings.warn(PWMSoftwareFallback( 

1533 'To reduce servo jitter, use the pigpio pin factory.' 

1534 'See https://gpiozero.readthedocs.io/en/stable/api_output.html#servo for more info' 

1535 )) 

1536 

1537 try: 

1538 self.value = initial_value 

1539 except: 

1540 self.close() 

1541 raise 

1542 

1543 @property 

1544 def frame_width(self): 

1545 """ 

1546 The time between control pulses, measured in seconds. 

1547 """ 

1548 return self._frame_width 

1549 

1550 @property 

1551 def min_pulse_width(self): 

1552 """ 

1553 The control pulse width corresponding to the servo's minimum position, 

1554 measured in seconds. 

1555 """ 

1556 return self._min_dc * self.frame_width 

1557 

1558 @property 

1559 def max_pulse_width(self): 

1560 """ 

1561 The control pulse width corresponding to the servo's maximum position, 

1562 measured in seconds. 

1563 """ 

1564 return (self._dc_range * self.frame_width) + self.min_pulse_width 

1565 

1566 @property 

1567 def pulse_width(self): 

1568 """ 

1569 Returns the current pulse width controlling the servo. 

1570 """ 

1571 if self.pwm_device.pin.frequency is None: 

1572 return None 

1573 else: 

1574 return self.pwm_device.pin.state * self.frame_width 

1575 

1576 @pulse_width.setter 

1577 def pulse_width(self, value): 

1578 self.pwm_device.pin.state = value / self.frame_width 

1579 

1580 def min(self): 

1581 """ 

1582 Set the servo to its minimum position. 

1583 """ 

1584 self.value = -1 

1585 

1586 def mid(self): 

1587 """ 

1588 Set the servo to its mid-point position. 

1589 """ 

1590 self.value = 0 

1591 

1592 def max(self): 

1593 """ 

1594 Set the servo to its maximum position. 

1595 """ 

1596 self.value = 1 

1597 

1598 def detach(self): 

1599 """ 

1600 Temporarily disable control of the servo. This is equivalent to 

1601 setting :attr:`value` to :data:`None`. 

1602 """ 

1603 self.value = None 

1604 

1605 def _get_value(self): 

1606 if self.pwm_device.pin.frequency is None: 

1607 return None 

1608 else: 

1609 return ( 

1610 ((self.pwm_device.pin.state - self._min_dc) / self._dc_range) * 

1611 self._value_range + self._min_value) 

1612 

1613 @property 

1614 def value(self): 

1615 """ 

1616 Represents the position of the servo as a value between -1 (the minimum 

1617 position) and +1 (the maximum position). This can also be the special 

1618 value :data:`None` indicating that the servo is currently 

1619 "uncontrolled", i.e. that no control signal is being sent. Typically 

1620 this means the servo's position remains unchanged, but that it can be 

1621 moved by hand. 

1622 """ 

1623 result = self._get_value() 

1624 if result is None: 

1625 return result 

1626 else: 

1627 # NOTE: This round() only exists to ensure we don't confuse people 

1628 # by returning 2.220446049250313e-16 as the default initial value 

1629 # instead of 0. The reason _get_value and _set_value are split 

1630 # out is for descendents that require the un-rounded values for 

1631 # accuracy 

1632 return round(result, 14) 

1633 

1634 @value.setter 

1635 def value(self, value): 

1636 if value is None: 

1637 self.pwm_device.pin.frequency = None 

1638 elif -1 <= value <= 1: 

1639 self.pwm_device.pin.frequency = int(1 / self.frame_width) 

1640 self.pwm_device.pin.state = ( 

1641 self._min_dc + self._dc_range * 

1642 ((value - self._min_value) / self._value_range) 

1643 ) 

1644 else: 

1645 raise OutputDeviceBadValue( 

1646 "Servo value must be between -1 and 1, or None") 

1647 

1648 @property 

1649 def is_active(self): 

1650 return self.value is not None 

1651 

1652 

1653class AngularServo(Servo): 

1654 """ 

1655 Extends :class:`Servo` and represents a rotational PWM-controlled servo 

1656 motor which can be set to particular angles (assuming valid minimum and 

1657 maximum angles are provided to the constructor). 

1658 

1659 Connect a power source (e.g. a battery pack or the 5V pin) to the power 

1660 cable of the servo (this is typically colored red); connect the ground 

1661 cable of the servo (typically colored black or brown) to the negative of 

1662 your battery pack, or a GND pin; connect the final cable (typically colored 

1663 white or orange) to the GPIO pin you wish to use for controlling the servo. 

1664 

1665 Next, calibrate the angles that the servo can rotate to. In an interactive 

1666 Python session, construct a :class:`Servo` instance. The servo should move 

1667 to its mid-point by default. Set the servo to its minimum value, and 

1668 measure the angle from the mid-point. Set the servo to its maximum value, 

1669 and again measure the angle:: 

1670 

1671 >>> from gpiozero import Servo 

1672 >>> s = Servo(17) 

1673 >>> s.min() # measure the angle 

1674 >>> s.max() # measure the angle 

1675 

1676 You should now be able to construct an :class:`AngularServo` instance 

1677 with the correct bounds:: 

1678 

1679 >>> from gpiozero import AngularServo 

1680 >>> s = AngularServo(17, min_angle=-42, max_angle=44) 

1681 >>> s.angle = 0.0 

1682 >>> s.angle 

1683 0.0 

1684 >>> s.angle = 15 

1685 >>> s.angle 

1686 15.0 

1687 

1688 .. note:: 

1689 

1690 You can set *min_angle* greater than *max_angle* if you wish to reverse 

1691 the sense of the angles (e.g. ``min_angle=45, max_angle=-45``). This 

1692 can be useful with servos that rotate in the opposite direction to your 

1693 expectations of minimum and maximum. 

1694 

1695 :type pin: int or str 

1696 :param pin: 

1697 The GPIO pin that the servo is connected to. See :ref:`pin-numbering` 

1698 for valid pin numbers. If this is :data:`None` a :exc:`GPIODeviceError` 

1699 will be raised. 

1700 

1701 :param float initial_angle: 

1702 Sets the servo's initial angle to the specified value. The default is 

1703 0. The value specified must be between *min_angle* and *max_angle* 

1704 inclusive. :data:`None` means to start the servo un-controlled (see 

1705 :attr:`value`). 

1706 

1707 :param float min_angle: 

1708 Sets the minimum angle that the servo can rotate to. This defaults to 

1709 -90, but should be set to whatever you measure from your servo during 

1710 calibration. 

1711 

1712 :param float max_angle: 

1713 Sets the maximum angle that the servo can rotate to. This defaults to 

1714 90, but should be set to whatever you measure from your servo during 

1715 calibration. 

1716 

1717 :param float min_pulse_width: 

1718 The pulse width corresponding to the servo's minimum position. This 

1719 defaults to 1ms. 

1720 

1721 :param float max_pulse_width: 

1722 The pulse width corresponding to the servo's maximum position. This 

1723 defaults to 2ms. 

1724 

1725 :param float frame_width: 

1726 The length of time between servo control pulses measured in seconds. 

1727 This defaults to 20ms which is a common value for servos. 

1728 

1729 :type pin_factory: Factory or None 

1730 :param pin_factory: 

1731 See :doc:`api_pins` for more information (this is an advanced feature 

1732 which most users can ignore). 

1733 """ 

1734 def __init__( 

1735 self, pin=None, initial_angle=0.0, 

1736 min_angle=-90, max_angle=90, 

1737 min_pulse_width=1/1000, max_pulse_width=2/1000, 

1738 frame_width=20/1000, pin_factory=None): 

1739 self._min_angle = min_angle 

1740 self._angular_range = max_angle - min_angle 

1741 if initial_angle is None: 

1742 initial_value = None 

1743 elif ((min_angle <= initial_angle <= max_angle) or 

1744 (max_angle <= initial_angle <= min_angle)): 

1745 initial_value = 2 * ((initial_angle - min_angle) / self._angular_range) - 1 

1746 else: 

1747 raise OutputDeviceBadValue( 

1748 "AngularServo angle must be between %s and %s, or None" % 

1749 (min_angle, max_angle)) 

1750 super(AngularServo, self).__init__( 

1751 pin, initial_value, min_pulse_width, max_pulse_width, frame_width, 

1752 pin_factory=pin_factory 

1753 ) 

1754 

1755 @property 

1756 def min_angle(self): 

1757 """ 

1758 The minimum angle that the servo will rotate to when :meth:`min` is 

1759 called. 

1760 """ 

1761 return self._min_angle 

1762 

1763 @property 

1764 def max_angle(self): 

1765 """ 

1766 The maximum angle that the servo will rotate to when :meth:`max` is 

1767 called. 

1768 """ 

1769 return self._min_angle + self._angular_range 

1770 

1771 @property 

1772 def angle(self): 

1773 """ 

1774 The position of the servo as an angle measured in degrees. This will 

1775 only be accurate if :attr:`min_angle` and :attr:`max_angle` have been 

1776 set appropriately in the constructor. 

1777 

1778 This can also be the special value :data:`None` indicating that the 

1779 servo is currently "uncontrolled", i.e. that no control signal is being 

1780 sent. Typically this means the servo's position remains unchanged, but 

1781 that it can be moved by hand. 

1782 """ 

1783 result = self._get_value() 

1784 if result is None: 

1785 return None 

1786 else: 

1787 # NOTE: Why round(n, 12) here instead of 14? Angle ranges can be 

1788 # much larger than -1..1 so we need a little more rounding to 

1789 # smooth off the rough corners! 

1790 return round( 

1791 self._angular_range * 

1792 ((result - self._min_value) / self._value_range) + 

1793 self._min_angle, 12) 

1794 

1795 @angle.setter 

1796 def angle(self, angle): 

1797 if angle is None: 

1798 self.value = None 

1799 elif ((self.min_angle <= angle <= self.max_angle) or 

1800 (self.max_angle <= angle <= self.min_angle)): 

1801 self.value = ( 

1802 self._value_range * 

1803 ((angle - self._min_angle) / self._angular_range) + 

1804 self._min_value) 

1805 else: 

1806 raise OutputDeviceBadValue( 

1807 "AngularServo angle must be between %s and %s, or None" % 

1808 (self.min_angle, self.max_angle))