class Gui: def __init__(self, master): self.arduino = None self.port = "COM7" self.updater = Thread() self.windowframe = Frame(master) self.port_entry = Entry(self.windowframe) self.port_label = Label(self.windowframe, text="COM Port:") self.arduino_connect_button = Button(self.windowframe, text="Connect Arduino", command=self.connect_arduino) self.start_button = Button(self.windowframe, text="Start", command=self.start) self.stop_Button = Button(self.windowframe, text="Exit", command=master.destroy) self.temperature_plot = Plot(self.windowframe, "Time [min]", "T\n\n°C", 500) self.place_widgets() def place_widgets(self): self.windowframe.place(x=10, y=10, width=500, height=560) self.port_label.place(x=0, y=0, height=25, width=160) self.port_entry.place(x=170, y=0, height=25, width=160) self.arduino_connect_button.place(x=340, y=0, width=160, height=25) self.start_button.place(x=0, y=30, width=245, height=25) self.stop_Button.place(x=255, y=30, height=25, width=245) self.temperature_plot.place(x=0, y=60, height=500, width=500) def connect_arduino(self): if self.port_entry.get() != "": self.port = self.port_entry.get() self.arduino = Arduino(self.port) sleep(1) def start(self): def update(): start_time = datetime.now() while True: thermocouple_temperature = self.arduino.thermocouple_temperature.get() runtime = (datetime.now() - start_time).seconds / 60.0 self.temperature_plot.add_datapoint(runtime, thermocouple_temperature) self.updater._target = update self.updater.start() self.arduino.start_updater()
class GUI: """A simple GUI for the PLD heater""" def __init__(self, master): self.PLD_port = "COM5" self.PLD_address = 5 self.PLD = None self.pyrometer_port = "COM10" self.pyrometer = None self.active_plot = 1 self.start_time = None self.label_updater = Thread() self.pyrometer_pld_communication = Thread() self.icon_left = PhotoImage(file="Button_left.png") self.icon_right = PhotoImage(file="Button_right.png") self.window_frame = Frame(master, bd=2, relief=GROOVE) self.sensor_frame = Frame(self.window_frame, bd=2, relief=GROOVE) self.parameter_frame = Frame(self.window_frame, bd=2, relief=GROOVE) self.graph_frame = Frame(self.window_frame, bd=2, relief=GROOVE) self.connect_frame = Frame(self.window_frame, bd=2, relief=GROOVE) self.log_frame = Frame(self.window_frame, bd=2, relief=GROOVE) self.plot_frame = Frame(self.window_frame, bd=2, relief=GROOVE) self.oven_temperature_label = Label(self.sensor_frame, text="Oven temperature: °C") self.external_temperature_label = Label(self.sensor_frame, text="Sample temperature: °C") self.working_setpoint_label = Label(self.sensor_frame, text="Working setpoint: °C") self.working_output_label = Label(self.sensor_frame, text="Working ouput %") self.power_output_label = Label(self.parameter_frame, text="Power output %") self.power_output_entry = Entry(self.parameter_frame) self.power_output_setter_button = Button(self.parameter_frame, text="Set power output [%]", command=self.set_target_output_power, state=DISABLED) self.setpoint_label = Label(self.parameter_frame, text="Setpoint: °C") self.setpoint_entry = Entry(self.parameter_frame) self.setpoint_setter_button = Button(self.parameter_frame, text="Set target setpoint [°C]", command=self.set_target_setpoint, state=DISABLED) self.mode_label = Label(self.parameter_frame, text="Manual control mode") self.mode_switcher_button = Button(self.parameter_frame, text="Switch mode", command=self.switch_mode, state=DISABLED) self.external_sensor_mode_label = Label(self.parameter_frame, text="External sensor mode off") self.external_sensor_mode_button = Button(self.parameter_frame, text="Enable external sensor mode", command=self.enable_external_sensor_temperature, state=DISABLED) self.hold_temperature_button = Button(self.parameter_frame, text="Hold temperature", command=self.hold_temperature, state=DISABLED) self.PLD_com_port_entry = Entry(self.connect_frame) self.PLD_com_port_label = Label(self.connect_frame, text="PLD COM Port") self.PLD_slave_address_entry = Entry(self.connect_frame) self.PLD_salve_address_label = Label(self.connect_frame, text="PLD slave Address (Default 1)") self.PLD_connect_button = Button(self.connect_frame, text="Connect PLD", command=self.connect_pld) self.pyrometer_com_port_entry = Entry(self.connect_frame) self.pyrometer_com_port_label = Label(self.connect_frame, text="Pyrometer COM Port") self.pyrometer_connect_button = Button(self.connect_frame, text="Connect Pyrometer", command=self.connect_pyrometer) self.start_label_updater_button = Button(self.connect_frame, text="Start", command=self.start_label_updater, state=DISABLED) self.log_label = Label(self.log_frame, text="Temperature Log") self.log_text = Text(self.log_frame) self.switch_plot_left_button = Button(self.plot_frame, command=self.switch_plot_left, image=self.icon_left) self.switch_plot_right_button = Button(self.plot_frame, command=self.switch_plot_right, image=self.icon_right) self.plot_label = Label(self.plot_frame, text="Oven temperature") self.pyrometer_plot_frame = Frame(self.plot_frame) self.oven_temperature_plot_frame = Frame(self.plot_frame) self.power_ouput_plot_frame = Frame(self.plot_frame) self.pyrometer_plot = Plot(self.pyrometer_plot_frame, "Time [min]", "T\n\n°C", 350) self.power_ouput_plot = Plot(self.power_ouput_plot_frame, "Time [min]", "P\n\n%", 350) self.oven_temperature_plot = Plot(self.oven_temperature_plot_frame, "Time [min]", "T\n\n°C", 350) self.place_widgets() def place_widgets(self): """Place each widgets""" self.window_frame.place(x=10, y=10, height=415, width=1010) self.connect_frame.place(height=105, width=630, x=10, y=10) self.pyrometer_com_port_label.place(height=25, width=200, x=10, y=10) self.pyrometer_com_port_entry.place(height=25, width=200, x=215, y=10) self.pyrometer_connect_button.place(height=25, width=200, x=420, y=10) self.PLD_com_port_label.place(height=25, width=200, x=10, y=40) self.PLD_com_port_entry.place(height=25, width=200, x=215, y=40) self.PLD_connect_button.place(height=25, width=200, x=420, y=40) self.PLD_salve_address_label.place(height=25, width=200, x=10, y=70) self.PLD_slave_address_entry.place(height=25, width=200, x=215, y=70) self.start_label_updater_button.place(height=25, width=200, x=420, y=70) self.parameter_frame.place(height=135, width=630, x=10, y=125) self.setpoint_label.place(height=25, width=200, x=10, y=10) self.setpoint_entry.place(height=25, width=200, x=215, y=10) self.setpoint_setter_button.place(height=25, width=200, x=420, y=10) self.power_output_label.place(height=25, width=200, x=10, y=40) self.power_output_entry.place(height=25, width=200, x=215, y=40) self.power_output_setter_button.place(height=25, width=200, x=420, y=40) self.mode_switcher_button.place(height=25, width=405, x=215, y=70) self.mode_label.place(height=25, width=200, x=10, y=70) self.external_sensor_mode_label.place(height=25, width=200, x=10, y=100) self.external_sensor_mode_button.place(height=25, width=200, x=215, y=100) self.hold_temperature_button.place(height=25, width=200, x=420, y=100) self.sensor_frame.place(height=135, width=220, x=10, y=270) self.oven_temperature_label.place(height=25, width=200, x=10, y=10) self.external_temperature_label.place(height=25, width=200, x=10, y=40) self.working_setpoint_label.place(height=25, width=200, x=10, y=70) self.working_output_label.place(height=25, width=200, x=10, y=100) self.log_frame.place(height=135, width=400, x=240, y=270) self.log_text.place(height=115, width=380, x=10, y=10) self.plot_frame.place(x=640, y=10, width=360, height=395) self.switch_plot_left_button.place(x=5, y=5, height=30, width=30) self.switch_plot_right_button.place(x=325, y=5, height=30, width=30) self.plot_label.place(x=35, y=5, height=25, width=295) self.pyrometer_plot_frame.place(x=5, y=40, width=350, height=350) self.oven_temperature_plot_frame.place(x=5, y=40, width=350, height=350) self.power_ouput_plot_frame.place(x=5, y=40, width=350, height=350) self.pyrometer_plot.place(x=0, y=0, width=350, height=350) self.oven_temperature_plot.place(x=0, y=00, width=350, height=350) self.power_ouput_plot.place(x=0, y=0, width=350, height=350) self.oven_temperature_plot_frame.lift() def start_label_updater(self): """Read values from instrument objects every second, display them, plot them and write in a logfile""" self.start_time = datetime.now() def update_labels(): while True: pyrometer_temperature = "---" oven_temperature = "---" working_output = "---" working_setpoint = "---" runtime = (datetime.now() - self.start_time).seconds / 60.0 if self.PLD is not None: oven_temperature = self.PLD.oven_temp.get() self.oven_temperature_plot.add_datapoint(runtime, oven_temperature) self.oven_temperature_label.configure(text="Oven temperature: %s °C" % oven_temperature) working_output = self.PLD.working_output.get() self.power_ouput_plot.add_datapoint(runtime, working_output) self.working_output_label.configure(text="Working output: %s %%" % working_output) working_setpoint = self.PLD.working_setpoint.get() self.working_setpoint_label.configure(text="Working setpoint: %s °C" % working_setpoint) if self.pyrometer is not None: pyrometer_temperature = self.pyrometer.temperature.get() self.pyrometer_plot.add_datapoint(runtime, pyrometer_temperature) self.external_temperature_label.configure(text="Sample temperature %s °C" % pyrometer_temperature) logstring = "Time: " + strftime("%X") \ + ("Oven temperature: %s °C" % oven_temperature).ljust(28, " ") \ + ("Power Output %s %%" % working_output).ljust(28, " ")\ + ("Working Setpoint: %s °C" % working_setpoint).ljust(28, " ")\ + ("Pyrometer temperature: %s °C" % pyrometer_temperature).ljust(28, " ") \ + "\n" printstring = "Time: " + strftime("%X") \ + ("Oven temperature: %s °C" % oven_temperature).ljust(28, " ") \ + ("Pyrometer temperature: %s °C" % pyrometer_temperature).ljust(28, " ")\ + "\n" self.log_text.insert(END, printstring) sleep(0.5) self.label_updater._target = update_labels self.label_updater.start() if self.PLD is not None and self.pyrometer is not None: self.start_pyrometer_pld_communication() if self.PLD is not None: self.mode_switcher_button.configure(state=NORMAL) self.power_output_setter_button.configure(state=NORMAL) self.PLD.switch_to_manual_mode() self.mode_label.configure(text="Manual operation mode") self.power_output_setter_button.configure(state=NORMAL) def connect_pld(self): """Connect to the PLD Eurotherm controller, start in manual mode""" if self.PLD_com_port_entry.get() != "": self.PLD_port = self.PLD_com_port_entry.get() if self.PLD_slave_address_entry.get() != "": self.PLD_address = int(self.PLD_slave_address_entry.get()) self.PLD = PLD(self.PLD_port, self.PLD_address) try: self.PLD.switch_to_manual_mode() except IOError: sleep(0.5) self.PLD.switch_to_manual_mode() self.PLD.start_oven_temperature_listener() self.PLD.start_working_output_listener() self.PLD.start_working_setpoint_listener() self.PLD.start_serial_io_handler() self.start_label_updater_button.configure(state=NORMAL) def connect_pyrometer(self): """Connect to the pyrometer""" if self.pyrometer_com_port_entry.get() != "": self.pyrometer_port = self.pyrometer_com_port_entry.get() self.pyrometer = Pyrometer(self.pyrometer_port) self.pyrometer.start_temperature_listener() self.start_label_updater_button.configure(state=NORMAL) self.external_sensor_mode_button.configure(state=NORMAL) def start_pyrometer_pld_communication(self): """Start supplying the PLD with the pyrometer temperature as external sensor temperature""" def talk(): while True: self.PLD.external_sensor_temperature.put(self.pyrometer.temperature) sleep(1) self.pyrometer_pld_communication._target = talk self.pyrometer_pld_communication.start() def set_target_setpoint(self): """Write the target setpoint in the entry widget to the instrument""" self.PLD.target_setpoint = float(self.setpoint_entry.get()) self.setpoint_label.configure(text="Setpoint %s °C" % self.PLD.target_setpoint) self.PLD.write_target_setpoint(self.PLD.target_setpoint) def set_target_output_power(self): """Write the target ouput power in the entry to the instrument""" self.PLD.power_output = float(self.power_output_entry.get()) self.power_output_label.configure(text="Power ouput %s%%" % self.PLD.power_output) self.PLD.write_manual_output_power(self.PLD.power_output) def switch_mode(self): """Switch the instrument between manual and automatic mode""" if not self.PLD.operation_mode: self.PLD.switch_to_manual_mode() self.PLD.operation_mode = 1 self.mode_label.configure(text="Manual operation mode") self.power_output_setter_button.configure(state=NORMAL) self.setpoint_setter_button.configure(state=DISABLED) elif self.PLD.operation_mode: self.PLD.switch_to_automatic_mode() self.PLD.operation_mode = 0 self.mode_label.configure(text="Automatic operation mode") self.setpoint_setter_button.configure(state=NORMAL) self.power_output_setter_button.configure(state=DISABLED) def enable_external_sensor_temperature(self): """Enabele using an external temperarture sensor for the PLD""" self.PLD.set_external_sensor_temperature_mode() self.hold_temperature_button.configure(state=NORMAL) def hold_temperature(self): """Switch the PLD to manual mode and hold the current power output""" self.setpoint_setter_button.configure(state=DISABLED) self.power_output_setter_button.configure(state=NORMAL) self.PLD.hold_current_temperature() def switch_plot_left(self): """Switch the displayed plot""" if self.active_plot: self.active_plot -= 1 self.show_plot() def switch_plot_right(self): """Switch the displayed plot""" if self.active_plot < 2: self.active_plot += 1 self.show_plot() def show_plot(self): """Switch the displayed plot""" if self.active_plot == 0: self.pyrometer_plot_frame.lift() self.plot_label.configure(text="Pyrometer temperature") if self.active_plot == 1: self.oven_temperature_plot_frame.lift() self.plot_label.configure(text="Oven temperature") if self.active_plot == 2: self.power_ouput_plot_frame.lift() self.plot_label.configure(text="Power Output")