-2

I have a GUI with live graph reading serial data working pretty good for my amateur skills, but could someone explain to me how to get rid of this error?

File "C:\Users\222\Desktop\V25 Live graph.py", line 200, in measure

cnt=cnt+1

UnboundLocalError: local variable 'cnt' referenced before assignment

Everything I try messes up my whole project. Thanks guys for any advice,code below.

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import tkinter as tk
import time
import serial
from tkinter import *
from tkinter import ttk
import numpy  # Import numpy
import pandas as pd
import numpy as np
import sys
import matplotlib.pyplot as plt #import matplotlib library
from drawnow import *


arduinoData = serial.Serial('com15', 115200) #Creating our serial object named arduinoData

plt.ion()                                    #Tell matplotlib you want interactive mode to plot live data
cnt=0
style.use("ggplot")                          #ggplot...dark_background

tempF= []



# Main Tkinter application
class Application(Frame):

            # Init the variables & start measurements
        def __init__(self, master=None):
                Frame.__init__(self, master)
                root.title( "Stylibleue Dashboard")
                root.state('zoomed')       # This makes full screen on a windows machines

                self.grid(row=0, column=0, sticky="nsew")
                self.grid_rowconfigure(0, weight=1)
                self.grid_columnconfigure(0, weight=3)
                self.columnconfigure(1, weight=3)
                self.columnconfigure(2, weight=3)
                self.columnconfigure(3, weight=3)
                self.columnconfigure(4, weight=3)

                self.B11 = StringVar()
                self.B2 = StringVar()

                self.createWidgets()
                self.pack()
                self.measure()


            # Create display elements
        def createWidgets(self):

                self.temperature = Label(self, text="", font=('Verdana', 20)).grid(row=5, column=0,padx=100,pady=200)
                self.temperature = Label(self, text="", font=('Verdana', 20)).grid(row=5, column=1,padx=100)
                self.temperature = Label(self, text="", font=('Verdana', 20)).grid(row=5, column=2,padx=100)
                self.temperature = Label(self, text="", font=('Verdana', 20)).grid(row=5, column=3,padx=100)
                self.temperature = Label(self, text="", font=('Verdana', 20)).grid(row=5, column=4,padx=100)
                self.temperature = Label(self, text="", font=('Verdana', 20)).grid(row=5, column=5,padx=100)


                ttk.Button(self, text='Graph', command=self.makeFig).grid(row=2, column=5, sticky=E, pady=50)



                ttk.Separator(self,orient=HORIZONTAL).grid(row=1, columnspan=6, sticky="ew")


                self.temperature = Label(self, text="Bassin 2 :", font=('Verdana', 20)).grid(row=2, column=0, sticky= W ,columnspan=2)

                self.temperature = Label(self, text="DO :", font=('Verdana', 20)).grid(row=2, column=1, sticky="nsew")

                self.temperature = Label(self, text="TEMP :", font=('Verdana', 20)).grid(row=2, column=3, sticky="nsew")



        def makeFig(self):

            plt.title('My Live Streaming Sensor Data')      #Plot the title
            plt.grid(True)                                  #Turn the grid on
            plt.ylabel('Temp F')                            #Set ylabels
            plt.plot(tempF, label='Degrees F')              #plot the temperature
            plt.legend(loc='upper left')                    #plot the legend




    # Read the incoming serial data and display it
        def measure(self):

                if(arduinoData.inWaiting()>0):

                        data = arduinoData.readline()

                        data =str(data,'utf-8')                         #removes the surrounding rubbish

                        self.B11.set(str(data))
                        self.temperature = Label(self, textvariable=self.B11, font=('Verdana', 20)).grid(row=2, column=4, sticky="nsew")

                        self.B2.set(str(data))
                        self.temperature = Label(self, textvariable=self.B2, font=('Verdana', 20)).grid(row=2, column=2, sticky="nsew")

                        tempF.append(data)                              #Build our tempF array by appending temp readings

                        print(data)                 

        # Wait 1 second between each measurement
                self.after(1000,self.measure)

                arduinoData.flushOutput()
                arduinoData.flushInput()

                drawnow(self.makeFig)                           #Call drawnow to update our live graph
                plt.pause(.000001)                              #Pause Briefly. Important to keep drawnow from crashing
                cnt=cnt+1
                if(cnt>5000):                                   #If you have 50 or more points, delete the first one from the array
                     tempF.pop(0)                               #This allows us to just see the last 50 data points


# Create and run the GUI
root = Tk()
app = Application(master=root)
app.mainloop()
FlyingTeller
  • 17,638
  • 3
  • 38
  • 53
Ll N
  • 19
  • 5

1 Answers1

0

Your python interpreter is looking for the cnt variable on the local scope, which happens because of the assignment to it. Consider this example, which shows the same behaviour:

c = 0
def foo():
    c=c+1
foo()
Traceback (most recent call last):
  File "C:\...\miniconda3\envs\py36\lib\site-packages\IPython\core\interactiveshell.py", line 2963, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-4-c19b6d9633cf>", line 1, in <module>
    foo()
  File "<ipython-input-3-454c342b701e>", line 2, in foo
    c=c+1
UnboundLocalError: local variable 'c' referenced before assignment

Now if you were to write instead

c=0
def foo():
    d=c+1
foo()

There will be no error. In order to convince your interpreter to use the global variable instead of searching for it on the local scope, use the global keyword:

c=0
def foo():
    global c
    c = c+1
foo()
print(c)
Out[11]: 1
FlyingTeller
  • 17,638
  • 3
  • 38
  • 53
  • Cheers pal solved it. Thanks for the quick response. Onward. – Ll N Jul 30 '18 at 06:26
  • @LlN If this answer solved your problem, [please consider accepting it](https://stackoverflow.com/help/accepted-answer) – Mr. T Jul 30 '18 at 06:54
  • Wouldn't it make more sense to make `cnt` an instance variable of the `Application` class than to use a global variable? – fhdrsdg Jul 30 '18 at 08:39