串口通信+进制基础+位运算
串口通信
串口通讯(Serial Communication)是一种接口标准,是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。
通讯方式
- 单工模式(Simplex Communication)的数据传输是单向的。信息只能沿一个方向传输
- 半双工模式(Half Duplex)既可以发送数据又可以接收数据,但不能同时进行发送和接收
- 全双工模式(Full Duplex)通信允许数据同时在两个方向上传输
比特率
比特率就是每秒钟传输的数据位数
常见串口通信协议标准
EIA RS232(通常简称“RS232”): 1962年由美国电子工业协会(EIA)制定。
EIA RS485(通常简称“RS485”): 1983年由美国电子工业协会(EIA)制定。
流程
1. 连接夹爪(串口端口)
2. 进入到`/dev/ttyUSB0`修改权限`chmod 777 ttyUSB0`
3. 发送rs232数据过去
RS232
RS232是计算机与通信工业应用中最广泛一种串行接口。它以全双工方式工作,需要地线、发送线和接收线三条线。RS232只能实现点对点的通信方式。
缺点
传输速率低,最高波特率19200bps
传输距离有限,一般在15m以内
抗干扰能力较差
RS485
具有良好的抗干扰能力,信号能传输上千米
可实现真正的多点通讯
串口调试工具cutecom
sudo apt install cutecom
因时机械人有一款基于LA16-021D 的直线伺服驱动器的电动夹爪,通讯方式有can/rs232/rs485三种通讯方式,此处记录基于rs232控制机械夹爪的代码和相关文件。
以下内容摘录与因时机器人官网:
2 通信协议
2.1 通信协议概要
主控单元与夹爪之间采用问答方式通信,主控单元主动发送指令帧,夹爪收到指令帧,解
析并执行后返回应答帧。
同一控制网络中允许一个主控单元同时连接控制多个夹爪,因此每个夹爪需用户分配不同
的 ID 号作为唯一标识(夹爪出厂时默认的 ID 号为 1)。主控单元发出的指令帧数据体中包括
有 ID 号信息,只有与之匹配的 ID 号对应的夹爪才能完整接收指令帧信息,并在执行指令后返
回相应的应答帧。
通信方式为 RS232 异步串口,每个指令帧以字节为最小单位,单一字节由 1 位起始位、8
位数据位以及 1 位停止位组成,无奇偶校验,共 10 比特。
2.2 指令帧
基础指令帧格式:
帧头:连续收到0xEB和0x90 ,表示有指令帧到达。
ID号: 每个夹爪都有一个ID号。ID号范围为1~254,转换为十六进制为0x01~0xFE。广播ID号255(0xFF),若控制器发出的ID号为255(0xFF),所有的夹爪均接收指令帧,但都不返回应答信息。
数据体长度:等于待发送的数据段长度,包括指令号与数据,即“ Len ”,总指令帧的长度为“ Len +5”。
补充基础知识:
0X代表16进制,这里的帧头是2个字节,其中第一个0xEB,是指16进制的14*16 + 11 = 235(十进制),转换为2进制是1110 1011。其实不需要知道这么详细,只需要知道,16进制2个字母(或数字)代表2进制(计算机中的)8个位即可。即,1个字节代表8位。
数据体1/2——指令号:指定该指令帧的类型。
CMD_MC_PARA_SAVE(0x01):参数保存到内部闪存,掉电不丢失
CMD_MC_PARA_ID_SET(0x04):设置夹爪ID
CMD_MC_MOVE_CATCH_XG(0x10):以设置的速度和力控阈值去夹取
CMD_MC_MOVE_HOLD_CATCH_XG(0x18):以设置的速度和力控阈值持续夹取
CMD_MC_MOVE_RELEASE(0x11):以设置的速度松开
CMD_MC_MOVE_STOPHERE(0x16):急停
CMD_MC_SET_EG_PARA(0x12):设置夹爪开口的最大最小值
MD_MC_READ_EG_PARA(0x13):读取夹爪开口的最大最小值
CMD_MC_READ_EG_STATE(0x14):读取当前夹爪的状态
CMD_MC_READ_EG_RUNSTATE(0x41);读取当前夹爪运行状态
数据体2/2——数据:随指令帧一起发送的数据内容。其中,读指令时该数据体无字节;
写指令时即为需要写入的内容。
校验和:校验和 Check_Sum,定义为校验和之前的除帧头两字节外其余所有数据累加和的低字节。
抓取:
释放:
from serial import Serial # 夹爪驱动类 class Gripper: def __init__(self, port, baudrate): self.serial = Serial(port, baudrate) def catch(self, speed=500, power=100): # 夹取逻辑 # 1.创建串口通讯的对象 # 2.发送数据 注意传的是字节数据 # data = b'\xEB\x90\x01\x05\x10\xF4\x01\x64\x00\x6F' b0b1 = b'\xEB\x90' b2 = b'\x01' b3 = b'\x05' b4 = b'\x10' # 数据转换成字节数组 b5 = bytearray([speed & 0x00ff]) # 取低字节 b6 = bytearray([speed >> 8]) # 取高字节 b7 = bytearray([power & 0x00ff]) # 取低字节 b8 = bytearray([power >> 8]) # 取高字节 # 将字节转成int数据 b9 = bytearray([(ord(b2)+ord(b3)+ord(b4)+ord(b5)+ord(b6)+ord(b7)+ord(b8)) & 0x00ff]) data = b0b1+b2+b3+b4+b5+b6+b7+b8+b9 # 3.写入数据(字节数据) self.serial.write(data) # 读取返回值 # read_data = self.serial.read(7) # print(read_data[0]) # 4.关闭串口通讯对象 self.serial.close() def release(self, speed=500): # 释放逻辑 # 1.创建串口通讯的对象 # 2.发送数据 注意传的是字节数据 # data = b'\xEB\x90\x01\x05\x10\xF4\x01\x64\x00\x6F' b0b1 = b'\xEB\x90' b2 = b'\x01' b3 = b'\x03' b4 = b'\x11' # 数据转换成字节数组 b5 = bytearray([speed & 0x00ff]) # 取低字节 b6 = bytearray([speed >> 8]) # 取高字节 # 将字节转成int数据 b7 = bytearray([(ord(b2) + ord(b3) + ord(b4) + ord(b5) + ord(b6)) & 0x00ff]) data = b0b1 + b2 + b3 + b4 + b5 + b6 + b7 # 3.写入数据(字节数据) self.serial.write(data) # 4.关闭串口通讯对象 self.serial.close() if __name__ == '__main__': # 注意运行前,要先给 /dev/ttyUSB0 这个端口 chmod+权限 gripper = Gripper('/dev/ttyUSB0', 115200) # 夹取 gripper.catch() # 等待夹取完成 ... # 释放 gripper.release()