simplify kiln-tuner, fix docs
This commit is contained in:
parent
62efd5cde5
commit
1abeac4f4e
@ -94,10 +94,12 @@ If you're done playing around with simulations and want to deploy the code on a
|
||||
|
||||
All parameters are defined in config.py, review/change to your mind's content.
|
||||
|
||||
You should change, test, and verify PID parameters in config.py. Here is a [PID Tuning Guide](https://github.com/jbruce12000/kiln-controller/blob/master/docs/pid_tuning.md). There is also an [autotuner](https://github.com/jbruce12000/kiln-controller/blob/master/docs/ziegler_tuning.md). Be patient with tuning. No tuning is perfect across a wide temperature range.
|
||||
You should change, test, and verify PID parameters in config.py. You need to read through config.py carefully to understand each setting.
|
||||
|
||||
You may want to change the configuration parameter **sensor_time_wait**. It's the duty cycle for the entire system. It's set to two seconds by default which means that a decision is made every 2s about whether to turn on relay[s] and for how long. If you use mechanical relays, you may want to increase this. At 2s, my SSR switches 11,000 times in 13 hours.
|
||||
|
||||
You should change **temp_scale** to either f for Farenheit or c for Celcius.
|
||||
|
||||
## Testing
|
||||
|
||||
After you've completed connecting all the hardware together, there are scripts to test the thermocouple and to test the output to the solid state relay. Read the scripts below and then start your testing. First, activate the virtual environment like so...
|
||||
@ -116,6 +118,10 @@ and you can use this script to examine each pin's state including input/output/v
|
||||
|
||||
$ ./gpioreadall.py
|
||||
|
||||
## PID Tuning
|
||||
|
||||
Run the [autotuner](https://github.com/jbruce12000/kiln-controller/blob/master/docs/ziegler_tuning.md). It will heat your kiln to 400, pass that, and then once it cools back down to 400, it will calculate PID values to copy into config.py. No tuning is perfect across a wide temperature range. Here is a [PID Tuning Guide](https://github.com/jbruce12000/kiln-controller/blob/master/docs/pid_tuning.md) if you end up having to manually tune.
|
||||
|
||||
## Usage
|
||||
|
||||
### Server Startup
|
||||
|
||||
22
config.py
22
config.py
@ -28,7 +28,6 @@ listening_port = 8081
|
||||
# This is used to calculate a cost estimate before a run. It's also used
|
||||
# to produce the actual cost during a run. My kiln has three
|
||||
# elements that when my switches are set to high, consume 9460 watts.
|
||||
|
||||
kwh_rate = 0.1319 # cost per kilowatt hour per currency_type to calculate cost to run job
|
||||
kw_elements = 9.460 # if the kiln elements are on, the wattage in kilowatts
|
||||
currency_type = "$" # Currency Symbol to show when calculating cost to run job
|
||||
@ -99,10 +98,12 @@ sensor_time_wait = 2
|
||||
# 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 25,200,200
|
||||
pid_ki = 10 # Integral
|
||||
pid_kd = 200 # Derivative
|
||||
|
||||
#pid_kp = 25 # Proportional 25,200,200
|
||||
#pid_ki = 10 # Integral
|
||||
#pid_kd = 200 # Derivative
|
||||
pid_kp = 14.22801211254364
|
||||
pid_ki = 4.747842807629315
|
||||
pid_kd = 240.283966775251
|
||||
|
||||
########################################################################
|
||||
#
|
||||
@ -115,7 +116,7 @@ stop_integral_windup = True
|
||||
########################################################################
|
||||
#
|
||||
# Simulation parameters
|
||||
simulate = False
|
||||
simulate = True
|
||||
sim_t_env = 60.0 # deg C
|
||||
sim_c_heat = 500.0 # J/K heat capacity of heat element
|
||||
sim_c_oven = 5000.0 # J/K heat capacity of oven
|
||||
@ -132,7 +133,6 @@ 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
|
||||
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
|
||||
@ -164,10 +164,10 @@ pid_control_window = 5 #degrees
|
||||
# cheap thermocouple. Invest in a better thermocouple.
|
||||
thermocouple_offset=0
|
||||
|
||||
# number of samples of temperature to average.
|
||||
# If you suffer from the high temperature kiln issue and have set
|
||||
# honour_theromocouple_short_errors to False,
|
||||
# you will likely need to increase this (eg I use 40)
|
||||
# number of samples of temperature to average over each duty cycle.
|
||||
# The larger the number, the more load on the board. K type
|
||||
# thermocouples have a precision of about 1/2 degree C. This
|
||||
# averaging smooths out the stair step jumps of this imprecision.
|
||||
temperature_average_samples = 40
|
||||
|
||||
# Thermocouple AC frequency filtering - set to True if in a 50Hz locale, else leave at False for 60Hz locale
|
||||
|
||||
@ -6,18 +6,19 @@ import csv
|
||||
import time
|
||||
import argparse
|
||||
|
||||
def recordprofile(csvfile, targettemp):
|
||||
|
||||
try:
|
||||
try:
|
||||
sys.dont_write_bytecode = True
|
||||
import config
|
||||
sys.dont_write_bytecode = False
|
||||
|
||||
except ImportError:
|
||||
except ImportError:
|
||||
print("Could not import config file.")
|
||||
print("Copy config.py.EXAMPLE to config.py and adapt it for your setup.")
|
||||
exit(1)
|
||||
|
||||
|
||||
def recordprofile(csvfile, targettemp):
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.insert(0, script_dir + '/lib/')
|
||||
|
||||
@ -186,31 +187,39 @@ if __name__ == "__main__":
|
||||
subparsers = parser.add_subparsers()
|
||||
parser.set_defaults(mode='')
|
||||
|
||||
parser_profile = subparsers.add_parser('recordprofile', help='Record kiln temperature profile')
|
||||
parser_profile.add_argument('csvfile', type=str, help="The CSV file to write to.")
|
||||
parser_profile.add_argument('--targettemp', type=int, default=400, help="The target temperature to drive the kiln to (default 400).")
|
||||
parser_profile.set_defaults(mode='recordprofile')
|
||||
csvfile = "tuning.csv"
|
||||
target = 400
|
||||
if config.temp_scale.lower() == "c":
|
||||
target = (target - 32)*5/9
|
||||
tangentdivisor = 8
|
||||
|
||||
parser_zn = subparsers.add_parser('zn', help='Calculate Ziegler-Nicols parameters')
|
||||
parser_zn.add_argument('csvfile', type=str, help="The CSV file to read from. Must contain two columns called time (time in seconds) and temperature (observed temperature)")
|
||||
parser_zn.add_argument('--showplot', action='store_true', help="If set, also plot results (requires pyplot to be pip installed)")
|
||||
parser_zn.add_argument('--tangentdivisor', type=float, default=8, help="Adjust the tangent calculation to fit better. Must be >= 2 (default 8).")
|
||||
parser_zn.set_defaults(mode='zn')
|
||||
# parser_profile = subparsers.add_parser('recordprofile', help='Record kiln temperature profile')
|
||||
# parser_profile.add_argument('csvfile', type=str, help="The CSV file to write to.")
|
||||
# parser_profile.add_argument('--targettemp', type=int, default=400, help="The target temperature to drive the kiln to (default 400).")
|
||||
# parser_profile.set_defaults(mode='recordprofile')
|
||||
|
||||
#parser_zn = subparsers.add_parser('zn', help='Calculate Ziegler-Nicols parameters')
|
||||
#parser_zn.add_argument('csvfile', type=str, help="The CSV file to read from. Must contain two columns called time (time in seconds) and temperature (observed temperature)")
|
||||
#parser_zn.add_argument('--showplot', action='store_true', help="If set, also plot results (requires pyplot to be pip installed)")
|
||||
#parser_zn.add_argument('--tangentdivisor', type=float, default=8, help="Adjust the tangent calculation to fit better. Must be >= 2 (default 8).")
|
||||
#parser_zn.set_defaults(mode='zn')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.mode == 'recordprofile':
|
||||
recordprofile(args.csvfile, args.targettemp)
|
||||
# default behavior is to record profile to csv file tuning.csv
|
||||
# and then calculate pid values and print them
|
||||
recordprofile(csvfile, target)
|
||||
calculate(csvfile, tangentdivisor, False)
|
||||
|
||||
elif args.mode == 'zn':
|
||||
if args.tangentdivisor < 2:
|
||||
raise ValueError("tangentdivisor must be >= 2")
|
||||
|
||||
calculate(args.csvfile, args.tangentdivisor, args.showplot)
|
||||
|
||||
elif args.mode == '':
|
||||
parser.print_help()
|
||||
exit(1)
|
||||
|
||||
else:
|
||||
raise NotImplementedError("Unknown mode %s" % args.mode)
|
||||
#elif args.mode == 'zn':
|
||||
# if args.tangentdivisor < 2:
|
||||
# raise ValueError("tangentdivisor must be >= 2")
|
||||
#
|
||||
# calculate(args.csvfile, args.tangentdivisor, args.showplot)
|
||||
#
|
||||
# elif args.mode == '':
|
||||
# parser.print_help()
|
||||
# exit(1)
|
||||
#
|
||||
# else:
|
||||
# raise NotImplementedError("Unknown mode %s" % args.mode)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user