def calc_cost(tuning_rule, pid_pre_tune): timestamp = 0 cost = 0 n_err = 0 delayed_temps_len = max(1, round(args.delay / args.sampletime)) sim = Simulation( tuning_rule, PIDArduino(args.sampletime, float(pid_pre_tune[0]), float(pid_pre_tune[1]), float(pid_pre_tune[2]), args.out_min, args.out_max, lambda: timestamp), Kettle(args.diameter, args.volume, args.kettle_temp), deque(maxlen=delayed_temps_len), [], [], [], []) sim.delayed_temps.extend(sim.delayed_temps.maxlen * [args.kettle_temp]) # run system for a specified interval while timestamp < (args.interval * 60): timestamp += args.sampletime output = sim.sut.calc(sim.delayed_temps[0], args.setpoint) output = max(output, 0) output = min(output, 100) sim_update(sim, timestamp, output, args) #start calculating error and cost(mse) if timestamp > args.time_constant: n_err += 1 err = args.setpoint - sim.sensor_temps[-1] cost += err**2 J = cost / n_err return J
def simulate_autotune(args): timestamp = 0 # seconds maxlen = max(1, round(args.delay / args.sampletime)) delayed_temps = deque(maxlen=maxlen) delayed_temps.extend(maxlen * [args.kettle_temp]) # Simulation = namedtuple( # 'Simulation', # ['name', 'sut', 'kettle', 'delayed_temps', 'timestamps', # 'heater_temps', 'sensor_temps', 'outputs']) sim = Simulation( 'autotune', PIDAutotune( args.setpoint, 100, args.sampletime, out_min=args.out_min, out_max=args.out_max, time=lambda: timestamp), Kettle(args.diameter, args.volume, args.kettle_temp), delayed_temps, [], [], [], [] ) # Run autotune until completed while not sim.sut.run(sim.delayed_temps[0]): timestamp += args.sampletime sim_update(sim, timestamp, sim.sut.output, args) if args.verbose > 0: print('time: {0} sec'.format(timestamp)) print('state: {0}'.format(sim.sut.state)) print('{0}: {1:.2f}%'.format(sim.name, sim.sut.output)) print('temp sensor: {0:.2f}°C'.format(sim.sensor_temps[-1])) print('temp heater: {0:.2f}°C'.format(sim.heater_temps[-1])) print() print('time: {0} min'.format(round(timestamp / 60))) print('state: {0}'.format(sim.sut.state)) print() # On success, print params for each tuning rule if sim.sut.state == PIDAutotune.STATE_SUCCEEDED: for rule in sim.sut.tuning_rules: params = sim.sut.get_pid_parameters(rule) PID_dict[rule] = [params.Kp,params.Ki,params.Kd] if rule == "ziegler-nichols": PID_finetune[rule] = [params.Kp,params.Ki,params.Kd] print('Rule: {0}'.format(rule)) print('Kp: {0}'.format(params.Kp)) print('Ki: {0}'.format(params.Ki)) print('Kd: {0}'.format(params.Kd)) print() if args.export: write_csv(sim) if not args.noplot: title = 'PID autotune, {0:.1f}l kettle, {1:.1f}kW heater, {2:.1f}s delay'.format( args.volume, args.heater_power, args.delay) plot_simulations([sim], title)
def simulate_pid(args,PID_dict): timestamp = 0 # seconds delayed_temps_len = max(1, round(args.delay / args.sampletime)) sims = [] # Create a simulation for each tuple pid(name, kp, ki, kd) for key,pid in PID_dict.items(): sim = Simulation( key, PIDArduino( args.sampletime, float(pid[0]), float(pid[1]), float(pid[2]), args.out_min, args.out_max, lambda: timestamp), Kettle(args.diameter, args.volume, args.kettle_temp), deque(maxlen=delayed_temps_len), [], [], [], [] ) sims.append(sim) # Init delayed_temps deque for each simulation for sim in sims: sim.delayed_temps.extend(sim.delayed_temps.maxlen * [args.kettle_temp]) # Run simulation for specified interval while timestamp < (args.interval * 60): timestamp += args.sampletime for sim in sims: output = sim.sut.calc(sim.delayed_temps[0], args.setpoint) output = max(output, 0) output = min(output, 100) sim_update(sim, timestamp, output, args) if args.verbose > 0: print('time: {0} sec'.format(timestamp)) print('{0}: {1:.2f}%'.format(sim.name, output)) print('temp sensor: {0:.2f}°C'.format(sim.sensor_temps[-1])) print('temp heater: {0:.2f}°C'.format(sim.heater_temps[-1])) if args.verbose > 0: print() if args.export: for sim in sims: write_csv(sim) if not args.noplot: title = 'PID simulation, {0:.1f}l kettle, {1:.1f}kW heater, {2:.1f}s delay'.format( args.volume, args.heater_power, args.delay) plot_simulations(sims, title)
from kettle import Kettle k1 = Kettle(1500, 2000, 'white') print('K1', k1.vol, k1.pwr, k1.clr) k2 = Kettle(1000, 1500, 'black') print('K2', k2.vol, k2.pwr, k2.clr) k3 = Kettle(1500, 2000, 'black') print('K3', k3.vol, k3.pwr, k3.clr) k1.openLid() k2.openLid() k1.addWater(500) k1.addWater(500) k1.closeLid() k1.on() k1.boilKettle(100, 5) k1.off() k2.on()