Files
grow-python/library/grow/pump.py
Phil Howard 85db231475 Make pumps mutually exclusive
Forces only one pump to be active at a time, to avoid the sudden inrush current browning out the Pi or causing weirdness when multiple pumps fire and drop the voltage.
2021-03-08 18:12:03 +00:00

93 lines
2.4 KiB
Python

import time
import atexit
import threading
import RPi.GPIO as GPIO
PUMP_1_PIN = 17
PUMP_2_PIN = 27
PUMP_3_PIN = 22
PUMP_PWM_FREQ = 10000
PUMP_MAX_DUTY = 90
global_lock = threading.Lock()
class Pump(object):
"""Grow pump driver."""
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.
"""
self._gpio_pin = [PUMP_1_PIN, PUMP_2_PIN, PUMP_3_PIN][channel - 1]
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(self._gpio_pin, GPIO.OUT, initial=GPIO.LOW)
self._pwm = GPIO.PWM(self._gpio_pin, PUMP_PWM_FREQ)
self._pwm.start(0)
self._timeout = None
atexit.register(self._stop)
def _stop(self):
self._pwm.stop(0)
GPIO.setup(self._gpio_pin, GPIO.IN)
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 not global_lock.acquire(blocking=False):
return False
self._pwm.ChangeDutyCycle(int(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."""
self.set_speed(0)
if self._timeout is not None:
self._timeout.cancel()
self._timeout = None
global_lock.release()
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