CS modbus/TCP读写数据时,默认每个寄存器16位,机器人读取到的数据为16位的无符号数(0-65535)
若外部设备(例如PLC)通过modbus/TCP向机器人写入浮点数(使用2个寄存器,共32位),机器人如何读取?
以下举例,PLC向机器人的寄存器地址256和257一共两个寄存器,写入浮点数。
1. 在机器人中创建m256(对应地址256,类型位寄存器输出)和m257(对应地址256,类型位寄存器输出)
2. 在modbus poll软件中,连接机器人,并使用功能吗16对多寄存器进行读写。Display类型选择为float CD AB。此时往256寄存器写入数值1.0
机器人运行脚本(其中modbus_float.script代码如文末),机器人可以正确读取到modbus 发来的浮点数1.0
若使用西门子PLC基于modbus 发送浮点数,以下程序中写为: var_1:=getModbusFloat('m257','m256')(即西门子的高word和低word为大端,机器人使用时反一下)
modbus_float.script代码如下:
import struct def Bytes2Float(d,BigEndian=False): # 输入4个字节数据,转化为对应的32位的实数,默认使用小端编码,使用大端编码添加参数BigEndian为True if BigEndian ==True: return struct.unpack('<f', struct.pack('4B', *d))[0] else: return struct.unpack('>f', struct.pack('4B', *d))[0] def Bytes2Int32(d,BigEndian=False): # 输入4个字节数据,转化为对应的32位的带符号整数,默认使用小端编码,使用大端编码添加参数BigEndian为True if BigEndian ==True: return struct.unpack('<i', struct.pack('4B', *d))[0] else: return struct.unpack('>i', struct.pack('4B', *d))[0] def Bytes2Int16(d,BigEndian=False): # 输入2个字节数据,转化为对应的16位的带符号整数,默认使用小端编码,使用大端编码添加参数BigEndian为True if BigEndian ==True: return struct.unpack('<h', struct.pack('2B', *d))[0] else: return struct.unpack('>h', struct.pack('2B', *d))[0] def Float2Bytes(d,BigEndian=False): # 输入32位的实数,转化位对应4个字节数据,默认使用小端编码,使用大端编码添加参数BigEndian为True if BigEndian ==True: return list(struct.unpack('4B',struct.pack('f',d))) else: return list(struct.unpack('4B',struct.pack('>f',d))) def Int322Bytes(d,BigEndian=False): # 输入32位带符号整数,转化位对应4个字节数据,默认使用小端编码,使用大端编码添加参数BigEndian为True if BigEndian ==True: return list(struct.unpack('4B',struct.pack('<i',d))) else: return list(struct.unpack('4B',struct.pack('>i',d))) def Int162Bytes(d,BigEndian=False): # 输入16位带符号整数,转化位对应2个字节数据,默认使用小端编码,使用大端编码添加参数BigEndian为True if BigEndian ==True: return list(struct.unpack('2B',struct.pack('<h',d))) else: return list(struct.unpack('2B',struct.pack('>h',d))) def getModbusFloat(m_low,m_high): # 将m_low和m_high 两个寄存器地址的数据读入,m_low和m_high为modbus变量名 # m_low存储的是低word的数据,m_high存储的是高word的数据, # 即格式为CD,AB low = modbus_get_signal_status(m_low) high = modbus_get_signal_status(m_high) d= [high>>8,high&255,low>>8,low&255] return Bytes2Float(d) def setModbusFloat(data,m_low,m_high): # 将浮点数,拆分成2个无符号16bit数据 word,低word存入m_low, 高word存入m_high # 数据格式CD,AB # 即:m_low:AB # m_high: CD d = Float2Bytes(data) low = d[2]*256+d[3] high = d[0]*256+d[1] modbus_set_output_register(m_low, low) modbus_set_output_register(m_high, high)
机器人也可以对modbus的2个连续寄存器写入浮点数,plc从这2个连续寄存器读取浮点数,具体如下:
假设机器人写入258和259两个寄存器(在配置中新建2个寄存器变量)
modbus poll软件中,功能码修改为03 read holding register,display类型依旧为float CD AB
机器人使用setModbusFloat(2.8,'m258','m259')写入寄存器,可以看到modbus poll可以读取到浮点数结果2.8.
如果上位机为西门子plc,机器人使用setModbusFloat(2.8,'m259','m258')来解决西门子高word和低word颠倒问题