Merge branch 'displays' into emergency-shutoff

This commit is contained in:
Tanaes 2022-07-23 10:48:10 -04:00
commit d994c8e31c
6 changed files with 131 additions and 10 deletions

View File

@ -1,7 +1,7 @@
import logging
# uncomment this if using MAX-31856
#from lib.max31856 import MAX31856
from lib.max31856 import MAX31856
########################################################################
#
@ -10,6 +10,7 @@ import logging
### Logging
log_level = logging.INFO
log_format = '%(asctime)s %(levelname)s %(name)s: %(message)s'
log_file = '/var/log/kiln-controller.log'
### Server
listening_ip = "0.0.0.0"
@ -43,11 +44,14 @@ gpio_fan = 22 # pin 15
# energized the safety relay.
## Display outputs
gpio_disp1_clk = 20 # pin 38
gpio_disp1_dat = 21 # pin 40
gpio_disp2_clk = 16 # pin 36
gpio_disp2_dat = 26 # pin 37
temp_disp = {'type': 'TMC1637',
'pins': {'clock': 16,
'data': 26}} # pin 36, pin 37
time_disp = {'type': 'TMC1637',
'pins': {'clock': 20,
'data': 21}} # pin 38, pin 40
gpio_dotstar_clk = 19 # pin 35
gpio_dotstar_dat = 13 # pin 33

View File

@ -23,7 +23,9 @@ except:
print ("Copy config.py.EXAMPLE to config.py and adapt it for your setup.")
exit(1)
logging.basicConfig(level=config.log_level, format=config.log_format)
logging.basicConfig(level=config.log_level,
format=config.log_format,
filename=config.log_file)
log = logging.getLogger("kiln-controller")
log.info("Starting kiln controller")

35
lib/display.py Normal file
View File

@ -0,0 +1,35 @@
import tm1637
import logging
log = logging.getLogger(__name__)
class TM1637(object):
def __init__(self,
clk_pin,
dat_pin):
self.clk_pin = clk_pin
self.dat_pin = dat_pin
try:
self.tm = tm1637.TM1637(clk=clk_pin,
dio=dat_pin)
except ImportError as e:
log.warning('import failure: \n%s' % e)
def temp(self,
t):
self.tm.number(t)
def time(self,
h,
m):
self.tm.numbers(h, m, True)
def text(self,
text):
self.tm.show(text[0:4])
def off(self):
self.tm.write([0, 0, 0, 0])

View File

@ -1,10 +1,12 @@
import threading
import time
from math import floor, ceil
import random
import datetime
import logging
import json
import config
from display import TM1637
log = logging.getLogger(__name__)
@ -13,6 +15,26 @@ class Output(object):
def __init__(self):
self.active = False
self.load_libs()
log.warning('Active: %s' % self.active)
if self.active:
log.info("Trying to initialize displays")
try:
self.time_disp = Display(config.time_disp['type'],
config.time_disp['pins'])
self.time_disp.time(11,11)
except NameError as e:
log.warning("Couldn't initialize time display")
log.warning("Error: %s" % e)
self.time_disp = False
try:
self.temp_disp = Display(config.temp_disp['type'],
config.temp_disp['pins'])
self.temp_disp.text('----')
except NameError as e:
log.warning("Couldn't initialize temp display")
log.warning("Error: %s" % e)
self.temp_disp = False
def load_libs(self):
try:
@ -30,11 +52,19 @@ class Output(object):
def safety_off(self):
'''Energizes the safety relay'''
self.GPIO.output(config.gpio_e_relay, self.GPIO.HIGH)
if self.active:
log.info("energizing safety relay")
self.GPIO.output(config.gpio_e_relay, self.GPIO.HIGH)
else:
log.info("simulating energizing safety relay")
def safety_on(self):
'''Deenergizes the safety relay'''
self.GPIO.output(config.gpio_e_relay, self.GPIO.LOW)
if self.active:
log.info("deenergizing safety relay")
self.GPIO.output(config.gpio_e_relay, self.GPIO.LOW)
else:
log.info("simulating deenergizing safety relay")
def heat(self,sleepfor):
self.GPIO.output(config.gpio_heat, self.GPIO.HIGH)
@ -45,6 +75,29 @@ class Output(object):
self.GPIO.output(config.gpio_heat, self.GPIO.LOW)
time.sleep(sleepfor)
class Display(object):
def __init__(self,
type,
pins):
if type == "TMC1637":
self.disp = TM1637(pins['clock'],
pins['data'])
def temp(self, t):
self.disp.temp(t)
def time(self, h, m):
self.disp.time(h, m)
def off(self):
self.disp.off()
def text(self, text):
self.disp.text(text)
# FIX - Board class needs to be completely removed
class Board(object):
def __init__(self):
@ -178,10 +231,20 @@ class Oven(threading.Thread):
self.daemon = True
self.temperature = 0
self.time_step = config.sensor_time_wait
self.output = Output()
if self.output.time_disp:
self.output.time_disp.text(self.state)
if self.output.temp_disp:
self.output.temp_disp.temp(self.temperature)
self.reset()
def reset(self):
self.output.safety_on()
self.state = "IDLE"
if self.output.time_disp:
self.output.time_disp.text(self.state)
self.profile = None
self.start_time = 0
self.runtime = 0
@ -192,6 +255,7 @@ class Oven(threading.Thread):
def run_profile(self, profile, startat=0):
self.reset()
self.output.safety_off()
if self.board.temp_sensor.noConnection:
log.info("Refusing to start profile - thermocouple not connected")
@ -272,6 +336,10 @@ class Oven(threading.Thread):
self.reset()
def get_state(self):
if self.output.temp_disp:
self.output.temp_disp.temp(int(self.board.temp_sensor.temperature))
state = {
'runtime': self.runtime,
'temperature': self.board.temp_sensor.temperature + config.thermocouple_offset,
@ -393,14 +461,12 @@ class RealOven(Oven):
# call parent init
Oven.__init__(self)
self.output.safety_off()
# start thread
self.start()
def reset(self):
super().reset()
self.output.safety_on()
self.output.cool(0)
def heat_then_cool(self):
@ -420,6 +486,14 @@ class RealOven(Oven):
if heat_off:
self.output.cool(heat_off)
time_left = self.totaltime - self.runtime
time_left_h = int(floor(time_left / 3600))
time_left_m = int(ceil((time_left % 3600) / 60))
if self.output.time_disp:
self.output.time_disp.time(time_left_h,
time_left_m)
log.info("temp=%.2f, target=%.2f, pid=%.3f, heat_on=%.2f, heat_off=%.2f, run_time=%d, total_time=%d, time_left=%d" %
(self.board.temp_sensor.temperature + config.thermocouple_offset,
self.target,

View File

@ -1,7 +1,10 @@
import threading,logging,json,time,datetime
from oven import Oven
import config
log = logging.getLogger(__name__)
class OvenWatcher(threading.Thread):
def __init__(self,oven):
self.last_profile = None
@ -9,11 +12,13 @@ class OvenWatcher(threading.Thread):
self.started = None
self.recording = False
self.observers = []
threading.Thread.__init__(self)
self.daemon = True
self.oven = oven
self.start()
# FIXME - need to save runs of schedules in near-real-time
# FIXME - this will enable re-start in case of power outage
# FIXME - re-start also requires safety start (pausing at the beginning

View File

@ -7,3 +7,4 @@ RPi.GPIO
Adafruit-MAX31855
Adafruit-GPIO
websocket-client
raspberrypi-tm1637