0

I am currently trying to create a live graph on a window using Tkinter and Matplotlib. The data from this graph is continuously appended onto a CSV file and saved like this example row:

06/09/2020 19:57:53,4,2.549,3.546

Where the second column is the second, and the 3 and 4th columns are voltage data I am trying to plot with respect to time. I have a separate python script that's continuously appending to this CSV, so it's very large and there are a lot of data points. Because of that, my graph became really messy after a while (see image below) and I want to limit the data to points from the last 60 seconds and have the x-axis ticks more spaced out instead of at every data point. I also want to zoom out of the graph a bit so the noise doesn't seem as obvious (from 0 to 5 V, for example). I tried adding plot1.xlim(t-60, t), plot2.xlim(t-60, t), plot1.ylim(0,5), plot2.ylim(0,5) but none of those set the limit as I wanted. It just zoomed into a really weird section of the graph, cutting out a big portion of the plot vertically. How should I configure my plot so that the y-axis goes from 0 to 5 and the x-axis shows the most recent 60 second worth of data? I am new to Tkinter and I would really appreciate any help. Thank you!!!

Picture of my screen with really messy axis:

My code:

#import tkinter for GUI
import tkinter as tk
from tkinter import ttk
#font types
LARGE_FONT = ("Verdana", 12)

#import stuff for graph
import matplotlib
import matplotlib.ticker as mticker
from matplotlib import pyplot as plt
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure

#import animation to make graph live
import matplotlib.animation as animation
from matplotlib import style
style.use("seaborn-darkgrid")
#animate function
f = Figure(figsize=(20,20), dpi=100)
plot1 = f.add_subplot(211)
plot2 = f.add_subplot(212)
def animate(ii):
    pullData = open("/media/pi/68D2-7E93/test2.csv","r").read()
    dataList = pullData.split('\n')
    tList = []
    vList = []
    v1List = []
    for eachLine in dataList:
        if len(eachLine) >1:
            timedate, t, voltage, voltage1 = eachLine.split(',')
            tList.append(t)
            vList.append(voltage)
            v1List.append(voltage1)

    #plot graphs
    plot1.clear()
    plot1.plot(tList, vList, 'r')
    plot2.clear()
    plot2.plot(tList, v1List, 'b')
    #add labels and config axis
    plot1.set_title("Aquaponic Sensors")
    plot1.set_autoscaley_on(False)
    plot1.set_autoscalex_on(False)
    plot1.set_ylabel("pH (v)")
    #plot1.set_xlim(t-60,t)
    #plot1.axes.set_ybound(0,1)
    #plot1.set_ylim(2,4)
    #plot1.set_xlim(500, 510)

    plot2.set_ylabel("Temperature (v)")
    plot2.set_xlabel("Time (s)")
    #plot2.set_ybound(0,5)



#initialization
class AllWindow(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        #add title
        tk.Tk.wm_title(self, "NU Aquaponics")

        container = tk.Frame(self)      
        container.pack(side="top", fill="both", expand=True)      
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)      
        #show the frames
        self.frames = {}
        for F in (HomePage, ControlPanel, Settings):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(HomePage)

    def show_frame(self, cont):       
        frame = self.frames[cont]
        frame.tkraise()


#add home page
class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Dashboard", font = LARGE_FONT)
        label.pack(pady=10, padx=10)

        #quit button
        quitButton = tk.Button(self, text="QUIT", fg='red',
                                command=quit)
        quitButton.pack()
        #navigation button
        navibutton1 = ttk.Button(self, text="Control Panel",
                            command=lambda: controller.show_frame(ControlPanel))
        navibutton1.pack()
        navibutton2 = ttk.Button(self, text="Settings",
                            command=lambda: controller.show_frame(Settings))
        navibutton2.pack()

        #add graph to dashboard

        #bring up canvas
        canvas = FigureCanvasTkAgg(f, self)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand = True)
        #add navigation bar
        toolbar = NavigationToolbar2Tk(canvas, self)
        toolbar.update()
        canvas._tkcanvas.pack()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand = True)


#add control panel page
class ControlPanel(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Control Panel", font = LARGE_FONT)
        label.pack(pady=10, padx=10)

        #control buttons
        self.lightButton = tk.Button(self,
                             text="Light OFF",
                             bg= "red",
                             command=self.toggle_light)
        self.lightButton.pack()

        #navigation button
        navibutton1 = ttk.Button(self, text="Back to Dashboard",
                            command=lambda: controller.show_frame(HomePage))
        navibutton1.pack()
        navibutton2 = ttk.Button(self, text="Settings",
                            command=lambda: controller.show_frame(Settings))
        navibutton2.pack()

        #fcns triggered by control button
        #fcn to turn LED on or off
    def toggle_light(self):
      #  if LED1.value == 0:
     #       LED1.value = 1
        #change light button color
            self.lightButton.configure(bg= "green")
            self.lightButton.configure(fg= "white")
            self.lightButton.configure(text = "Light ON")
        else:
      #      LED1.value = 0
        #change light button color to red if light off
            self.lightButton.configure(bg= "red")
            self.lightButton.configure(text = "Light OFF")
#add settings page
class Settings(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Settings", font = LARGE_FONT)
        label.pack(pady=10, padx=10)
        #navigation button
        navibutton1 = ttk.Button(self, text="Back to Dashboard",
                            command=lambda: controller.show_frame(HomePage))
        navibutton1.pack()
        navibutton2 = ttk.Button(self, text="Go to Control Panel",
                            command=lambda: controller.show_frame(ControlPanel))
        navibutton2.pack()

app = AllWindow()
app.geometry('1025x690')
#update animation first
ani = animation.FuncAnimation(f, animate, interval=1000)
app.mainloop()

This is what happens if I uncomment plot1.set_ylim(2,4) lines, am I misunderstanding what set_ylim does? It seems like it's just changing the number of ticks that's shown instead of zooming out and setting the highest and lowest ticks see image here

1 Answer 1

1

Reading from a CSV file will give you strings, by default. To fix your code, you have to pass in the data as floats, as such:

    tList = []
    vList = []
    v1List = []
    for eachLine in dataList:
        if len(eachLine) >1:
            timedate, t, voltage, voltage1 = eachLine.split(',')
            tList.append(float(t))
            vList.append(float(voltage))
            v1List.append(float(voltage1))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.