带GUI的通信循环

时间:2016-10-05 11:01:56

标签: python tkinter arduino pyserial raspberry-pi3

我正在为机器制作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()

2 个答案:

答案 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