mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	| @@ -32,8 +32,14 @@ class OutputDevice(SourceMixin, GPIODevice): | ||||
|         If ``True`` (the default), the :meth:`on` method will set the GPIO to | ||||
|         HIGH. If ``False``, the :meth:`on` method will set the GPIO to LOW (the | ||||
|         :meth:`off` method always does the opposite). | ||||
|  | ||||
|     :param bool initial_value: | ||||
|         If ``False`` (the default), the device will be off initially.  If | ||||
|         ``None``, the device will be left in whatever state the pin is found in | ||||
|         when configured for output (warning: this can be on).  If ``True``, the | ||||
|         device will be switched on initially. | ||||
|     """ | ||||
|     def __init__(self, pin=None, active_high=True): | ||||
|     def __init__(self, pin=None, active_high=True, initial_value=False): | ||||
|         self._active_high = active_high | ||||
|         super(OutputDevice, self).__init__(pin) | ||||
|         self._active_state = GPIO.HIGH if active_high else GPIO.LOW | ||||
| @@ -42,6 +48,12 @@ class OutputDevice(SourceMixin, GPIODevice): | ||||
|             # NOTE: catch_warnings isn't thread-safe but hopefully no-one's | ||||
|             # messing around with GPIO init within background threads... | ||||
|             with warnings.catch_warnings(record=True) as w: | ||||
|                 # This is horrid, but we can't specify initial=None with setup | ||||
|                 if initial_value is None: | ||||
|                     GPIO.setup(pin, GPIO.OUT) | ||||
|                 else: | ||||
|                     GPIO.setup(pin, GPIO.OUT, initial= | ||||
|                         [self._inactive_state, self._active_state][bool(initial_value)]) | ||||
|                 GPIO.setup(pin, GPIO.OUT) | ||||
|             # The only warning we want to squash is a RuntimeWarning that is | ||||
|             # thrown when setting pins 2 or 3. Anything else should be replayed | ||||
| @@ -56,6 +68,8 @@ class OutputDevice(SourceMixin, GPIODevice): | ||||
|             raise | ||||
|  | ||||
|     def _write(self, value): | ||||
|         if not self.active_high: | ||||
|             value = not value | ||||
|         try: | ||||
|             GPIO.output(self.pin, bool(value)) | ||||
|         except ValueError: | ||||
| @@ -66,13 +80,13 @@ class OutputDevice(SourceMixin, GPIODevice): | ||||
|         """ | ||||
|         Turns the device on. | ||||
|         """ | ||||
|         self._write(self._active_state) | ||||
|         self._write(True) | ||||
|  | ||||
|     def off(self): | ||||
|         """ | ||||
|         Turns the device off. | ||||
|         """ | ||||
|         self._write(self._inactive_state) | ||||
|         self._write(False) | ||||
|  | ||||
|     @property | ||||
|     def value(self): | ||||
| @@ -103,9 +117,9 @@ class DigitalOutputDevice(OutputDevice): | ||||
|     which uses an optional background thread to handle toggling the device | ||||
|     state without further interaction. | ||||
|     """ | ||||
|     def __init__(self, pin=None, active_high=True): | ||||
|     def __init__(self, pin=None, active_high=True, initial_value=False): | ||||
|         self._blink_thread = None | ||||
|         super(DigitalOutputDevice, self).__init__(pin, active_high) | ||||
|         super(DigitalOutputDevice, self).__init__(pin, active_high, initial_value) | ||||
|         self._lock = Lock() | ||||
|  | ||||
|     def close(self): | ||||
| @@ -114,11 +128,11 @@ class DigitalOutputDevice(OutputDevice): | ||||
|  | ||||
|     def on(self): | ||||
|         self._stop_blink() | ||||
|         self._write(self._active_state) | ||||
|         self._write(True) | ||||
|  | ||||
|     def off(self): | ||||
|         self._stop_blink() | ||||
|         self._write(self._inactive_state) | ||||
|         self._write(False) | ||||
|  | ||||
|     def toggle(self): | ||||
|         """ | ||||
| @@ -167,10 +181,10 @@ class DigitalOutputDevice(OutputDevice): | ||||
|     def _blink_led(self, on_time, off_time, n): | ||||
|         iterable = repeat(0) if n is None else repeat(0, n) | ||||
|         for i in iterable: | ||||
|             self._write(self._active_state) | ||||
|             self._write(True) | ||||
|             if self._blink_thread.stopping.wait(on_time): | ||||
|                 break | ||||
|             self._write(self._inactive_state) | ||||
|             self._write(False) | ||||
|             if self._blink_thread.stopping.wait(off_time): | ||||
|                 break | ||||
|  | ||||
| @@ -241,19 +255,34 @@ class PWMOutputDevice(OutputDevice): | ||||
|         The GPIO pin which the device is attached to. See :doc:`notes` for | ||||
|         valid pin numbers. | ||||
|  | ||||
|     :param bool active_high: | ||||
|         If ``True`` (the default), the :meth:`on` method will set the GPIO to | ||||
|         HIGH. If ``False``, the :meth:`on` method will set the GPIO to LOW (the | ||||
|         :meth:`off` method always does the opposite). | ||||
|  | ||||
|     :param bool initial_value: | ||||
|         If ``0`` (the default), the device's duty cycle will be 0 initially. | ||||
|         Other values between 0 and 1 can be specified as an initial duty cycle. | ||||
|         Note that ``None`` cannot be specified (unlike the parent class) as | ||||
|         there is no way to tell PWM not to alter the state of the pin. | ||||
|  | ||||
|     :param int frequency: | ||||
|         The frequency (in Hz) of pulses emitted to drive the device. Defaults | ||||
|         to 100Hz. | ||||
|     """ | ||||
|     def __init__(self, pin=None, active_high=True, frequency=100): | ||||
|     def __init__(self, pin=None, active_high=True, initial_value=0, frequency=100): | ||||
|         self._pwm = None | ||||
|         self._blink_thread = None | ||||
|         if not 0 <= initial_value <= 1: | ||||
|             raise OutputDeviceError("initial_value must be between 0 and 1") | ||||
|         super(PWMOutputDevice, self).__init__(pin, active_high) | ||||
|         try: | ||||
|             self._pwm = GPIO.PWM(self.pin, frequency) | ||||
|             self._pwm.start(0.0) | ||||
|             self._value = initial_value | ||||
|             if not active_high: | ||||
|                 initial_value = 1 - initial_value | ||||
|             self._pwm.start(100 * initial_value) | ||||
|             self._frequency = frequency | ||||
|             self._value = 0.0 | ||||
|         except: | ||||
|             self.close() | ||||
|             raise | ||||
| @@ -271,9 +300,14 @@ class PWMOutputDevice(OutputDevice): | ||||
|  | ||||
|     def _read(self): | ||||
|         self._check_open() | ||||
|         return self._value | ||||
|         if self.active_high: | ||||
|             return self._value | ||||
|         else: | ||||
|             return 1 - self._value | ||||
|  | ||||
|     def _write(self, value): | ||||
|         if not self.active_high: | ||||
|             value = 1 - value | ||||
|         if not 0 <= value <= 1: | ||||
|             raise OutputDeviceError("PWM value must be between 0 and 1") | ||||
|         try: | ||||
| @@ -289,26 +323,20 @@ class PWMOutputDevice(OutputDevice): | ||||
|         The duty cycle of the PWM device. 0.0 is off, 1.0 is fully on. Values | ||||
|         in between may be specified for varying levels of power in the device. | ||||
|         """ | ||||
|         if self.active_high: | ||||
|             return self._read() | ||||
|         else: | ||||
|             return 1 - self._read() | ||||
|         return self._read() | ||||
|  | ||||
|     @value.setter | ||||
|     def value(self, value): | ||||
|         self._stop_blink() | ||||
|         if self._active_high: | ||||
|             self._write(value) | ||||
|         else: | ||||
|             self._write(1 - value) | ||||
|         self._write(value) | ||||
|  | ||||
|     def on(self): | ||||
|         self._stop_blink() | ||||
|         self._write(self._active_state) | ||||
|         self._write(1) | ||||
|  | ||||
|     def off(self): | ||||
|         self._stop_blink() | ||||
|         self._write(self._inactive_state) | ||||
|         self._write(0) | ||||
|  | ||||
|     def toggle(self): | ||||
|         """ | ||||
| @@ -386,20 +414,18 @@ class PWMOutputDevice(OutputDevice): | ||||
|     def _blink_led( | ||||
|             self, on_time, off_time, fade_in_time, fade_out_time, n, fps=50): | ||||
|         sequence = [] | ||||
|         if fade_in_time > 0.0: | ||||
|         if fade_in_time > 0: | ||||
|             sequence += [ | ||||
|                 (i * (1 / fps) / fade_in_time, 1 / fps) | ||||
|                 for i in range(int(fps * fade_in_time)) | ||||
|                 ] | ||||
|         sequence.append((1.0, on_time)) | ||||
|         if fade_out_time > 0.0: | ||||
|         sequence.append((1, on_time)) | ||||
|         if fade_out_time > 0: | ||||
|             sequence += [ | ||||
|                 (1 - (i * (1 / fps) / fade_out_time), 1 / fps) | ||||
|                 for i in range(int(fps * fade_out_time)) | ||||
|                 ] | ||||
|         sequence.append((0.0, off_time)) | ||||
|         if not self.active_high: | ||||
|             sequence = [(1 - value, delay) for (value, delay) in sequence] | ||||
|         sequence.append((0, off_time)) | ||||
|         sequence = ( | ||||
|                 cycle(sequence) if n is None else | ||||
|                 chain.from_iterable(repeat(sequence, n)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user