pimoroni-pico/micropython/modules_py/automation.py

418 lines
13 KiB
Python

import gc
from machine import Pin, PWM
from pimoroni_i2c import PimoroniI2C
from pimoroni import Analog
# IO Pin Constants
GP0 = 0
GP1 = 1
GP2 = 2
# Index Constants
RELAY_1 = 0
RELAY_2 = 1
RELAY_3 = 2
OUTPUT_1 = 0
OUTPUT_2 = 1
OUTPUT_3 = 2
ADC_1 = 0
ADC_2 = 1
ADC_3 = 2
INPUT_1 = 0
INPUT_2 = 1
INPUT_3 = 2
INPUT_4 = 3
SWITCH_A = 0
SWITCH_B = 1
class Automation2040W():
CONN_LED_PIN = 3
I2C_SDA_PIN = 4
I2C_SCL_PIN = 5
ADC_LED_PINS = (6, 7, 8)
RELAY_PINS = (9, 10, 11)
USER_SW_PINS = (12, 13)
USER_LED_PINS = (14, 15)
OUTPUT_PINS = (16, 17, 18)
IN_BUFFERED_PINS = (19, 20, 21, 22)
ADC_PINS = (26, 27, 28)
# Count Constants
NUM_GPIOS = 3
NUM_RELAYS = 3
NUM_OUTPUTS = 3
NUM_ADCS = 3
NUM_INPUTS = 4
NUM_SWITCHES = 2
VOLTAGE_GAIN = 0.06 # 56 / (56 + 820)
VOLTAGE_OFFSET = -0.06
MAX_ADC_LED_VOLTAGE = 45.0
def __init__(self):
# Free up hardware resources
gc.collect()
# Set up the i2c for Qw/st
self.i2c = PimoroniI2C(self.I2C_SDA_PIN, self.I2C_SCL_PIN, 100000)
# Set up the relay pins
self.__relays = []
for i in range(self.NUM_RELAYS):
self.__relays.append(Pin(self.RELAY_PINS[i], Pin.OUT))
self.release_relay(i)
# Set up outputs with pwm
self.__outputs = []
for i in range(self.NUM_OUTPUTS):
output = PWM(Pin(self.OUTPUT_PINS[i]))
output.freq(1000)
output.duty_u16(0)
self.__outputs.append(output)
# Set up the input pins
self.__inputs = []
for i in range(self.NUM_INPUTS):
self.__inputs.append(Pin(self.IN_BUFFERED_PINS[i], Pin.IN))
# Set up the adc pins and leds
self.__analogs = []
self.__adc_led_pwms = []
for i in range(self.NUM_ADCS):
self.__analogs.append(Analog(self.ADC_PINS[i], self.VOLTAGE_GAIN, offset=self.VOLTAGE_OFFSET))
led_pwm = PWM(Pin(self.ADC_LED_PINS[i]))
led_pwm.freq(1000)
led_pwm.duty_u16(0)
self.__adc_led_pwms.append(led_pwm)
# Set up the user switches
self.__switches = []
self.__switch_led_pwms = []
for i in range(self.NUM_SWITCHES):
self.__switches.append(Pin(self.USER_SW_PINS[i], Pin.IN, Pin.PULL_UP))
led_pwm = PWM(Pin(self.USER_LED_PINS[i]))
led_pwm.freq(1000)
led_pwm.duty_u16(0)
self.__switch_led_pwms.append(led_pwm)
# Set up the connectivity LED
self.__conn_led_pwm = PWM(Pin(self.CONN_LED_PIN))
self.__conn_led_pwm.freq(1000)
self.__conn_led_pwm.duty_u16(0)
def conn_led(self, brightness):
if brightness is True:
self.__conn_led_pwm.duty_u16(65535)
elif brightness is False:
self.__conn_led_pwm.duty_u16(0)
elif brightness < 0.0 or brightness > 100.0:
raise ValueError("brightness out of range. Expected 0 to 100, or True or False")
else:
gamma = 2.8
value = int(pow(float(brightness) / 100.0, gamma) * 65535 + 0.5)
self.__conn_led_pwm.duty_u16(value)
def switch_pressed(self, switch):
if switch < 0 or switch >= self.NUM_SWITCHES:
raise ValueError("switch out of range. Expected SWITCH_A (0) or SWITCH_B (1)")
return not self.__switches[switch].value()
def switch_led(self, switch, brightness):
if switch < 0 or switch >= self.NUM_SWITCHES:
raise ValueError("switch out of range. Expected SWITCH_A (0) or SWITCH_B (1)")
if brightness is True:
self.__switch_led_pwms[switch].duty_u16(65535)
elif brightness is False:
self.__switch_led_pwms[switch].duty_u16(0)
elif brightness < 0.0 or brightness > 100.0:
raise ValueError("brightness out of range. Expected 0 to 100, or True or False")
else:
gamma = 2.8
value = int(pow(brightness / 100.0, gamma) * 65535 + 0.5)
self.__switch_led_pwms[switch].duty_u16(value)
def relay(self, relay, actuate=None):
if relay < 0 or relay >= self.NUM_RELAYS:
raise ValueError("relay out of range. Expected RELAY_1 (0), RELAY_2 (1), or RELAY_3 (2)")
if actuate is None:
return self.__relays[relay].value()
self.__relays[relay].value(actuate)
def actuate_relay(self, relay):
if relay < 0 or relay >= self.NUM_RELAYS:
raise ValueError("relay out of range. Expected RELAY_1 (0), RELAY_2 (1), or RELAY_3 (2)")
self.__relays[relay].on()
def release_relay(self, relay):
if relay < 0 or relay >= self.NUM_RELAYS:
raise ValueError("relay out of range. Expected RELAY_1 (0), RELAY_2 (1), or RELAY_3 (2)")
self.__relays[relay].off()
def output(self, output, value=None):
if output < 0 or output >= self.NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0), OUTPUT_2 (1), or OUTPUT_3 (2)")
if value is None:
return self.__outputs[output].duty_u16() != 0
if value is True:
value = 100.0
if value is False:
value = 0
try:
if value >= 0.0 and value <= 100.0:
self.__outputs[output].duty_u16(int((value / 100.0) * 65535))
return
except TypeError:
pass
raise ValueError("value out of range. Expected 0 to 100, or True or False")
def output_percent(self, output):
if output < 0 or output >= self.NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0), OUTPUT_2 (1), or OUTPUT_3 (2)")
return round((self.__outputs[output].duty_u16() / 65535) * 100.0, 1)
def change_output_freq(self, output, freq):
if output < 0 or output >= self.NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0), OUTPUT_2 (1), or OUTPUT_3 (2)")
if freq < 10 or freq > 1000.0:
raise ValueError("freq out of range. Expected 10Hz to 1000Hz")
self.__outputs[output].freq(freq)
def read_input(self, input):
if input < 0 or input >= self.NUM_INPUTS:
raise ValueError("input out of range. Expected INPUT_1 (0), INPUT_2 (1), INPUT_3 (2), or INPUT_4 (3)")
return self.__inputs[input].value()
def read_adc(self, adc):
if adc < 0 or adc >= self.NUM_ADCS:
raise ValueError("adc out of range. Expected ADC_1 (0), ADC_2 (1), or ADC_3 (2)")
voltage = self.__analogs[adc].read_voltage()
gamma = 2.8
value = int(pow(voltage / self.MAX_ADC_LED_VOLTAGE, gamma) * 65535 + 0.5)
self.__adc_led_pwms[adc].duty_u16(value)
return voltage
def reset(self):
# Reset the relays
for i in range(self.NUM_RELAYS):
self.release_relay(i)
# Reset the outputs
for i in range(self.NUM_OUTPUTS):
self.output(i, False)
# Reset the adc LEDs
for i in range(self.NUM_ADCS):
self.__adc_led_pwms[i].duty_u16(0)
# Reset the switch LEDs
for i in range(self.NUM_SWITCHES):
self.__switch_led_pwms[i].duty_u16(0)
# Reset the connectivity LED
self.__conn_led_pwm.duty_u16(0)
class Automation2040WMini():
CONN_LED_PIN = 3
I2C_SDA_PIN = 4
I2C_SCL_PIN = 5
ADC_LED_PINS = (6, 7, 8)
RELAY_PIN = 9
USER_SW_PINS = (12, 13)
USER_LED_PINS = (14, 15)
OUTPUT_PINS = (16, 17)
IN_BUFFERED_PINS = (19, 20)
ADC_PINS = (26, 27, 28)
# Count Constants
NUM_GPIOS = 3
NUM_RELAYS = 1
NUM_OUTPUTS = 2
NUM_ADCS = 3
NUM_INPUTS = 2
NUM_SWITCHES = 2
VOLTAGE_GAIN = 0.06 # 56 / (56 + 820)
VOLTAGE_OFFSET = -0.06
MAX_ADC_LED_VOLTAGE = 45.0
def __init__(self):
# Free up hardware resources
gc.collect()
# Set up the i2c for Qw/st
self.i2c = PimoroniI2C(self.I2C_SDA_PIN, self.I2C_SCL_PIN, 100000)
# Set up the relay pins
self.__relay = Pin(self.RELAY_PIN, Pin.OUT)
# Set up outputs with pwm
self.__outputs = []
for i in range(self.NUM_OUTPUTS):
output = PWM(Pin(self.OUTPUT_PINS[i]))
output.freq(1000)
output.duty_u16(0)
self.__outputs.append(output)
# Set up the input pins
self.__inputs = []
for i in range(self.NUM_INPUTS):
self.__inputs.append(Pin(self.IN_BUFFERED_PINS[i], Pin.IN))
# Set up the adc pins and leds
self.__analogs = []
self.__adc_led_pwms = []
for i in range(self.NUM_ADCS):
self.__analogs.append(Analog(self.ADC_PINS[i], self.VOLTAGE_GAIN, offset=self.VOLTAGE_OFFSET))
led_pwm = PWM(Pin(self.ADC_LED_PINS[i]))
led_pwm.freq(1000)
led_pwm.duty_u16(0)
self.__adc_led_pwms.append(led_pwm)
# Set up the user switches
self.__switches = []
self.__switch_led_pwms = []
for i in range(self.NUM_SWITCHES):
self.__switches.append(Pin(self.USER_SW_PINS[i], Pin.IN, Pin.PULL_UP))
led_pwm = PWM(Pin(self.USER_LED_PINS[i]))
led_pwm.freq(1000)
led_pwm.duty_u16(0)
self.__switch_led_pwms.append(led_pwm)
# Set up the connectivity LED
self.__conn_led_pwm = PWM(Pin(self.CONN_LED_PIN))
self.__conn_led_pwm.freq(1000)
self.__conn_led_pwm.duty_u16(0)
def conn_led(self, brightness):
if brightness is True:
self.__conn_led_pwm.duty_u16(65535)
elif brightness is False:
self.__conn_led_pwm.duty_u16(0)
elif brightness < 0.0 or brightness > 100.0:
raise ValueError("brightness out of range. Expected 0 to 100, or True or False")
else:
gamma = 2.8
value = int(pow(brightness / 100.0, gamma) * 65535 + 0.5)
self.__conn_led_pwm.duty_u16(value)
def switch_pressed(self, switch):
if switch < 0 or switch >= self.NUM_SWITCHES:
raise ValueError("switch out of range. Expected SWITCH_A (0) or SWITCH_B (1)")
return not self.__switches[switch].value()
def switch_led(self, switch, brightness):
if switch < 0 or switch >= self.NUM_SWITCHES:
raise ValueError("switch out of range. Expected SWITCH_A (0) or SWITCH_B (1)")
if brightness is True:
self.__switch_led_pwms[switch].duty_u16(65535)
elif brightness is False:
self.__switch_led_pwms[switch].duty_u16(0)
elif brightness < 0.0 or brightness > 100.0:
raise ValueError("brightness out of range. Expected 0 to 100, or True or False")
else:
gamma = 2.8
value = int(pow(brightness / 100.0, gamma) * 65535 + 0.5)
self.__switch_led_pwms[switch].duty_u16(value)
def relay(self, actuate=None):
if actuate is None:
return self.__relay.value()
self.__relay.value(actuate)
def actuate_relay(self):
self.__relay.on()
def release_relay(self):
self.__relay.off()
def output(self, output, value=None):
if output < 0 or output >= self.NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0) or OUTPUT_2 (1)")
if value is None:
return self.__outputs[output].duty_u16() != 0
if value is True:
value = 100.0
if value is False:
value = 0
try:
if value >= 0.0 and value <= 100.0:
self.__outputs[output].duty_u16(int((value / 100.0) * 65535))
return
except TypeError:
pass
raise ValueError("value out of range. Expected 0 to 100, or True or False")
def output_percent(self, output):
if output < 0 or output >= self.NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0) or OUTPUT_2 (1)")
return round((self.__outputs[output].duty_u16() / 65535) * 100.0, 1)
def change_output_freq(self, output, freq):
if output < 0 or output >= self.NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0) or OUTPUT_2 (1)")
if freq < 10 or freq > 1000.0:
raise ValueError("freq out of range. Expected 10Hz to 1000Hz")
self.__outputs[output].freq(freq)
def read_input(self, input):
if input < 0 or input >= self.NUM_INPUTS:
raise ValueError("input out of range. Expected INPUT_1 (0) or INPUT_2 (1)")
return self.__inputs[input].value()
def read_adc(self, adc):
if adc < 0 or adc >= self.NUM_ADCS:
raise ValueError("adc out of range. Expected ADC_1 (0), ADC_2 (1), or ADC_3 (2)")
voltage = self.__analogs[adc].read_voltage()
gamma = 2.8
value = int(pow(voltage / self.MAX_ADC_LED_VOLTAGE, gamma) * 65535 + 0.5)
self.__adc_led_pwms[adc].duty_u16(value)
return voltage
def reset(self):
# Reset the relay
self.release_relay()
# Reset the outputs
for i in range(self.NUM_OUTPUTS):
self.output(i, False)
# Reset the adc LEDs
for i in range(self.NUM_ADCS):
self.__adc_led_pwms[i].duty_u16(0)
# Reset the switch LEDs
for i in range(self.NUM_SWITCHES):
self.__switch_led_pwms[i].duty_u16(0)
# Reset the connectivity LED
self.__conn_led_pwm.duty_u16(0)