python - 使用 TKinter python 的串行监视器不起作用
问题描述
import self
import serial
import time
import collections
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import struct
import copy
from matplotlib.backends.backend_tkagg import FigureCanvasTk, NavigationToolbar2Tk
import tkinter as Tk
from tkinter.ttk import Frame
import pandas as pd
class serialPlot:
def __init__(self, serialPort='COM12', serialBaud=9600, plotLength=100, dataNumBytes=2, numPlots=1):
self.port = serialPort
self.baud = serialBaud
self.plotMaxLength = plotLength
self.dataNumBytes = dataNumBytes
self.numPlots = numPlots
self.rawData = bytearray(numPlots * dataNumBytes)
self.dataType = None
if dataNumBytes == 2:
self.dataType = 'h' # 2 byte integer
elif dataNumBytes == 4:
self.dataType = 'f' # 4 byte float
self.data = []
for me in range(numPlots): # give an array for each type of data and store them in a list
self.data.append(collections.deque([0] * plotLength, maxlen=plotLength))
self.isRun = True
self.isReceiving = False
self.thread = None
self.plotTimer = 0
self.previousTimer = 0
# self.csvData = []
print('Trying to connect to: ' + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
try:
self.serialConnection = serial.Serial(serialPort, serialBaud, timeout=4)
print('Connected to ' + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
except:
print("Failed to connect wif " + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
def readSerialStart(self):
if self.thread is None:
self.thread = Thread(target=self.backgroundThread)
self.thread.start()
# Block till we start receiving values
while not self.isReceiving:
time.sleep(0.1)
def getSerialData(self, frame, lines, lineValueText, lineLabel, timeText):
currentTimer = time.clock()
self.plotTimer = int((currentTimer - self.previousTimer) * 1000) # teh first reading will be erroneous
self.previousTimer = currentTimer
timeText.set_text('Plot Interval = ' + str(self.plotTimer) + 'ms')
privateData = copy.deepcopy(
self.rawData[:]) # so dat teh 3 values in our plots will be synchronized to teh same sample time
for me in range(self.numPlots):
data = privateData[(me * self.dataNumBytes):(self.dataNumBytes + me * self.dataNumBytes)]
value, = struct.unpack(self.dataType, data)
self.data[me].append(value) # we get teh latest data point and append it to our array
lines[me].set_data(range(self.plotMaxLength), self.data[me])
lineValueText[me].set_text('[' + lineLabel[me] + '] = ' + str(value))
# self.csvData.append([self.data[0][-1], self.data[1][-1], self.data[2][-1]])
def backgroundThread(self): # retrieve data
time.sleep(1.0) # give some buffer time for retrieving data
self.serialConnection.reset_input_buffer()
while self.isRun:
self.serialConnection.readinto(self.rawData)
self.isReceiving = True
# print(self.rawData)
def sendSerialData(self, data):
self.serialConnection.write(data.encode('utf-8'))
def close(self):
self.isRun = False
self.thread.join()
self.serialConnection.close()
print('Disconnected...')
# df = pd.DataFrame(self.csvData)
# df.to_csv('/home/rikisenia/Desktop/data.csv')
class Window(Frame):
def __init__(self, figure, master, SerialReference):
Frame.__init__(self, master)
self.entry = None
self.setPoint = None
self.master = master # a reference to teh master window
self.serialReference = SerialReference # keep a reference to our serial connection so dat we can use it for bi-directional communicate from this class
self.initWindow(figure) # initialize teh window wif our settings
def initWindow(self, figure):
self.master.title("Real Time Plot")
canvas = FigureCanvasTk(figure, master=self.master)
toolbar = NavigationToolbar2Tk(canvas, self.master)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
# create out widgets in teh master frame
lbl1 = Tk.Label(self.master, text="Scaling Factor")
lbl1.pack(padx=5, pady=5)
self.entry = Tk.Entry(self.master)
self.entry.insert(0, '1.0') # (index, string)
self.entry.pack(padx=5)
SendButton = Tk.Button(self.master, text='Send', command=self.sendFactorToMCU)
SendButton.pack(padx=5)
def sendFactorToMCU(self):
self.serialReference.sendSerialData(self.entry.get() + '%') # '%' is our ending marker
def main():
# portName = 'COM5'
portName = 'COM12'
baudRate = 9600
maxPlotLength = 100 # number of points in x-axis of real time plot
dataNumBytes = 4 # number of bytes of 1 data point
numPlots = 3 # number of plots in 1 graph
s = serialPlot(portName, baudRate, maxPlotLength, dataNumBytes, numPlots) # initializes all required variables
s.readSerialStart() # starts background thread
# plotting starts below
pltInterval = 50 # Period at which teh plot animation updates [ms]
xmin = 0
xmax = maxPlotLength
ymin = -1
ymax = 1
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(xlim=(xmin, xmax), ylim=(float(ymin - (ymax - ymin) / 10), float(ymax + (ymax - ymin) / 10)))
ax.set_title('Arduino Accelerometer')
ax.set_xlabel("Time")
ax.set_ylabel("Accelerometer Output")
# put our plot onto Tkinter's GUI
root = Tk.Tk()
app = Window(fig, root, s)
lineLabel = ['X', 'Y', 'Z']
style = ['r-', 'c-', 'b-'] # linestyles for teh different plots
timeText = ax.text(0.70, 0.95, '', transform=ax.transAxes)
lines = []
lineValueText = []
for me in range(numPlots):
lines.append(ax.plot([], [], style[me], label=lineLabel[me])[0])
lineValueText.append(ax.text(0.70, 0.90 - me * 0.05, '', transform=ax.transAxes))
anim = animation.FuncAnimation(fig, s.getSerialData, fargs=(lines, lineValueText, lineLabel, timeText),
interval=pltInterval) # fargs has to be a tuple
# plt.legend(loc="upper left")
root.mainloop() # use this instead of plt.show() since we are encapsulating everything in Tkinter
s.close()
if __name__ == '__main__':
main()
基本上我想从 Arduino 串行数据中绘制一个图表,还使用串行监视器将数据发送回 Arduino 以控制电机转速。
在进行一些更改后,我从https://thepoorengineer.com/en/python-gui/找到了这段代码, 连接是使用串行端口创建的,但 Tkinter 没有显示,请帮助我完成这项工作
解决方案
你曾经退出 readSerialStart() 吗?您可以打印从串行端口返回的任何内容吗?
推荐阅读
- r - 使用标头参数时的Openxlsx问题
- python - PCA 散点图上的轴是什么?
- npm - GitHub 操作:将 vue-cli-service 构建的输出部署到 Azure 应用服务
- vue.js - 为什么 Vuetify Autocomplete 不选择正在设置的数据?
- reactjs - 在应用启动时在后台初始化/急切加载 React 组件以供以后使用
- node.js - 如何在 Node JS 中使用 Google Maps Circle、Rectangle 和 Polygon?
- qt - 当 QML 滚动条位于底部并且窗口高度被调整大小时,它不会更新
- java - JTabbedPane 直到我最小化窗口才显示
- javascript - Promise allSettled 不是函数
- tracking - 如何跟踪和展示网络流量的载体?