3

I'm trying to make a program that reads the serial of my arduino and shows the information in real time in a GUI. The problem is that I don't know how to make the data update in real time.

This is my current code:

import re
import serial
import PySimpleGUI as sg

class InterfaceGrafica:
    def __init__(self):
        layout = [[sg.Text('Interface gráfica para o controle do secador.')],
                  [sg.Text('Valor do controle PWM:'), sg.Text(Dados().pwm, key = 'pwm')],
                  [sg.Text('Valor da temperatura: '), sg.Text(Dados().temp, key = 'temp')],
                  [sg.Text('Peso: '), sg.Text(Dados().peso, key = 'peso')],
                  [sg.Text('Valor da umidade: '), sg.Text(Dados().um, key = 'um')],
                  [sg.Text('Temperatura setpoint: '), sg.Text(Dados().set, key = 'set')],
                  [sg.Button('Exit')]]

        self.janela = sg.Window('Versão final', layout=layout, size=(600, 600))

    def Iniciar(self):
        while True:
            self.event, self.values = self.janela.Read()
            if self.event == sg.WIN_CLOSED or self.event == 'Exit':
                break
            conecao = serial.Serial("COM3", 9600)

            for i in range(20):
                leitura = conecao.readline()
                leiturad = leitura.decode()
                var = re.split(',', leiturad)
                print(leiturad)
                self.janela.Element('pwm').Update(values=var[0])
                janela.Refresh
                self.janela.Element('temp').Update(values=var[1])
                self.janela.Element('peso').Update(values=var[2])
                self.janela.Element('um').Update(values=var[3])
                self.janela.Element('set').Update(values=var[4])

tela = InterfaceGrafica()
tela.Iniciar()
He3lixxx
  • 3,263
  • 1
  • 12
  • 31
  • Using multi-threading to check and get data from your serial port, then call `window.write_event_value` to generate an event with value. In your event loop to process that event and update sg.Text, like `self.janela['pwm'].update(value=value)`. – Jason Yang Jun 22 '21 at 15:54

2 Answers2

2

You need to set a timeout for self.janela.read( timeout=250 )
I created a fake Dados to test, (which you don't have to use), and it updates.

https://pysimplegui.readthedocs.io/en/latest/

#! /usr/bin/env python3
##  pip3 install serial pysimplegui
##  Python -m pip install serial pysimplegui

import re
import serial
import random
import PySimpleGUI as sg

class Singleton( object ):
    def __new__( cls ):
        if not hasattr( cls, 'instance' ):
            cls .instance = super( Singleton, cls ) .__new__( cls )
        return cls .instance

Dados = Singleton()

def update():
    print( 'update' )
    Dados .pwm = random .random()
    Dados .temp = f'{ random .randint( 50, 100 ) } *F'
    Dados .peso = f'$ { random .randint( 1, 30 ) }'
    Dados .um = random .randint( 1, 100 )
    Dados .set = random .randint( 1, 100 )


class InterfaceGrafica:
    def __init__(self):
        layout = [ [ sg .Text('Interface gráfica para o controle do secador.') ],
                   [ sg .Text('Valor do controle PWM:'),  sg .Text( Dados .pwm,  key='pwm' ) ],
                   [ sg .Text('Valor da temperatura: '),  sg .Text( Dados .temp,  key='temp' ) ],
                   [ sg .Text('Peso: '),  sg .Text( Dados .peso,  key='peso' ) ],
                   [ sg .Text('Valor da umidade: '),  sg .Text( Dados .um,  key='um' ) ],
                   [ sg .Text('Temperatura setpoint: '),  sg .Text( Dados .set,  key='set' ) ],
                   [ sg .Button('Exit') ] ]

        self.janela = sg.Window( 'Versão final', layout=layout, size=(400, 300) )

        while True:
            self.event, self.values = self.janela.read( timeout=250 )
            if self.event == sg.WIN_CLOSED or self.event == 'Exit':
                break
            '''
            conecao = serial.Serial("COM3", 9600)
            for i in range(20):  leitura = conecao.readline()  ##  read 20 lines from serial

            leiturad = leitura.decode()  ##  decode those 20 lines
            var = re.split(',', leiturad)  ##  split CSV into list
            print(var)
            '''

            self.janela['pwm']( Dados .pwm )  ##  var[ 0 ]
            self.janela['temp']( Dados .temp )  ##  var[ 1 ]
            self.janela['peso']( Dados .peso )  ##  var[ 2 ]
            self.janela['um']( Dados .um )  ##  var[ 3 ]
            self.janela['set']( Dados .set )  ##  var[ 4 ]
            self.janela.Refresh()
            update()

update()
InterfaceGrafica()
Doyousketch2
  • 2,060
  • 1
  • 11
  • 11
0

Using multi-thread, or your GUI will be no respond when your code blocked at reading com port.

Following code not tested for no com port input, so somewhere maybe typo error or something wrong.

import serial   # pip install PySerial
import threading
import PySimpleGUI as sg

class GUI:
    def __init__(self):
        sg.theme('DarkBlue3')
        sg.set_options(font=("Courier New", 16))
        layout = [
            [self.center([[sg.Text('Controller of Dryer', font=("Courier New", 20, 'bold'))]])],
            [sg.Text("")],
            [sg.Text('PWM        '), self.Text('PWM'     )],
            [sg.Text('TEMPERATURE'), self.Text('TEMP'    )],
            [sg.Text('WEIGHT     '), self.Text('WEIGHT'  )],
            [sg.Text('MOISTURE   '), self.Text('MOISTURE')],
            [sg.Text('SETPOINT   '), self.Text('SETPOINT')],
            [sg.Text("")],
            [self.center([[sg.Button('Exit')]])],
        ]
        self.window = sg.Window('Final version', layout=layout, finalize=True)
        self.running = True
        self.com = serial.Serial("COM3", 9600)
        threading.Thread(target=self.get_data, args=(window,), daemon=True).start()
        self.start()

    def center(self, layout):
        return sg.Column(layout, element_justification='center', expand_x=True)

    def Text(self, key):
        return sg.Text('', size=(20, 1), text_color='white', background_color='blue', key=key)

    def get_data(self):
        while self.running:
            data = com.readline().decode().split(",")
            self.window.write_event_value("DATA", data)

    def start(self):
        while True:
            event, values = self.window.read()
            if event in (sg.WIN_CLOSED, 'Exit'):
                break
            elif event == 'DATA':
                data = values[event]
                self.update(data)
        self.running = False
        self.window.close()

    def update(self, data):
        for i, key in enumerate(('PWM', 'TEMP', 'WEIGHT', 'MOISTURE', 'SETPOINT')):
            self.window[key].update(value=data[i])

GUI()
Jason Yang
  • 11,284
  • 2
  • 9
  • 23