0

I implemented a live data-visualization with matplotlib in PySimpleGUI. The program works fine so far. The issue I am having is, that the plot ist printed with a weird constant value (s. figure).

`

import logging
from time import time
import PySimpleGUI as pg
import math
import serial
import serial.tools.list_ports
import csv 
import matplotlib.pyplot as plt                                         #import matülotlib for graph-plotting
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg         #enable matplotlib to be embeded into PySimpleGUI
from queue import Queue                                                 #lib to define queues

#Variables
##bools
check_logging = False     #check logging-status (True = active; False = incactive)
check_measure = True      #check, if mode switches (Measure, Calibration)
check_csv   = False       #check, if csv-file is active
check_axline = False      #check, if 'Start'- or 'Stop'-button was pressed --> vertical marker in plot
check_plot = False
##Strings
check_sensor_before = " "      #check, if sensor-switch happened to only send index-char once
input1 = 0                 #check, if input1 already has saved data
input2 = 0                   #check, if input2 already has saved data
##double
t = 0.0         #check elapsed time since epoch
t_log = 0.0     #check start time of log to calculate elapsed time of logging-process
##lists
t_list = []         #time values
rpm1_list = []
rpm2_list = []
mark = []           #time values for start- and end-marker
##counter
plot_counter_start = 0        #keep track of the start index (just plot the 20 latest elements)
plot_counter_end = 0          #keep track of the end index (just plot the 20 latest elements)



#Serial-COM
ser=serial.Serial('COM3', 9600, timeout=10)         #build up serial connection to Arduino
ser.flush()

def create_plot(t, rpm):
    plt.clf()                                       #clear the current figure's memory; if queues update, y- and x-axis update with the new point set (max 20 points)
    #plt.xlabel('Time [s]')
    #plt.ylabel('Rotational Speed [1/min]')
    #plt.title('Rotational Speed Measurement')
    plt.plot(t, rpm, color='blue', mfc='red', marker='o',  label='points')
    plt.grid(True)
    return plt.gcf()                                #transform plot to figure for PySimpleGUI

col_layout1=[
    [pg.Text('Mode:                     Sensor:', font=('Calibri', 12, 'bold'), size=(25, 1), justification='left')],
    [pg.Combo(['Measure', 'Calibration'], font=('Calibri', 12), default_value='Measure', key='-mode-'), pg.Combo(['Auger LH/RH', 'Tamper', 'Vibration', 'Fan Speed', 'Fumes'], font=('Calibri', 12), default_value='Auger LH/RH', key='-sensor-')],
    [pg.Text('', size=(1,1))],
    [pg.Text('Auger LH         Auger RH', size=(20, 1), font=('Calibri', 12))],
    [pg.Input(size=(10, 1), font=('Calibri', 12), key='-input1-', justification='center'), pg.Input(size=(10, 1), font=('Calibri', 12), key='-input2-', justification='center')],
    [pg.Text('', size=(1,1))],
    [pg.Text('Data Logging', font=('Calibri', 12, 'bold'), size=(12, 1), justification='left'), pg.Radio('plot off', group_id='plot', default=True, key='-plot-'), pg.Radio('plot on', group_id='plot')],
    [pg.Text('Filename (.csv):', font=('Calibri', 10), size=(20, 1), justification='left')],
    [pg.Input(size=(21, 1), font=('Calibri', 12), key='-file_name-', justification='center')],
    [pg.Button('Start', font=('Calibri', 12), size=(10,1)), pg.Button('Stop', font=('Calibri', 12), size=(6,1))],
    [pg.Button('Save', font=('Calibri', 12), size=(21,1))],
    [pg.Text('', font=('Calibri', 10), size=(24, 1), justification='left', key = '-save_status-')],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))],
    [pg.Text('', size=(1,1))]
]

layout = [ 
    [pg.Column(col_layout1), pg.Canvas(size=(550, 450), key='-CANVAS-')]    
]

#transform figure to canvas_figure (tkinter/PySimpleGUI-compatible)
def draw_figure(canvas, figure):
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().place(width=500, height=450)
    return figure_canvas_agg

window = pg.Window('Mobile GAM', layout, size=(800, 480), element_justification='left', finalize=True)        #Create main-window

def plot(t, rpm):
    global plot_counter_start, plot_counter_end, check_axline                                     #refer to global variables to not encounter reference errors
    t_list.append(float(t))      #time-axis
    rpm1_list.append(int(rpm))   #rpm-axis (1st value)
        
    #check for max. list length (20)
    if (plot_counter_end - plot_counter_start) >= 20:                                                      #check, if 20 values are saved in value-lists 
        plot_counter_start = plot_counter_start + 1                                 #start incrementing the start-index as well to define the interval for the slice
        draw_figure(window['-CANVAS-'].TKCanvas, create_plot(t_list[plot_counter_start:plot_counter_end], rpm1_list[plot_counter_start:plot_counter_end]))      #plot the graph with sliced lists (20 most recent values)       
    else:
        draw_figure(window['-CANVAS-'].TKCanvas, create_plot(t_list, rpm1_list))      
    plot_counter_end = plot_counter_end + 1                                         #increment the end index to define the interval for the slice

#window.Maximize()  #Maximize window
#Deactivate 'Stop' and 'Save' at program-initialization
window.read(False)
window['Stop'].update(disabled=True)
window['Save'].update(disabled=True)

while True:
    window.refresh()
    event, values = window.read(False)

#---------------------------------------READ BUTTON EVENTS----------------------------------------- 
   
    if event == pg.WIN_CLOSED:
        break

    elif event == 'Start':
        #Reset status-text
        window['-save_status-'].update('')

        #update bools
        check_csv = True
        check_logging = True                              #save status: logging-process is initiated

        #create vertical marker lines
        check_axline = True

        t_log = time()                                    #save start-time of logging-process
        
        #Information for the CSV-File
        ##match-case-statements to check sensor-mode
        if values['-sensor-'] == 'Auger LH/RH':       
            header = ['Auger LH [RPM]', 'Auger RH [RPM]', 'Time [s]']  
        elif values['-sensor-'] == 'Tamper':
            header = ['Tamper [RPM]', 'Time [s]'] 
        elif values['-sensor-'] == 'Vibration':
            header = ['Vibration [RPM]', 'Time [s]'] 
        elif values['-sensor-'] == 'Fan Speed':
            header = ['Fan Speed [RPM]', 'Time [s]']
        elif values['-sensor-'] == 'Fumes':
            header = ['Fumes [RPM]', 'Time [s]']                   
          
        #CSV-File
        ##check for file name input
        if values['-file_name-'] == '':
            f = open('data.csv', 'w+', encoding='UTF8')     #declare file-pointer
        else:
            f = open(values['-file_name-']+'.csv', 'w+', encoding='UTF8')
        writer = csv.writer(f)                                  #declare write for 'writerow()'-function
        writer.writerow(header)   #write the header 

        #update buttons
        window.read(False)
        window['Start'].update(disabled=True)
        window['Stop'].update(disabled=False)
        window['Save'].update(disabled=True)

    elif event == 'Stop':
        check_logging = False
        #update buttons
        window.read(False)
        window['Start'].update(disabled=False)
        window['Stop'].update(disabled=True)
        window['Save'].update(disabled=False)

    elif event == 'Save':       
        f.close()               #close csv-file-pointer
        check_csv = False       #update csv-bool 

        #update buttons      
        window.read(False)
        window['Save'].update(disabled=True)

        #update status-text
        if values['-file_name-'] == '':
            window['-save_status-'].update('\'data.csv\' saved to Desktop')
        else:
            window['-save_status-'].update('\'' + values['-file_name-'] + '.csv\' saved to Desktop')
        
    if not values['-plot-']:        #check, if 'plot off' is active
        check_plot = True
    else:
        check_plot = False
#------------------------------------SEND DATA TO ARDUINO--------------------------------------------
#:::::::::::::::::::::::::::::::::::::::MODE STATUS::::::::::::::::::::::::::::::::::::::::::::::::::

    if check_measure and values['-mode-'] == 'Calibration':       #check for mode and measure-bool to only send index-char to Arduino at the switch
        check_measure = False
        ser.write('a'.encode())
    elif not check_measure and values['-mode-'] == 'Measure':
        check_measure = True
        ser.write('b'.encode())

#:::::::::::::::::::::::::::::::::::::::::SENSORS::::::::::::::::::::::::::::::::::::::::::::::::::::

    check_sensor = values['-sensor-']
    
    if(check_sensor == 'Auger LH/RH' and check_sensor_before != check_sensor):      #detect sensor-switch (combobox)
        #update auger-time
        t_auger = time()
        #Reset control buttons and bools for CSV-Logging
        check_logging = False
        window.read(False)
        window['Start'].update(disabled=False)
        window['Stop'].update(disabled=True)
        window['Save'].update(disabled=True)

        #close running log-files from previous sensors
        if(check_csv):
            f.close()

        check_sensor_before = check_sensor
        ser.write('c'.encode())

    elif(check_sensor == 'Tamper' and check_sensor_before != check_sensor):
        t_tamper = time()
        #Reset control buttons and bools for CSV-Logging
        check_logging = False
        window.read(False)
        window['Start'].update(disabled=False)
        window['Stop'].update(disabled=True)
        window['Save'].update(disabled=True)
        
        #close running log-files from previous sensors
        if(check_csv):
            f.close()

        check_sensor_before = check_sensor
        ser.write('d'.encode())            
    elif(check_sensor == 'Vibration' and check_sensor_before != check_sensor):
        t_vibration = time()
        #Reset control buttons and bools for CSV-Logging
        check_logging = False
        window.read(False)
        window['Start'].update(disabled=False)
        window['Stop'].update(disabled=True)
        window['Save'].update(disabled=True)
        
        #close running log-files from previous sensors
        if(check_csv):
            f.close()

        check_sensor_before = check_sensor
        ser.write('e'.encode())
    elif(check_sensor == 'Fan Speed' and check_sensor_before != check_sensor):
        t_fan = time()
        #Reset control buttons and bools for CSV-Logging
        check_logging = False
        window.read(False)
        window['Start'].update(disabled=False)
        window['Stop'].update(disabled=True)
        window['Save'].update(disabled=True)
        
        #close running log-files from previous sensors
        if(check_csv):
            f.close()

        check_sensor_before = check_sensor
        ser.write('f'.encode())
    elif(check_sensor == 'Fumes' and check_sensor_before != check_sensor):
        t_fumes = time()
        #Reset control buttons and bools for CSV-Logging
        check_logging = False
        window.read(False)
        window['Start'].update(disabled=False)
        window['Stop'].update(disabled=True)
        window['Save'].update(disabled=True)
        
        #close running log-files from previous sensors
        if(check_csv):
            f.close()

        check_sensor_before = check_sensor
        ser.write('g'.encode())

#------------------------------------RECEIVE DATA FROM ARDUINO--------------------------------------------
#::::::::::::::::::::::::::::::::::::RECEIVE AND PRINT TO GUI:::::::::::::::::::::::::::::::::::::::::::::

    try:
        input = ser.readline().decode('utf-8').rstrip()     #read key from Arduino (only in use for Auger-Measurement)
    except:
        input = ' '

    if(input == '-input1-'):
        try:
            input1 = ser.readline().decode()
            window['-input1-'].update(int(input1))
        except:
            input = ' '
    elif(input == '-input2-'):
        try:
            input2 = ser.readline().decode()
            window['-input2-'].update(int(input2))
        except:
            input = ' '

#:::::::::::::::::::::::::::::::::::::::::SAVE TO CSV-FILE:::::::::::::::::::::::::::::::::::::::::::::

    #Check, which sensor is selected for CSV-file and if logging is active
    if(check_sensor == 'Auger LH/RH' and time()>(t+0.4) and check_logging):    #update csv-values every 0.5 seconds  
        t_data_file = round(time()-t_log, 1) #time-coordinate 
        t_data = round(time(), 1) #time-coordinate                       
        data = [int(input1), int(input2), t_data_file]                              #define data.list       
        writer.writerow(data)                                                  #write the data

        #plot data
        if check_plot: 
            plot(t_data, input1)

        #Update time variable
        t = time()
    elif(check_sensor == 'Auger LH/RH' and time()>(t+0.4) and not check_logging):    #update csv-values every 0.5 seconds (0.4, since program cycle need just under 0.4 seconds --> 1s)  
        t_data = round(time(), 1) #time-coordinate 

        #plot data
        if check_plot: 
            plot(t_data, input1)
        #Update time variable
        t = time()

    elif(check_sensor == 'Tamper' and time()>(t+0.4) and check_logging):
        t_data_file = round(time()-t_log, 1) #time-coordinate 
        t_data = round(time()-t_log, 1)                             
        data = [int(input1), t_data_file]                             
        writer.writerow(data)

        #plot data
        if check_plot: 
            plot(t_data, input1)

        t = time()
    elif(check_sensor == 'Tamper' and time()>(t+0.4) and not check_logging):    #update csv-values every 0.5 seconds  
        t_data = round(time(), 1) #time-coordinate 

        #plot data
        if check_plot: 
            plot(t_data, input1)
        #Update time variable
        t = time()

    elif(check_sensor == 'Vibration' and time()>(t+0.4) and check_logging):
        t_data_file = round(time()-t_log, 1) #time-coordinate 
        t_data = round(time()-t_log, 1)                             
        data = [int(input1), t_data_file]                 
        writer.writerow(data)    

        #plot data
        if check_plot: 
            plot(t_data, input1)

        t = time()
    elif(check_sensor == 'Vibration' and time()>(t+0.4) and not check_logging):    #update csv-values every 0.5 seconds  
        t_data = round(time(), 1) #time-coordinate 

        #plot data
        if check_plot: 
            plot(t_data, input1)
        #Update time variable
        t = time()

    elif(check_sensor == 'Fan Speed' and time()>(t+0.4) and check_logging): 
        t_data_file = round(time()-t_log, 1) #time-coordinate
        t_data = round(time()-t_log, 1)                           
        data = [int(input1), t_data_file]                 
        writer.writerow(data) 

        #plot data
        if check_plot: 
            plot(t_data, input1)

        t = time()
    elif(check_sensor == 'Fan Speed' and time()>(t+0.4) and not check_logging):    #update csv-values every 0.5 seconds  
        t_data = round(time(), 1) #time-coordinate 

        #plot data
        if check_plot: 
            plot(t_data, input1)
        #Update time variable
        t = time()

    elif(check_sensor == 'Fumes' and time()>(t+0.4) and check_logging):
        t_data_file = round(time()-t_log, 1) #time-coordinate 
        t_data = round(time()-t_log, 1)                           
        data = [int(input1), t_data_file]              
        writer.writerow(data) 

        #plot data
        if check_plot: 
            plot(t_data, input1)
                                                                
        t = time()
    elif(check_sensor == 'Fumes' and time()>(t+0.4) and not check_logging):    #update csv-values every 0.5 seconds  
        t_data = round(time(), 1) #time-coordinate 

        #plot data
        if check_plot: 
            plot(t_data, input1)
        #Update time variable
        t = time()
    
window.close()

` enter image description here

I tried to remove x- and y-label as well as the plot title, to make sure, that there is no problem with them. The weird caption value is still printed.

Any idea what could cause this?

Thanks for your support :)

0 Answers0