布瑞特单圈绝对值旋转编码器串口数据读取
数据手册:http://briter.net/col.jsp?id=109 (2.1版本RS485说明书通信协议 单圈.pdf)
绝对式编码器为布瑞特BRT38-ROM16384-RT1,采用RS485通信。
该绝对式编码器共有5根线:红、黄、黑、绿、白
由于需要通过绝对是编码器采集数据,并通过串口上传至上位机。因此,需要使用RS485转USB模块进行转接。
1.2 MODBUS-RTU 帧格式
本编码器支持 MODBUS 的 0x03(读保持寄存器)、0x06(写单个寄存器)。
1.2.1 0x03 读保持寄存器
1.2.2 0x06 写单个寄存器
1.3 寄存器定义
1.3.1 编码器寄存器
如上表可知,该编码器共有13个寄存器,每个寄存器对应着一种功能,可通过对这13个寄存器进行设置,实现特定的功能。
由1.2可知,寄存器有两种模式:读和写。支持功能码为0x03为读保持寄存器,支持功能码为0x06为写保持寄存器。
编码器通信设置:
1、 读取编码器虚拟多圈值
Tx:01 03 00 00 00 02 (C4 0B)
Rx:01 03 04 00 01 76 3B (CC 40)
主站发送:
Tx寄存器字节 | 1(ADR) | 2(读) | 3(起始寄存器高字节) | 4(起始寄存器低字节) | 5(寄存器低字节) | 6(寄存器低字节) | 7(CRC高字节) | 8(CRC低字节) |
---|---|---|---|---|---|---|---|---|
内容 | 01 | 03 | 00 | 00 | 00 | 02 | C4 | 0B |
寄存器的第3和4个字节构成寄存器的地址即0x0000
从站回送:
Rx寄存器字节 | 1(ADR) | 2(读) | 3(字节总数) | 4、5(寄存器数据1) | 6、7(寄存器数据2) | … | M-1、M(寄存器数据M) | M+1(CRC高字节) | M+2(CRC低字节) |
---|---|---|---|---|---|---|---|---|---|
内容 | 01 | 03 | 04 | 00 01 | 76 3B | CC | 40 |
注:括号内为 CRC 校验位,编码器值返回数据是 00 01 76 3B (十进制:95803)
2、设置编码器波特率
Tx:01 06 00 05 00 02 (18 0A)
Rx:01 06 00 05 00 02 (18 0A)
注:括号内为 CRC 校验位,设置的波特率为 38400 (0x02)
主站发送:
Tx寄存器字节 | 1(ADR) | 2(写) | 3(寄存器高字节) | 4(寄存器低字节) | 5(寄存器数高字节) | 6(寄存器数低字节) | 7(CRC高字节) | 8(CRC低字节) |
---|---|---|---|---|---|---|---|---|
内容 | 01 | 06 | 00 | 05 | 00 | 02 | 18 | 0A |
寄存器的第3和4个字节构成寄存器的地址即0x0005,第5和6个字节构成要发送的数据为0x0002。
当从站接收正确,从站回送:
Rx寄存器字节 | 1(ADR) | 2(读) | 3(寄存器高字节) | 4(寄存器低字节) | 5(寄存器数高字节) | 6(寄存器数低字节) | 7(CRC高字节) | 8(CRC低字节) |
---|---|---|---|---|---|---|---|---|
内容 | 01 | 06 | 00 | 05 | 00 | 02 | 18 | 0A |
寄存器的第3和4个字节构成寄存器的地址即0x0005,第5和6个字节构成要发送的数据为0x0002。
3、设置编码器数据模式
Tx: 01 06 00 06 00 01 (A8 0B)
Rx: 01 06 00 06 00 01 (A8 0B)
注:括号内为 CRC 校验位,设置当前编码器数据模式为自动回传(默认查询)
4、设置编码器自动回传时间(毫秒)
Tx: 01 06 00 07 00 64 (39 E0)
Rx: 01 06 00 07 00 64 (39 E0)
注:括号内为 CRC 校验位,设定自动回传时间为 100 毫秒(HEX:0x0064)
千万注意:一旦设置自动回传时间小于 20 毫秒,编码器将无法再设置其他参数,谨慎使用!!
5、设置编码器零点
Tx:01 06 00 08 00 01 (C9 C8)
Rx:01 06 00 08 00 01 (C9 C8)
注:括号内为 CRC 校验位,设置当前编码器当前点为零点。
6、设置编码器数值递增方向
Tx:01 06 00 09 00 01 (98 08)
Rx:01 06 00 09 00 01 (98 08)
注:括号内为 CRC 校验位,设置当前编码器逆时针数值增加(默认顺时针)
7、设置编码器当前位置值
Tx 01 06 00 0B 03 E8 (F8 B6)
Rx: 01 06 00 0B 03 E8 (F8 B6)
注:括号内为 CRC 校验位,设置的位置为 1000 (HEX:0x3E8)
8、编码器转速计算:
编码器旋转速度 = 编码器角速度值 / 单圈精度 / 转速计算时间(单位:转/分钟)
例如:编码器角速度值回传为 1000,单圈精度为 32768,转速采样时间为
100ms(0.1/60min)
编码器旋转速度 = 1000/32768/(0.1/60) = 1000*0.0183 = 18.31 转/分钟
完整代码如下:
**串口设置:**串口号为COM15(根据实际情况设置);波特率:115200;数据位:8;停止位:1;超时时间:None
#模式切换 转换成16进制
modecmd1 = bytes([0x01, 0x06, 0x00, 0x06, 0x00, 0x01, 0xA8, 0x0B]) #自动回传
modecmd2 = bytes([0x01, 0x06, 0x00, 0x06, 0x00, 0x00, 0x69, 0xCB]) #查询
modecmd3 = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B]) #读取编码器虚拟多圈值
BUF_SIZE = 10
buf = bytearray([0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
c = c1 = c2 = ib = flag = 0
def CRC16(data, length): # CRC校验函数代码:使用参考手册提供的代码。
CRC = 0xFFFF
for i in range(length):
CRC ^= data[i]
for _ in range(8):
if CRC & 0x0001:
CRC = (CRC >> 1) ^ 0xA001
else:
CRC >>= 1
return CRC
if __name__ == '__main__':
ser = serial.Serial(port="COM15",
baudrate=115200,
bytesize=8,
parity=serial.PARITY_NONE,
stopbits=1,
timeout=None)
if ser.isOpen():
print("Open Successfully ", end='')
print(ser.name)
else:
print("Open Fail")
# write_len = ser.write(modecmd1) # 写指令:切换模式,设置参数
while True:
R = ser.read(1) # 读取一个字节
if R == b'': # 接收字符串为空
print("Read Fail")
ser.close()
break
c = int.from_bytes(R, byteorder='big') # 将十六进制转换为整数
if flag > 0:
if ib < BUF_SIZE - 1:
buf[ib] = c
ib += 1
else:
CRC = CRC16(buf, BUF_SIZE - 3) # 校验位,数据手册有提供
if (CRC & 0xFF) == buf[7] and ((CRC >> 8) & 0xFF) == buf[8]:
A = (buf[5] << 8) + buf[6] # 将buf[5]左移8位后与buf[6]相加,结果赋值给A。
print(A)
else:
print("CRC Fail")
flag = 0
if flag == 0:
if c2 == 0x01 and c1 == 0x03 and c == 0x04: # 判断帧头,且帧头要连续,即为0x01、0x03、0x04
flag = 1
ib = 3
c2 = c1
c1 = c