我正在为机器制作Python的GUI。我的python程序在Raspberry Pi 3上运行,它通过串口与Arduino UNO进行通信。
我制定了一个协议; arduino发送" 1"。树莓知道" 1"代表Run / Stop,并返回RunStop变量的值(0或1)。之后,arduino发送了一个" 2"。树莓派知道它代表速度值,并发回速度变量(介于1和4之间)。
我已经制作了以下两个有效的程序,但我不知道如何在GUI中实现它。因为当我在 root.mainloop()之前添加它时,GUI不会启动。当我把它放在后面时,while循环永远不会启动。
Arduino代码:
int RunStop, Speed = 0;
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop() {
Serial.write(1);
delay(2000);
RunStop = Serial.read();
if (RunStop == 1) {
digitalWrite(13, HIGH);
} else {
digitalWrite(13, LOW);
}
delay(2000);
Serial.write(2);
delay(2000);
Speed = Serial.read();
if (Speed == 3) {
digitalWrite(12, HIGH);
} else {
digitalWrite(12, LOW);
}
delay(2000);
}
Python通信代码:
import time
import serial
# configure the serial connections (the parameters differs on the device you are connecting to)
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate=9600,
)
ser.isOpen()
##Status variabelen
RunStop = b'\x01'
Speed = b'\x03'
while 1:
uartIn = ser.read()
print (uartIn)
time.sleep(1)
if uartIn == b'\x01':
ser.write(RunStop)
print ("Run/Stop Register")
elif uartIn == b'\x02':
ser.write(Speed)
print ("Speed Register")
else:
print ("No Register Requested")
GUI代码:
from tkinter import *
import time
import serial
# configure the serial connections (the parameters differs on the device you are connecting to)
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate=9600,
parity=serial.PARITY_ODD,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
ser.isOpen()
root = Tk()
root.title("Cutter")
## Layout
label_1 = Label(root, text="Pieces")
label_2 = Label(root, text="Length")
entry_1 = Entry(root, width=9)
entry_2 = Entry(root, width=9)
label_1.grid(row=3, sticky=W, padx=(10))
label_2.grid(row=4, sticky=W, padx=(10))
entry_1.grid(row=3, column=1, pady=(10,10))
entry_2.grid(row=4, column=1, pady=(10,15))
runStop = b'\x00'
Speed = b'\x01'
Pieces = b'\x00'
Length = b'\x00'
##pieces OK button function
def piecesOKphase():
x = entry_1.get()
print("pieces: " + x)
##length OK button function
def lengthOKphase():
x = entry_2.get()
print("length: " + x)
def runPhase():
global runStop
runStop = b'\x01'
def stopPhase():
global runStop
runStop = b'\x00'
#OK and RUN / STOP buttons
piecesOK = Button(root, text="OK", command=piecesOKphase)
piecesOK.grid(row=3, column=2)
lengthOK = Button(root, text="OK", command=lengthOKphase)
lengthOK.grid(row=4, column=2)
runButton = Button(root, text="Run", width=6, bg='#58FA58', command=runPhase)
stopButton = Button(root, text="Stop", width=6, bg='#FA5858', command=stopPhase)
runButton.grid(row=0, column=0,padx=(10,10), pady=(10,10))
stopButton.grid(row=0, column=2)
##speed container
CurrentSpeed = 1
def delSpeed():
global CurrentSpeed
global speedLabel
if CurrentSpeed > 1:
CurrentSpeed -= 1
speedLabel.config(text=str(CurrentSpeed))
speedLabel.config(text=CurrentSpeed)
else:
pass
def addSpeed():
global CurrentSpeed
if CurrentSpeed < 4:
CurrentSpeed += 1
speedLabel.config(text=CurrentSpeed)
else:
pass
speedMin = Button(root, text="Speed -", width=6, command=delSpeed)
speedLabel = Label(root, text=CurrentSpeed, font=20)
speedLabel.grid(row=1, column=1, padx=(10))
speedPlus = Button(root, text="Speed +", width=6, command=addSpeed)
speedMin.grid(row=1, column=0)
speedPlus.grid(row=1, column=2)
#Number keyboard functions
def B1phase():
try:
root.focus_get().insert(END, "1")
except AttributeError:
pass
def B2phase():
try:
root.focus_get().insert(END, "2")
except AttributeError:
pass
def B3phase():
try:
root.focus_get().insert(END, "3")
except AttributeError:
pass
def B4phase():
try:
root.focus_get().insert(END, "4")
except AttributeError:
pass
def B5phase():
try:
root.focus_get().insert(END, "5")
except AttributeError:
pass
def B6phase():
try:
root.focus_get().insert(END, "6")
except AttributeError:
pass
def B7phase():
try:
root.focus_get().insert(END, "7")
except AttributeError:
pass
def B8phase():
try:
root.focus_get().insert(END, "8")
except AttributeError:
pass
def B9phase():
try:
root.focus_get().insert(END, "9")
except AttributeError:
pass
def B0phase():
try:
root.focus_get().insert(END, "0")
except AttributeError:
pass
def clearPhase():
try:
root.focus_get().delete(0, 'end')
except AttributeError:
pass
## Number keyboard buttons
B1 = Button(root, text="1", width=6, command=B1phase)
B2 = Button(root, text="2", width=6, command=B2phase)
B3 = Button(root, text="3", width=6, command=B3phase)
B4 = Button(root, text="4", width=6, command=B4phase)
B5 = Button(root, text="5", width=6, command=B5phase)
B6 = Button(root, text="6", width=6, command=B6phase)
B7 = Button(root, text="7", width=6, command=B7phase)
B8 = Button(root, text="8", width=6, command=B8phase)
B9 = Button(root, text="9", width=6, command=B9phase)
B0 = Button(root, text="0", width=6, command=B0phase)
clearButton = Button(root, text="Clear", width=6, bg='#FA5858', command=clearPhase)
B1.grid(row=5, column=0)
B2.grid(row=5, column=1)
B3.grid(row=5, column=2, padx=(10,10))
B4.grid(row=6, column=0)
B5.grid(row=6, column=1)
B6.grid(row=6, column=2, padx=(10,10))
B7.grid(row=7, column=0)
B8.grid(row=7, column=1)
B9.grid(row=7, column=2, padx=(10,10))
B0.grid(row=8, column=1)
clearButton.grid(row=8, column=0)
## Manual
label_4 = Label(root, text="")
label_4.grid(row=2, sticky=W)
label_3 = Label(root, text="Manual")
label_3.grid(row=9, sticky=W, padx=(10), pady=(10,10))
manualCut = Button(root, text="Cut", width=4)
manualCut.grid(row=10, column=0, pady=(1,15))
manualFeed = Button(root, text="Feed", width=4)
manualFeed.grid(row=10, column=1, pady=(1,15))
# Test function
def testPhase():
print (CurrentSpeed)
manualTest = Button(root, text="Test", width=4, command=testPhase)
manualTest.grid(row=10, column=2, pady=(1,15))
## OTHER
root.mainloop()
修改
我使用过Tkinter的 。
GUI启动,while循环运行。但我无法点击任何按钮。
from tkinter import *
import time
import serial
# configure the serial connections (the parameters differs on the device you are connecting to)
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate=9600,
parity=serial.PARITY_ODD,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
ser.isOpen()
## GUI Title
root = Tk()
root.title("Cutter")
##Communication
RunStop = b'\x01' ## 0 = OFF, 1 = ON
Speed = b'\x03' ## 1, 2, 3, 4
CurrentSpeed = 1
Pieces = b'\x00'
Pieces100 = b'\x00'
Pieces10 = b'\x00'
Pieces1 = b'\x00'
length10000 = b'\x00'
Length1000 = b'\x00'
Length100 = b'\x00'
Length10 = b'\x00'
Length1 = b'\x00'
def Communication():
while 1:
uartIn = ser.read()
print (uartIn)
time.sleep(1)
if uartIn == b'\x01':
ser.write(RunStop)
print ("Run/Stop Register")
elif uartIn == b'\x02':
ser.write(Speed)
print ("Speed Register")
else:
print ("No Register Requested")
root.after(500, Communication)
## Functions
def runBOT():
global RunStop
RunStop = b'\x01'
def stopBOT():
global RunStop
RunStop = b'\x00'
def delSpeedBOT():
global CurrentSpeed
global speedLabel
if CurrentSpeed > 1:
CurrentSpeed -= 1
speedLabel.config(text=str(CurrentSpeed))
speedLabel.config(text=CurrentSpeed)
else:
pass
def addSpeedBOT():
global CurrentSpeed
if CurrentSpeed < 4:
CurrentSpeed += 1
speedLabel.config(text=CurrentSpeed)
else:
pass
def piecesBOT():
x = entryPieces.get()
print("pieces: " + x)
def lengthBOT():
x = entryLength.get()
print("length: " + x)
## Layout
labelPieces = Label(root, text="Pieces")
labelLength = Label(root, text="Length")
entryPieces = Entry(root, width=9)
entryLength = Entry(root, width=9)
labelPieces.grid(row=3, sticky=W, padx=(10))
labelLength.grid(row=4, sticky=W, padx=(10))
entryPieces.grid(row=3, column=1, pady=(10,10))
entryLength.grid(row=4, column=1, pady=(10,15))
## Buttons
runButton = Button(root, text="Run", width=6, bg='#58FA58', command=runBOT)
runButton.grid(row=0, column=0,padx=(10,10), pady=(10,10))
stopButton = Button(root, text="Stop", width=6, bg='#FA5858', command=stopBOT)
stopButton.grid(row=0, column=2)
speedMin = Button(root, text="Speed -", width=6, command=delSpeedBOT)
speedMin.grid(row=1, column=0)
speedLabel = Label(root, text=CurrentSpeed, font=20)
speedLabel.grid(row=1, column=1, padx=(10))
speedPlus = Button(root, text="Speed +", width=6, command=addSpeedBOT)
speedPlus.grid(row=1, column=2)
piecesOK = Button(root, text="OK", command=piecesBOT)
piecesOK.grid(row=3, column=2)
lengthOK = Button(root, text="OK", command=lengthBOT)
lengthOK.grid(row=4, column=2)
#Number keyboard functions
def B1phase():
try:
root.focus_get().insert(END, "1")
except AttributeError:
pass
def B2phase():
try:
root.focus_get().insert(END, "2")
except AttributeError:
pass
def B3phase():
try:
root.focus_get().insert(END, "3")
except AttributeError:
pass
def B4phase():
try:
root.focus_get().insert(END, "4")
except AttributeError:
pass
def B5phase():
try:
root.focus_get().insert(END, "5")
except AttributeError:
pass
def B6phase():
try:
root.focus_get().insert(END, "6")
except AttributeError:
pass
def B7phase():
try:
root.focus_get().insert(END, "7")
except AttributeError:
pass
def B8phase():
try:
root.focus_get().insert(END, "8")
except AttributeError:
pass
def B9phase():
try:
root.focus_get().insert(END, "9")
except AttributeError:
pass
def B0phase():
try:
root.focus_get().insert(END, "0")
except AttributeError:
pass
def clearPhase():
try:
root.focus_get().delete(0, 'end')
except AttributeError:
pass
## Number keyboard buttons
B1 = Button(root, text="1", width=6, command=B1phase)
B2 = Button(root, text="2", width=6, command=B2phase)
B3 = Button(root, text="3", width=6, command=B3phase)
B4 = Button(root, text="4", width=6, command=B4phase)
B5 = Button(root, text="5", width=6, command=B5phase)
B6 = Button(root, text="6", width=6, command=B6phase)
B7 = Button(root, text="7", width=6, command=B7phase)
B8 = Button(root, text="8", width=6, command=B8phase)
B9 = Button(root, text="9", width=6, command=B9phase)
B0 = Button(root, text="0", width=6, command=B0phase)
clearButton = Button(root, text="Clear", width=6, bg='#FA5858', command=clearPhase)
B1.grid(row=5, column=0)
B2.grid(row=5, column=1)
B3.grid(row=5, column=2, padx=(10,10))
B4.grid(row=6, column=0)
B5.grid(row=6, column=1)
B6.grid(row=6, column=2, padx=(10,10))
B7.grid(row=7, column=0)
B8.grid(row=7, column=1)
B9.grid(row=7, column=2, padx=(10,10))
B0.grid(row=8, column=1)
clearButton.grid(row=8, column=0)
## Manual
label_4 = Label(root, text="")
label_4.grid(row=2, sticky=W)
label_3 = Label(root, text="Manual")
label_3.grid(row=9, sticky=W, padx=(10), pady=(10,10))
manualCut = Button(root, text="Cut", width=4)
manualCut.grid(row=10, column=0, pady=(1,15))
manualFeed = Button(root, text="Feed", width=4)
manualFeed.grid(row=10, column=1, pady=(1,15))
# Test function
def testPhase():
pass
manualTest = Button(root, text="Test", width=4, command=testPhase)
manualTest.grid(row=10, column=2, pady=(1,15))
## Running GUI and communication
root.after(500, Communication)
root.mainloop()
这不起作用: 通讯() root.mainloop()
答案 0 :(得分:1)
使用Tkinter .after方法定期调用用于从串口读取数据的代码。
http://effbot.org/tkinterbook/widget.htm
tkinter: how to use after method
Tkinter需要能够处理UI,因此在代码中放置任何循环意味着UI变得无响应。使用.after可以定期安排要运行的任务。
答案 1 :(得分:0)
假设您可以在串行端口上执行非阻塞读取,您可以编写一个读取串行端口的函数,然后安排自己在延迟后再次调用。
例如:
def poll_serial(root):
uartIn = ser.read()
if uartIn:
process_value_from_serial(uartIn)
root.after(1000, poll_serial, root)
在你的主程序中,你在开始mainloop
之前立即调用它,它将在程序的整个生命周期中每秒运行一次。
root = Tk()
...
poll_serial(root)
root.mainloop()
如果调用ser.read()
阻止,您可以将轮询功能修改为 1 :
def poll_serial(root):
if (ser.inWaiting()>0):
uartIn = ser.read()
if uartIn:
process_value_from_serial(uartIn)
root.after(1000, poll_serial, root)
1 在阅读之前检查串口的代码来自这个答案:https://stackoverflow.com/a/38758773/7432