aboutsummaryrefslogtreecommitdiff
path: root/main.py
diff options
context:
space:
mode:
Diffstat (limited to 'main.py')
-rw-r--r--main.py171
1 files changed, 171 insertions, 0 deletions
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..aa80fce
--- /dev/null
+++ b/main.py
@@ -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)