本人打算做一个模拟量控制伺服电机的工控设备。
买了一块正负10V输出的模拟量输出模块;
用PySide6编上位机程序,通过MODBUS-RTU协议,RS485通讯,读取文本框输入电压值,点击按钮把电压值发给模块的寄存器,通过模块输出电压;
从而控制伺服电机的转速,正反转。
为了避免广告嫌疑,我拍实物照片供参考,桌面有点杂乱,就看红字的三个件是本次主题。
(蓝色模块是模拟量采集模块,刚好与本次主题模块相反,暂时无关)。
废话不说了,上代码,代码简单,没有界面美化,纯粹为了实现模拟量输出的功能,注释完整,供非科班出身的入门工友参考扩展。
import serial
from PySide6.QtWidgets import QApplication, QWidget, QLineEdit, QPushButton, QVBoxLayout
import crcmod #crc校验库
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("通过串口发送程序到模拟量输出模块输出模拟量")
self.setGeometry(200,200,400, 300) #窗口大小
self.initUI()
self.hex_address='01 06 00 0A' #模拟量输出模块的站号01功能码06和寄存器码000A,根据自己的设备调整。
def initUI(self):
# 创建输入电压的文本框和发送电压值的按钮
self.coltage_text = QLineEdit()
self.coltage_btn = QPushButton('发送')
# 创建布局
vbox = QVBoxLayout()
vbox.addWidget(self.coltage_text)
vbox.addWidget(self.coltage_btn)
# 设置主窗口布局
self.setLayout(vbox)
# 设置按钮点击事件
self.coltage_btn.clicked.connect(self.sendData)
def address(self): #定义站号和功能码
adress_split=self.hex_address.split() #分割字符串
hex_address = "".join(c[0:4] for c in adress_split) #转换为4位16进制数
return hex_address #返回站号功能码
def input_coltage(self): #输入电压的转换
input_coltage=float(self.coltage_text.text()) #获取输入的电压的文本框数据
input_coltage_change=input_coltage*204.75+2047.5 #0-4095码对应-10V-+10V电压,2047.5是分界点,2047.5/10=204.75每伏刻度,计算电压码。
if input_coltage_change>4095: #保留小数点后3位,设置上下限范围,超过则按极值处理。
input_coltage_change=4095
if input_coltage_change<0:
input_coltage_change=0
else:
input_coltage_change=round(input_coltage_change,3)
hex_input_coltage = hex(int(input_coltage_change))[2:].zfill(4) # 电压浮点数转换为4位十六进制
return hex_input_coltage #返回电压码
def check_crc(self): #定义CRC-16校验码得到发送码
hex_address=self.address() #引用 hex_address
hex_input_coltage=self.input_coltage() #引用 hex_input_coltage
hex_str_12 = hex_address + hex_input_coltage #2位站号+2位功能码+4位寄存器码+4位电压码,共12位
data = bytes.fromhex(hex_str_12) # 将数据转换为bytes
crc = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)(data) # 使用crcmod进行CRC-16计算
crc_bytes = crc.to_bytes(2, 'big') # 将CRC校验码转换为字节字符串
crc_str_low = format(crc_bytes[1], '02x') # 提取低字节并转换为十六进制字符串,前面填充0以满足4位的要求
crc_str_high = format(crc_bytes[0], '02x') # 提取高字节并转换为十六进制字符串,前面填充0以满足4位的要求
crc_str = crc_str_low+crc_str_high # 将高字节和低字节进行交换
hex_str = hex_str_12 + crc_str # 将CRC添加到数据中,共16位
return hex_str #返回待发送的16位码
def sendData(self): # 通过串口发送出去
hex_str=self.check_crc() #引用发送码
ser = serial.Serial('COM5', 9600) #定义串口
ser.write(bytes.fromhex(hex_str)) #写入发送码
ser.close() #关闭串口
if __name__ == '__main__':
app = QApplication([])
windown = MyWidget()
windown.show()
app.exec()