Python Forum

Full Version: How to solve AttributeError
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am using line chart in tkinter.

First i create button event, then generate number graph & updating graph & working fine.

Now change program & receiving serial data in event & updating line chart.

now error appearing

"AttributeError"

& no lines are drawing on chart.

How to solve this error.

        if (len(data) < 100):
            data = np.append(data, float(dataList[1]))
        else:
            data[0:99] = data[1:100]
            data[99] = float(r1)
        lines.set_xdata(np.arange(0, len(data)))
        lines.set_ydata(dataList[1])
        canvas.draw()
same code is working in button event but not working in serial data event.

Need help.
Quote:now error appearing "AttributeError"
Please show error traceback, complete and unaltered
Output:
C:\Users\ROSHAN\AppData\Local\Programs\Python\Python35-32\python.exe "D:/Python/python serial/serialPortMarch2021.py" Error reading COM port: <class 'AttributeError'> Error reading COM port: <class 'AttributeError'> Error reading COM port: <class 'AttributeError'> Error reading COM port: <class 'AttributeError'> Error reading COM port: <class 'AttributeError'> Error reading COM port: <class 'AttributeError'> Error reading COM port: <class 'AttributeError'>
every second i am receiving data then error appears.
when i remove chart plotting code then no error.
Thanks
Ths error occurs when you read the serial port, not when you plot. This part of the error message gives it away "Error reading COM port:". If you need help finding the error post the code that reads the serial port..
Here is the code.
I have removed my other logging code & now error changes to
Output:
C:\Python\python.exe C:/Users/ROSHAN/PycharmProjects/untitled/serialPortMarch.py Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'> Error reading COM port: <class 'NameError'>
code divided in 2 files.
main file has tkinter code &

another file has serial port related code(named serial_rx_tx.py)

data receiving from serial port updating on label successfully.
both code here

main code file
import tkinter as tk
from tkinter import *
import serial
from tkinter import messagebox
from tkinter import ttk
import serial.tools.list_ports as port_list
import serial_rx_tx
import _thread
import time
import webbrowser
from tkinter import messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
import os.path
from datetime import datetime, date
import csv

# globals
serialPort = serial_rx_tx.SerialPort()
fileName = "data.csv"
data = np.array([])
# globaal array variable to hold numbewr of port
portList = []
dataList = []
stringEmpty = StringVar
selectedPort = StringVar
dataToBeWrite = StringVar
file = StringVar
root = tk.Tk();
root.title("My Serial Port")
root.geometry("800x520")

# init graph
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)

ax.set_title("Temperature Data Logger")
ax.set_xlabel("Time in Second")
ax.set_ylabel("Temperature In Degree")
ax.set_xlim(0, 60)
ax.set_ylim(0, 100)
lines = ax.plot([], [])[0]
data = np.array([])
ax.set_axisbelow(True)
ax.minorticks_on()
ax.grid(linestyle='-', linewidth='0.5', color='gray')
# Customize the major grid
ax.grid(which='major', linestyle='-', linewidth='0.5', color='black')
# Customize the minor grid
ax.grid(which='minor', linestyle=':', linewidth='0.5', color='gray')

canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().place(x=10, y=10, width=750, height=400)
canvas.draw()


# serial data callback function
def OnReceiveSerialData(message):
    global data
    global str_message
    global dataList
    global fileName
    global current_datetime
    global r1
    str_message = message.decode("utf-8")
    dataLabel1.config(text=str_message)
    dataList = str_message.split(",")

    if (len(dataList) > 1):
        if (len(data) < 100):
            data = np.append(data, float(r1))
        else:
            data[0:99] = data[1:100]
            data[99] = float(r1)
        lines.set_xdata(np.arange(0, len(data)))
        lines.set_ydata(data)
        canvas.draw()


# Register the callback above with the serial port object
serialPort.RegisterReceiveCallback(OnReceiveSerialData)


def sdterm_main():
    root.after(200, sdterm_main)  # run the main loop once each 200 ms


def openPort():
    global comport
    global baudrate
    if connectPort.cget("text") == 'Connect':
        comport = "COM3"
        baudrate = 9600
        selectedPort = comboBox.get().split("-")
        # print(" my poorrt:",selectedPort[0])
        serialPort.Open(selectedPort[0], baudrate)
        comboBox.config(state='disabled')
        connectPort.config(text='Disconnect')

    else:
        serialPort.Close()
        connectPort.config(text='Connect')


comboBox = ttk.Combobox(root, value=portList, font=("Helvetica 16"))
comboBox.place(x=450, y=450)

connectPort = Button(root, text="Connect", width=10, font=("Helvetica 16 bold"), command=openPort)
connectPort.place(x=300, y=450)

dataLabel1 = Label(text="Rx Data-1:", font=("Helvetica 12"))
dataLabel1.place(x=10, y=450)

# get list of available com ports
portList = list(port_list.comports())
# yupdate list of available comport in combobox
comboBox['value'] = portList
comboBox.set(portList[0])
root.after(200, sdterm_main)
root.mainloop()
here is file serial_rx_tx.py code
#
# Serial COM Port receive message event handler
# When a line of text arrives from the COM port terminated by a \n character, this module will pass the message to
# the function specified by the instantiator of this class.
#
import serial
import sys
import _thread

class SerialPort:
    def __init__(self):
        self.comportName = ""
        self.baud = 0
        self.timeout = None
        self.ReceiveCallback = None
        self.isopen = False
        self.receivedMessage = None
        self.serialport = serial.Serial()

    def __del__(self):
        try:
            if self.serialport.is_open():
                self.serialport.close()
        except:
            print("Destructor error closing COM port: ", sys.exc_info()[0] )

    def RegisterReceiveCallback(self,aReceiveCallback):
        self.ReceiveCallback = aReceiveCallback
        try:
            _thread.start_new_thread(self.SerialReadlineThread, ())
        except:
            print("Error starting Read thread: ", sys.exc_info()[0])

    def SerialReadlineThread(self):
        while True:
            try:
                if self.isopen:
                    self.receivedMessage = self.serialport.readline()
                    if self.receivedMessage != "":
                        self.ReceiveCallback(self.receivedMessage)
            except:
                print("Error reading COM port: ", sys.exc_info()[0])

    def IsOpen(self):
        return self.isopen

    def Open(self,portname,baudrate):
        if not self.isopen:
            # serialPort = 'portname', baudrate, bytesize = 8, parity = 'N', stopbits = 1, timeout = None, xonxoff = 0, rtscts = 0)
            self.serialport.port = portname
            self.serialport.baudrate = baudrate
            try:
                self.serialport.open()
                self.isopen = True
            except:
                print("Error opening COM port: ", sys.exc_info()[0])


    def Close(self):
        if self.isopen:
            try:
                self.serialport.close()
                self.isopen = False
            except:
                print("Close error closing COM port: ", sys.exc_info()[0])

    def Send(self,message):
        if self.isopen:
            try:
                # Ensure that the end of the message has both \r and \n, not just one or the other
                newmessage = message.strip()
                newmessage += '\r\n'
                self.serialport.write(newmessage.encode('utf-8'))
            except:
                print("Error sending message: ", sys.exc_info()[0] )
            else:
                return True
        else:
            return False
It would be helpful to temporarily remove the exception handler in SerialReadlineThread().