diff --git a/config.py b/config.py index 10d3a24..be68ded 100644 --- a/config.py +++ b/config.py @@ -57,7 +57,7 @@ sensor_time_wait = 2 # These parameters work well with the simulated oven. You must tune them # to work well with your specific kiln. Note that the integral pid_ki is # inverted so that a smaller number means more integral action. -pid_kp = 25 # Proportional +pid_kp = 25 # Proportional pid_ki = 200 # Integral pid_kd = 200 # Derivative @@ -66,11 +66,11 @@ pid_kd = 200 # Derivative # # Initial heating and Integral Windup # -# During initial heating, if the temperature is constantly under the +# During initial heating, if the temperature is constantly under the # setpoint,large amounts of Integral can accumulate. This accumulation # causes the kiln to run above the setpoint for potentially a long # period of time. These settings allow integral accumulation only when -# the temperature is within stop_integral_windup_margin percent below +# the temperature is within stop_integral_windup_margin percent below # or above the setpoint. This applies only to the integral. stop_integral_windup = True stop_integral_windup_margin = 10 @@ -96,20 +96,20 @@ sim_R_ho_air = 0.05 # K/W " with internal air circulation # If you change the temp_scale, all settings in this file are assumed to # be in that scale. -temp_scale = "f" # c = Celsius | f = Fahrenheit - Unit to display +temp_scale = "f" # c = Celsius | f = Fahrenheit - Unit to display time_scale_slope = "h" # s = Seconds | m = Minutes | h = Hours - Slope displayed in temp_scale per time_scale_slope time_scale_profile = "m" # s = Seconds | m = Minutes | h = Hours - Enter and view target time in time_scale_profile # emergency shutoff the profile if this temp is reached or exceeded. # This just shuts off the profile. If your SSR is working, your kiln will -# naturally cool off. If your SSR has failed/shorted/closed circuit, this +# naturally cool off. If your SSR has failed/shorted/closed circuit, this # means your kiln receives full power until your house burns down. # this should not replace you watching your kiln or use of a kiln-sitter -emergency_shutoff_temp = 2264 #cone 7 +emergency_shutoff_temp = 2264 #cone 7 -# If the kiln cannot heat or cool fast enough and is off by more than +# If the kiln cannot heat or cool fast enough and is off by more than # kiln_must_catch_up_max_error the entire schedule is shifted until -# the desired temperature is reached. If your kiln cannot attain the +# the desired temperature is reached. If your kiln cannot attain the # wanted temperature, the schedule will run forever. kiln_must_catch_up = True kiln_must_catch_up_max_error = 10 #degrees @@ -119,3 +119,13 @@ kiln_must_catch_up_max_error = 10 #degrees # set set this offset to -4 to compensate. This probably means you have a # cheap thermocouple. Invest in a better thermocouple. thermocouple_offset=0 + +# some kilns/thermocouples start erroneously reporting "short" errors at higher temperatures +# due to plasma forming in the kiln. +# Set this to False to ignore these errors and assume the temperature reading was correct anyway +honour_theromocouple_short_errors = True + +# number of samples of temperature to average. +# If you suffer from ghe high temperature kiln issue and have set honour_theromocouple_short_errors to False, +# you will likely need to increase this (eg I use 40) +temperature_average_samples = 5 diff --git a/lib/max31855.py b/lib/max31855.py index 1cd77aa..60475a7 100644 --- a/lib/max31855.py +++ b/lib/max31855.py @@ -26,7 +26,7 @@ class MAX31855(object): self.units = units self.data = None self.board = board - self.noConnection = self.shortToGround = self.shortToVCC = False + self.noConnection = self.shortToGround = self.shortToVCC = self.unknownError = False # Initialize needed GPIO GPIO.setmode(self.board) @@ -74,9 +74,10 @@ class MAX31855(object): if anyErrors: self.noConnection = (data_32 & 0x00000001) != 0 # OC bit, D0 self.shortToGround = (data_32 & 0x00000002) != 0 # SCG bit, D1 - self.shortToVCC = (data_32 & 0x00000004) != 0 + self.shortToVCC = (data_32 & 0x00000004) != 0 # SCV bit, D2 + self.unknownError = not (self.noConnection | self.shortToGround | self.shortToVCC) # Errk! else: - self.noConnection = self.shortToGround = self.shortToVCC = False + self.noConnection = self.shortToGround = self.shortToVCC = self.unknownError = False def data_to_tc_temperature(self, data_32 = None): '''Takes an integer and returns a thermocouple temperature in celsius.''' diff --git a/lib/oven.py b/lib/oven.py index e8c0c30..03fbae1 100644 --- a/lib/oven.py +++ b/lib/oven.py @@ -8,7 +8,6 @@ import config log = logging.getLogger(__name__) -TEMPERATURE_MOVING_AVERAGE_SAMPLES = 40 class Output(object): def __init__(self): @@ -124,15 +123,24 @@ class TempSensorReal(TempSensor): temps = [] while True: temp = self.thermocouple.get() - temps.append(temp) - if len(temps) > TEMPERATURE_MOVING_AVERAGE_SAMPLES: - del temps[0] - - if len(temps): - self.temperature = sum(temps) / len(temps) self.noConnection = self.thermocouple.noConnection self.shortToGround = self.thermocouple.shortToGround self.shortToVCC = self.thermocouple.shortToVCC + self.unknownError = self.thermocouple.unknownError + + is_bad_value = self.noConnection | self.unknownError + if config.honour_theromocouple_short_errors: + is_bad_value |= self.shortToGround | self.shortToVCC + + if not is_bad_value: + temps.append(temp) + if len(temps) > config.temperature_average_samples: + del temps[0] + else: + log.error(f"Problem reading temp N/C:{self.noConnection} GND:{self.shortToGround} VCC:{self.shortToVCC} ???:{self.unknownError}") + + if len(temps): + self.temperature = sum(temps) / len(temps) time.sleep(self.sleeptime) class Oven(threading.Thread): @@ -167,6 +175,9 @@ class Oven(threading.Thread): if self.board.temp_sensor.shortToVCC: log.info("Refusing to start profile - thermocouple short to VCC") return + if self.board.temp_sensor.unknownError: + log.info("Refusing to start profile - thermocouple unknown error") + return log.info("Running schedule %s" % profile.name) self.profile = profile @@ -217,6 +228,10 @@ class Oven(threading.Thread): log.info("emergency!!! lost connection to thermocouple, shutting down") self.reset() + if self.board.temp_sensor.unknownError: + log.info("emergency!!! unknown thermocouple error, shutting down") + self.reset() + def reset_if_schedule_ended(self): if self.runtime > self.totaltime: log.info("schedule ended, shutting down")