工作中碰见两台单通道的大功率光源控制器,但是没有找到该控制器的手册.
一看牌子和厂家名称,突然发现这个和上次同事发给我的多通道手册是一个牌子.
于是插上串口线用串口助手测一下果然 指令兼容的;
厂家名不说了省事,只看串口参数,截图放在下方.
本来是打算C#做,但是python不甘心,于是就python;控制光源控制器.
一共80行两个滑动条,不废话贴程序.
import tkinter as tk
from tkinter import messagebox
import time
import serial
serL=serial.Serial("COM2",19200,bytesize=serial.EIGHTBITS,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,timeout=0.5) #winsows系统使用com口连接串行口
serR=serial.Serial("COM3",19200,bytesize=serial.EIGHTBITS,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,timeout=0.5) #winsows系统使用com口连接串行口
if (serL.isOpen()):print("serLdone!")
if (serR.isOpen()):print("serRdone!")
def portL_close():
serL.close()
if (serL.isOpen()):
print("关闭失败")
def portR_close():
serR.close()
if (serR.isOpen()):
print("关闭失败")
def Lsend(send_data):
if (serL.isOpen()):
serL.write(send_data.encode('utf-8')) #utf-8 编码发送
#ser.write(binascii.a2b_hex(send_data)) #Hex发送
print("发送成功",send_data)
def Rsend(send_data):
if (serR.isOpen()):
serR.write(send_data.encode('utf-8')) #utf-8 编码发送
#ser.write(binascii.a2b_hex(send_data)) #Hex发送
print("发送成功",send_data)
win = tk.Tk();win.title("滑动条控制光源")
try:
win.iconbitmap('th.ico')
except:
pass
r"""
COM2 是左光源
COM3 是右光源
串口配置:
波特率:19200 数据位:8 停止位:1 校验位:NONE
19200 8 N 1
光源控制器本就单通道:不存在多通道操作:
发送字符串:
设置亮度:200
发送:SA0200#
返回:
亮度查询:
发送:SA#
返回:a0200
"""
def select_price_L(value):
Lsend(f"SA0{value}#")
print(value,"L")
def select_price_R(value):
Rsend(f"SA0{value}#")
print(value,"R")
Scale1=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='左侧光源' , #滑动条的标签:不写则不显示.
command=select_price_L)
Scale1.pack()
Scale1.set(255)#初始位置100
Scale2=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='右侧光源' , #滑动条的标签:不写则不显示.
command=select_price_R)
Scale2.pack()
Scale2.set(255)#初始位置100
def QueryWindow():
if messagebox.askokcancel("窗口关闭?")==True:
portL_close();portR_close()
win.destroy()
win.protocol('WM_DELETE_WINDOW', QueryWindow)
win.mainloop()
算然自己电脑有python环境但是工控机没python更没有第三方库,于是需要打包成exe.
开始: 新建个打包程序 如下:
import os,sys
def cmd(s="pause"):
os.system(s)
pass
打包的文件名="光源控制滑动条002"
生成单一EXE=" -F "
指定图标="-i th.ico"
不显示命令行="--noconsole"
cmd(f"pyinstaller {打包的文件名}.py {生成单一EXE} {指定图标} {不显示命令行} ")
新建一个文件夹: 这个程序和上面那个还有图标放在里面.运行打包程序.
dist里面就会出现打包成exe的python程序将同名图标复制进去就可以自定义图标.
不过没有加防多开,第一个没关运行二次会报串口打不开. 然后这个打包的exe 经常报毒就很奇怪.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
仔细观察的同学已经发现,上面的程序有好几个毛病,0.不能多开前面已经说过了.1.程序重新打开的时候光源亮度会回到255,2.不知道是控制器问题还是程序问题设置亮度低于100时就写不起作用了.
这次手上有一台海康de4通道光源控制器.控制方式竟然和上次那个一模一样.
附图为证:
.
四通道:贴程序看看.
import tkinter as tk
from tkinter import messagebox
import time,serial
ser=serial.Serial("COM4",19200,bytesize=serial.EIGHTBITS,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,timeout=0.1)
if (ser.isOpen()):print("serdone!")
def port_close():#关闭串口
ser.close()
if (ser.isOpen()):
print("关闭失败")
def read(S=""):
if (ser.isOpen()):
r = ser.read().decode('utf-8')
if (r==S):
print(f"{S}")
else:
print(f"{S}W>>失败!")
def send(send_data):
if (ser.isOpen()):
ser.write(send_data.encode('utf-8')) #utf-8 编码发送
print(">>",send_data)
CH1=0
CH2=0
CH3=0
CH4=0
def readCH_value():
global CH1,CH2,CH3,CH4
if (ser.isOpen()):
send(f"SA#");r1 = ser.readall().decode('utf-8');
send(f"SB#");r2 = ser.readall().decode('utf-8');
send(f"SC#");r3 = ser.readall().decode('utf-8');
send(f"SD#");r4 = ser.readall().decode('utf-8');
print(f"**************************************************");
if (len(r1)==5):
print(f"{len(r1)} {r1} {r1[2:]}");CH1=r1[2:]
if (len(r2)==5):
print(f"{len(r2)} {r2} {r2[2:]}");CH2=r2[2:]
if (len(r3)==5):
print(f"{len(r3)} {r3} {r3[2:]}");CH3=r3[2:]
if (len(r4)==5):
print(f"{len(r4)} {r4} {r4[2:]}");CH4=r4[2:]
print(f"**************************************************");
Scale1.set(CH1)
Scale2.set(CH2)
Scale3.set(CH3)
Scale4.set(CH4)
win = tk.Tk();win.title("滑动条控制光源")
def select_price1(value):
send(f"SA0{value}#")
read("A")
Scale1=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道1' , #滑动条的标签:不写则不显示.
command=select_price1)
Scale1.pack()
def select_price2(value):
send(f"SB0{value}#")
read("B")
Scale2=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道2' , #滑动条的标签:不写则不显示.
command=select_price2)
Scale2.pack()
def select_price3(value):
send(f"SC0{value}#")
read("C")
Scale3=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道3' , #滑动条的标签:不写则不显示.
command=select_price3)
Scale3.pack()
def select_price4(value):
send(f"SD0{value}#")
read("D")
Scale4=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道4' , #滑动条的标签:不写则不显示.
command=select_price4)
Scale4.pack()
readCH_value()
def QueryWindow():
if messagebox.askokcancel("窗口关闭?")==True:
try:
port_close();
except:
pass
win.destroy()
win.protocol('WM_DELETE_WINDOW', QueryWindow)
win.mainloop()
r"""
COM4 是光源
串口配置:
波特率:19200 数据位:8 停止位:1 校验位:NONE
19200 8 N 1
通道操作:
A:1通道
B:2通道
C:3通道
D:4通道
发送字符串:
设置亮度:200
发送:SA0200#
返回:
发送成功 SD0255#
D
发送成功 SC0255#
C
发送成功 SB0255#
B
发送成功 SA0255#
A
亮度查询:
发送:SA#
返回:a0200
发送成功 SA#
a0255
发送成功 SB#
b0255
发送成功 SC#
c0255
发送成功 SD#
d0255
"""
这次增加了,亮度读取,不会出现重启程序亮度回到255的情况.
1.亮度不能低于100的情况依然存在>依然不知道是哪里出了问题(从现象看应该是控制器的问题).
2.多开的问题也没解决.>>实际上还有个端口记忆和端口扫描的问题.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
偶然机缘巧合和大姐大说了一下第一个情况,大姐大瞄了一眼,就找到:这行:说你这个value哪来的???我木讷的思量了一下说是这是进度条传进来的.只见大姐大说,那肯定是你输入格式错了.
并指出可以控制进度条value的格式.
def select_price1(value):
send(f"SA0{value}#")
原来根本没有仔细看手册,手册只有短短一页. 回头一看亮度等级是(0000-0255).而不是自己想当然的(00-0255). 好了.问题发现了现在该优化了. 大姐大的精髓没学会.控制格式咱也不会.就简单粗暴的改一下吧.
#笨蛋办法 判断value长度决定前面有几个0 4通道进度条改成如下
def select_price1(value):
if(len(value)==3):
send(f"SA0{value}#")
if(len(value)==2):
send(f"SA00{value}#")
if(len(value)==1):
send(f"SA000{value}#")
read("A")
def select_price2(value):
if(len(value)==3):
send(f"SB0{value}#")
if(len(value)==2):
send(f"SB00{value}#")
if(len(value)==1):
send(f"SB000{value}#")
read("B")
def select_price3(value):
if(len(value)==3):
send(f"SC0{value}#")
if(len(value)==2):
send(f"SC00{value}#")
if(len(value)==1):
send(f"SC000{value}#")
read("C")
def select_price4(value):
if(len(value)==3):
send(f"SD0{value}#")
if(len(value)==2):
send(f"SD00{value}#")
if(len(value)==1):
send(f"SD000{value}#")
read("D")
完整程序如下:
import tkinter as tk
from tkinter import messagebox
import time,serial
ser=serial.Serial("COM1",19200,bytesize=serial.EIGHTBITS,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,timeout=0.1)
if (ser.isOpen()):print("serdone!")
def port_close():#关闭串口
ser.close()
if (ser.isOpen()):
print("关闭失败")
def read(S=""):
if (ser.isOpen()):
r = ser.read().decode('utf-8')
if (r==S):
print(f"{S}")
else:
print(f"{S}W>>失败!")
def send(send_data):
if (ser.isOpen()):
ser.write(send_data.encode('utf-8')) #utf-8 编码发送
print(">>",send_data)
CH1=0
CH2=0
CH3=0
CH4=0
def readCH_value():
global CH1,CH2,CH3,CH4
if (ser.isOpen()):
send(f"SA#");r1 = ser.readall().decode('utf-8');
send(f"SB#");r2 = ser.readall().decode('utf-8');
send(f"SC#");r3 = ser.readall().decode('utf-8');
send(f"SD#");r4 = ser.readall().decode('utf-8');
print(f"**************************************************");
if (len(r1)==5):
print(f"{len(r1)} {r1} {r1[2:]}");CH1=r1[2:]
if (len(r2)==5):
print(f"{len(r2)} {r2} {r2[2:]}");CH2=r2[2:]
if (len(r3)==5):
print(f"{len(r3)} {r3} {r3[2:]}");CH3=r3[2:]
if (len(r4)==5):
print(f"{len(r4)} {r4} {r4[2:]}");CH4=r4[2:]
print(f"**************************************************");
Scale1.set(CH1)
Scale2.set(CH2)
Scale3.set(CH3)
Scale4.set(CH4)
win = tk.Tk();win.title("滑动条控制光源")
def select_price1(value):
if(len(value)==3):
send(f"SA0{value}#")
if(len(value)==2):
send(f"SA00{value}#")
if(len(value)==1):
send(f"SA000{value}#")
read("A")
Scale1=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道1' , #滑动条的标签:不写则不显示.
command=select_price1)
Scale1.pack()
def select_price2(value):
if(len(value)==3):
send(f"SB0{value}#")
if(len(value)==2):
send(f"SB00{value}#")
if(len(value)==1):
send(f"SB000{value}#")
read("B")
Scale2=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道2' , #滑动条的标签:不写则不显示.
command=select_price2)
Scale2.pack()
def select_price3(value):
if(len(value)==3):
send(f"SC0{value}#")
if(len(value)==2):
send(f"SC00{value}#")
if(len(value)==1):
send(f"SC000{value}#")
read("C")
Scale3=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道3' , #滑动条的标签:不写则不显示.
command=select_price3)
Scale3.pack()
def select_price4(value):
if(len(value)==3):
send(f"SD0{value}#")
if(len(value)==2):
send(f"SD00{value}#")
if(len(value)==1):
send(f"SD000{value}#")
read("D")
Scale4=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=255, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='通道4' , #滑动条的标签:不写则不显示.
command=select_price4)
Scale4.pack()
readCH_value()
def QueryWindow():
if messagebox.askokcancel("窗口关闭?")==True:
try:
port_close();
except:
pass
win.destroy()
win.protocol('WM_DELETE_WINDOW', QueryWindow)
win.mainloop()
好,现在可以随意拖拽进度条控制4通道,光源控制器亮度了.