diff options
author | erg <uinarf@autistici.org> | 2023-01-12 16:15:35 +0100 |
---|---|---|
committer | erg <uinarf@autistici.org> | 2023-01-12 16:15:35 +0100 |
commit | d6970e81e607f27bee9323d10d1476621de3416c (patch) | |
tree | 1c27d765440256468eb24ecafef78a17cbdf72db /main.py | |
download | Pi_Temp_PID_Control-d6970e81e607f27bee9323d10d1476621de3416c.tar.gz Pi_Temp_PID_Control-d6970e81e607f27bee9323d10d1476621de3416c.tar.bz2 Pi_Temp_PID_Control-d6970e81e607f27bee9323d10d1476621de3416c.zip |
Initial commit
Diffstat (limited to 'main.py')
-rw-r--r-- | main.py | 171 |
1 files changed, 171 insertions, 0 deletions
@@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Module managing temperature in the shroombox. +""" + +from os import getpid +import pigpio +from math import isnan +import logging +import time +from simple_pid import PID + +__author__ = "Franek Ćazarewicz-Muradyan" +__licence__ = "GPL" +__version__ = "0.0.1" +__status__ = "Proof of concept" + +# ********************** +# Hardware Settings +# ********************** + +# One wire temperature sensor settings +w1_sensor_id = '28-0517c1b121ff' +w1_sensor_f = f'/sys/devices/w1_bus_master1/{w1_sensor_id}/w1_slave' +# Heater settings +relay_pin = 5 +mosfet_pin = 22 + +# ********************** +# Software Settings +# ********************** + +timeformat = '%Y-%M-%d %H:%M:%S' +temperature_min = 20 +temperature_max = 24 +temperature_target = 20 +read_retry = 3 +logname = '/var/log/pipi/shroombox.log' +data_file = '/var/log/pipi/shroombox.csv' + +# ********************** +# PID Settings +# ********************** +Kp = 1 +Ki = 0.2 +Kd = 0 +sample_time = 10 + +# ********************** +# Code +# ********************** + + +logging.basicConfig( + filename=logname, + encoding='utf-8', + filemode='a', + format='%(asctime)s,%(msecs)d %(name)s%(levelname)s %(message)s', datefmt='%H:%M:%S', + level=logging.DEBUG, +) +logging.info("Starting shroombox") +logger = logging.getLogger() + + +def read_temp( + retry: int = 0, +) -> float: + # If sensor is physically disconected, opening file will fail + temperature = float('NaN') + if retry > read_retry: + return temperature + with open(w1_sensor_f, 'r') as sensor: + ok = sensor.readline()[-4:].strip('\n') + if ok == 'YES': + try: + temperature = round(int(sensor.readline().split('=')[1])/1000, 1) + except IndexError: # TODO: What other exceptions? + return temperature + else: + retry += 1 + read_temp(retry=retry) + return temperature + + +def heater_on( + temp: float, + on: bool = False, +) -> bool: + status = pio.read(relay_pin) + timestamp = time.strftime(timeformat) + # turning it off + if not on: + if status == 1: + return False + else: + try: + pio.write(relay_pin, 1) + message = f"Turning off, temp: {temp}, {timestamp}" + logger.info(message) + return False + except: # TODO: documentation doesn't talk about exceptions on write + return True + # turning it on + if on: + if status == 0: + return False + else: + try: + pio.write(relay_pin, 0) + message = f"Turning on, temp: {temp}, {timestamp}" + logger.info(message) + return False + except: + return True + + +def temp_control( + current_temperature: float +) -> int: + pid = PID(Kp, Ki, Kd, setpoint=temperature_target) + pid.output_limits = (0, 255) + pid.sample_time = sample_time + return pid(current_temperature) + + +def main_alt(): + temp = read_temp_alt() + timestamp = time.strftime(timeformat) + print(temp) + with open(data_file, 'a') as dat: + dat.write(temp) + frequency = temp_control(temp) + try: + pio.set_PWM_frequency(mosfet_pin, frequency) + except ( + pio.PI_BAD_USER_GPIO, + pio.PI_NOT_PERMITTED, + ) as exc: + logger.warning(f"Failed to set GPIO PWM frequency: {exc} {timestamp}") + + +def main(): + temp = read_temp() + timestamp = time.strftime(timeformat) + print(temp) + if temp <= temperature_min: + # if temp < temperature_min - 5: + # print(f"Heater doesn't work, battery empty?") + # logger.warning(f"Heater doesn't work, battery empty?") + # state = heater_on(temp, on=False) + state = heater_on(temp, on=True) + if state != 0: + logger.warning(f"heater_on() method returned {state}, {timestamp}") + elif temp >= temperature_max: + state = heater_on(temp, on=False) + if state != 0: + logger.warning(f"heater_on() method returned {state} {timestamp}") + elif isnan(temp): + state = heater_on(temp, on=False) + logging.warning(f"Cannot read temperature, check your connections! {timestamp}") + + +if __name__ == '__main__': + with open('/run/shroombox.pid', 'w') as f: + f.write(str(getpid())) + while True: + pio = pigpio.pi() + main() + time.sleep(30) |