mirror of
https://github.com/pimoroni/grow-python
synced 2025-10-25 15:19:23 +00:00
103 lines
2.6 KiB
Python
103 lines
2.6 KiB
Python
import atexit
|
|
import threading
|
|
import time
|
|
|
|
import gpiodevice
|
|
|
|
from . import pwm
|
|
|
|
PUMP_1_PIN = "PIN11" # 17
|
|
PUMP_2_PIN = "PIN13" # 27
|
|
PUMP_3_PIN = "PIN15" # 22
|
|
PUMP_PWM_FREQ = 10000
|
|
PUMP_MAX_DUTY = 0.9
|
|
|
|
PLATFORMS = {
|
|
"Raspberry Pi 5": {"pump1": ("PIN11", pwm.OUTL), "pump2": ("PIN12", pwm.OUTL), "pump3": ("PIN15", pwm.OUTL)},
|
|
"Raspberry Pi 4": {"pump1": ("GPIO17", pwm.OUTL), "pump2": ("GPIO27", pwm.OUTL), "pump3": ("GPIO22", pwm.OUTL)},
|
|
}
|
|
|
|
|
|
global_lock = threading.Lock()
|
|
|
|
|
|
class Pump(object):
|
|
"""Grow pump driver."""
|
|
|
|
PINS = None
|
|
|
|
def __init__(self, channel=1):
|
|
"""Create a new pump.
|
|
|
|
Uses soft PWM to drive a Grow pump.
|
|
|
|
:param channel: One of 1, 2 or 3.
|
|
|
|
"""
|
|
|
|
if Pump.PINS is None:
|
|
Pump.PINS = gpiodevice.get_pins_for_platform(PLATFORMS)
|
|
|
|
self._gpio_pin = Pump.PINS[channel - 1]
|
|
|
|
self._pwm = pwm.PWM(self._gpio_pin, PUMP_PWM_FREQ)
|
|
self._pwm.start(0)
|
|
|
|
pwm.PWM.start_thread()
|
|
atexit.register(pwm.PWM.stop_thread)
|
|
|
|
self._timeout = None
|
|
|
|
def set_speed(self, speed):
|
|
"""Set pump speed (PWM duty cycle)."""
|
|
if speed > 1.0 or speed < 0:
|
|
raise ValueError("Speed must be between 0 and 1")
|
|
|
|
if speed == 0:
|
|
global_lock.release()
|
|
elif not global_lock.acquire(blocking=False):
|
|
return False
|
|
|
|
self._pwm.set_duty_cycle(PUMP_MAX_DUTY * speed)
|
|
self._speed = speed
|
|
return True
|
|
|
|
def get_speed(self):
|
|
"""Return Pump speed (PWM duty cycle)."""
|
|
return self._speed
|
|
|
|
def stop(self):
|
|
"""Stop the pump."""
|
|
if self._timeout is not None:
|
|
self._timeout.cancel()
|
|
self._timeout = None
|
|
self.set_speed(0)
|
|
|
|
def dose(self, speed, timeout=0.1, blocking=True, force=False):
|
|
"""Pulse the pump for timeout seconds.
|
|
|
|
:param timeout: Timeout, in seconds, of the pump pulse
|
|
:param blocking: If true, function will block until pump has stopped
|
|
:param force: Applies only to non-blocking. If true, any previous dose will be replaced
|
|
|
|
"""
|
|
|
|
if blocking:
|
|
if self.set_speed(speed):
|
|
time.sleep(timeout)
|
|
self.stop()
|
|
return True
|
|
|
|
else:
|
|
if self._timeout is not None:
|
|
if self._timeout.is_alive():
|
|
if force:
|
|
self._timeout.cancel()
|
|
|
|
self._timeout = threading.Timer(timeout, self.stop)
|
|
if self.set_speed(speed):
|
|
self._timeout.start()
|
|
return True
|
|
|
|
return False
|