Example #1
0
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()
Example #2
0
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")