用PySimpleGUI和pyserial輕鬆組建微控制器的上位機控制系統
PySimpleGUI是能輕鬆簡單地建立視覺化應用程式
pyserial串列埠開發模組
PySimpleGUI簡單示例:
import PySimpleGUI as sg
import serial
layout=[
[sg.Text('第一行')],
[sg.Button('第二行')]
]
window=sg.Window('這是個標題').Layout(layout)
button,value=window.Read()
print('button:',button)
print('value:',value)
執行結果如下:
其中layout是個二維陣列,layout[0][0]代表第一行第一列,layout[1][0]代表第二行第一列,以此類推,組成一個佈局。
而且其中的window.Read()會阻塞程式的進行,直到Button('第二行')被點選才退出。
常用的元件:
sg.InputText('Default text') 文字輸入框 sg.InputCombo(['choice 1', 'choice 2']) 下拉列表 sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6)) 列表框元素 sg.Slider(range=(1,500), default_value=222, size=(20,15), orientation='horizontal', font=('Helvetica', 12)) 滑塊元素 sg.Radio('My first Radio!', "RADIO1", default=True) 單選按鈕 sg.Checkbox('My first Checkbox!', default=True) 複選框
框架元件:
sg.Frame('title','layout')-----title=框架標題,layout=元件的佈局
import PySimpleGUI as sg import serial child_layout=[[sg.Text('第一行')],[sg.Text('第二行')]] layout=[ [sg.Text('第一行'),sg.Frame('標題',child_layout)] ] window=sg.Window('這是個標題').Layout(layout) button,value=window.Read() print('button:',button) print('value:',value)
執行結果如下:
配置pyserial:
import serial
ser = serial.Serial()
ser.baudrate = 115200 #波特率
ser.port = 'COM1' #com口
ser.stopbits=1 #停止位 1 1.5 2
ser.bytesize=8 #資料位
ser.parity='N' #奇偶位 N沒有 E偶校驗 O奇校驗
ser.timeout=5 #超時時間
ser.open() #連線失敗會丟擲錯誤
ser.write('hello\n'.encode()) #傳送資訊
result=ser.readline().decode() #接收資訊
print(result)
把PySimpleGUI和pyserial組合起來就可以實現自己定義功能的上位機控制程式了
示例(搭建簡單的ESP8266串列埠除錯助手):
程式碼如下:
import PySimpleGUI as sg
from serial import Serial
from threading import Thread
com=('COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9','COM10')
baud_rate=('115200','9600','38400')
Stop_bit=('1','1.5','2')
data_bit=('8','7','6','5')
verify=('無','奇校驗','偶校驗')
layout1 = [[sg.Text('COM口:'),sg.InputCombo(com,size=(15, 1))],
[sg.Text('波特率:'),sg.InputCombo(baud_rate,size=(15, 1))],
[sg.Text('停止位:'),sg.InputCombo(Stop_bit,size=(15, 1))],
[sg.Text('資料位:'),sg.InputCombo(data_bit,size=(15, 1))],
[sg.Text('奇偶位:'),sg.InputCombo(verify,size=(15, 1))],
[sg.RButton('連線串列埠',size=(20,1))]]
button_size=(15,1)
Configure_button=[[sg.T(' '),sg.Text('響應測試',size=(15,1)),sg.T(' '),sg.Text('復位',size=(13,1)),sg.Text('設定模式',size=(15,1))],
[sg.RButton('AT',size=button_size),sg.RButton('AT+RST',size=button_size),sg.RButton('AT+CWMODE=2',size=button_size)],
[sg.T(' '),sg.Text('設定wifi名稱 密碼 通道 安全性'),sg.T(' '*15),sg.Text('開啟多連線')],
[sg.RButton('AT+CWSAP="esp8266","0123456789",11,3',size=(35,1)),sg.RButton('AT+CIPMUX=1')],
[sg.T(' '),sg.Text('設定埠號')],
[sg.RButton('AT+CIPSERVER=1,8080')]]
send_configure=[[sg.InputText('',key='input',size=(41,1)),sg.Checkbox('自動換行',default=True),sg.RButton('傳送')]]
layout=[[sg.Multiline('',key='message',size=(29,5)),sg.Frame('',layout1)],
[sg.Frame('命令配置',Configure_button)],
[sg.Frame('傳送區',send_configure)]
]
window=sg.Window('糖醋鹹魚ESP8266配置助手').Layout(layout)
ser=None
text=''
isRun=True
def readData():
global isRun
global text
while isRun:
if ser != None and ser.is_open:
if text.count('\n')>5:
text=text[text.index('\n')+1:]
text+=ser.read().decode()
while True:
button, value = window.ReadNonBlocking()
window.FindElement('message').Update(text)
if button==None and value==None:
print('結束程式')
isRun=False
break
if button=='連線串列埠':
ser = Serial()
ser.baudrate = int(value[1]) #波特率
ser.port = value[0] #com口
ser.stopbits=int(value[2]) #停止位 1 1.5 2
ser.bytesize=int(value[3]) #資料位
if value[5]=='無': #奇偶位 N沒有 E偶數 O奇數
ser.parity='N'
elif value[5]=='奇校驗':
ser.parity = 'O'
elif value[5] == '偶校驗':
ser.parity = 'E'
ser.timeout=5 #超時時間
try:
ser.open()
sg.Popup('連線成功')
t = Thread(target=readData, name='read_data')
t.start() #開始執行緒
except Exception as e:
sg.Popup('連線失敗')
elif button=='傳送':
if ser!=None and ser.is_open:
if value['input']!='':
if value[5]==True:
ser.write((value['input']+'\n').encode())
ser.flush()
else:
ser.write(value['input'].encode())
ser.flush()
else:
sg.Popup('請輸入內容')
else:
sg.Popup('沒有連線')
else:
window.FindElement('input').Update(button) #修改傳送框的內容