串口通信+进制基础+位运算

串口通信

串口通讯(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'xEBx90x01x05x10xF4x01x64x00x6F'
        b0b1 = b'xEBx90'
        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'xEBx90x01x05x10xF4x01x64x00x6F'
        b0b1 = b'xEBx90'
        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()
原文地址:https://www.cnblogs.com/kongweisi/p/13910823.html