modbus数据获取与数据解析

#代码部分

首先注意一点Python版的modbus要获取modbus值必须先装【环境包】
pip install serial 
# serial为串口包,需要打开串口,也就是usb
pip install crcmod
# crcmod 用来crc校验的
pip install modbus_tk
# modbus_tk 就是满足modbus协议的Python包
import crcmod
from binascii import unhexlify
import modbus_tk
import time
import serial
from modbus_tk import modbus_rtu
from modbus_tk import defines as cst
import logging


def crc16Add(read):
    try:
        crc16 = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
        readcrcout = hex(crc16(unhexlify(read))).upper()
        str_list = list(readcrcout)
        if len(str_list) == 5:
            str_list.insert(2, '0')  # 位数不足补0,在列表中下标为2的加入元素0
        crc_data = "".join(str_list)
        read = read.strip() + crc_data[4:] + crc_data[2:4]
        return read
    except:
        # print("crc校验出错'")
        logging.warning('crc校验出错')

flag_value = True
def modbus_getdate(slave_id, start_addr, date_len):
    try:
        master = modbus_rtu.RtuMaster(serial.Serial(port=PORT,
                                                    baudrate=19200,
                                                    bytesize=8,
                                                    parity='N',
                                                    stopbits=1,
                                                    xonxoff=0))
        # # logger = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")
        master.set_timeout(3)
        master.set_verbose(True)
        # holding_date = master.execute(slave_id, cst.READ_HOLDING_REGISTERS, start_addr, date_len)
        holding_date = master.execute(slave=slave_id,function_code=cst.READ_HOLDING_REGISTERS,quantity_of_x=date_len,starting_address=start_addr)
        holding_data125 = list()
        for i in range(len(holding_date)):
            holding_data125.append('%04x' % (holding_date)[i])  # append()在Tmp1列表末尾添加新的对象
        all_holding_data = '0103' + '%02x' % (date_len * 2) + ''.join(holding_data125)  #
        # return str(all_holding_data)
        return crc16Add(all_holding_data) #这里crc校验了,如果单纯的看数据可以不校验
    
    except modbus_tk.modbus_rtu.ModbusInvalidResponseError as err:
        # print(err)
        logging.warning(err)

def get_s16(val):
    '''
    作用为解析16进制有符号数,值得注意的是modbus poll是不支持有符号数的,一会先讲个modbus poll的用法
    '''
    if val > 65536:
        return val/100 
    
    elif val > 32768:
        #因为我传的数是需要有2位小数的,但是16进制中没有小数点的概念,所以数本身扩大100倍,然后做处理再除以100,就得到小数点后2位
        return (val - 65536)/100
    else:
        return val/100

def f_analysis(x):
    '''
    解析4位一个的16进制数
    '''
    les = len(x)
    print(les,'数据长度')
    for i in range(les):
        if i % 4  == 0:
            # print(i,j)
            datas = int(x[i:i+4],16)
            print(i,get_s16(datas),datas) # i代表循环位置,get_s16()为解析16进制有符号数,datas为16进制数



if __name__ == '__main__':
    PORT = 'COM12'
    flag = True
    for i in range(2):
        if flag:
            da = modbus_getdate(slave_id=1,start_addr=0,date_len=16)
            print(da) # modbus取出的值
            # master.execute(slave=1, function_code=cst.WRITE_MULTIPLE_REGISTERS, starting_address=0,
            #                data_format='0')
            f_analysis(da[6:-4])
            # 不需要前6个和后四个原因是,前6个值是我为了协议拼接的,后四个是crc校验生成的,所以它们不是数据,不需要。
结果如下 ,因为是8个温度探头,但只有前三个接了真正的探头,所有只有前三个有值,而且还重复了,不过这不影响。哈哈
01032007920793084ef510f510f510f510f51007920793084ef510f510f510f510f510B741
64 数据长度
0 19.38 1938
4 19.39 1939
8 21.26 2126
12 -28.0 62736
16 -28.0 62736
20 -28.0 62736
24 -28.0 62736
28 -28.0 62736
32 19.38 1938
36 19.39 1939
40 21.26 2126
44 -28.0 62736
48 -28.0 62736
52 -28.0 62736
56 -28.0 62736
60 -28.0 62736
讲个modbus poll 的用法,其实modbus poll 和我上面的代码的作用是一样的,但是modbus poll 是写好的工具,
且只支持215次 以内的数据,也就是32768,这个整数,一旦你要发送有符号数,216次 时它就不能解析了。
下面请看不能解析的部分

modbus数据获取与数据解析_第1张图片

这不是我要的结果
正确结果为,因为 前3个是采集的温度数据,所以19381956是变化的,想表示的就是19.38摄氏度。

modbus数据获取与数据解析_第2张图片

讲讲modbus poll和我代码之间的关系
modbus poll参数设置

modbus数据获取与数据解析_第3张图片

    端口为 com12

modbus数据获取与数据解析_第4张图片

子站数为1,地址从0开始,取16个寄存器的值
代码参数设置

modbus数据获取与数据解析_第5张图片

这个代码参数设置,在代码中可以找到

modbus数据获取与数据解析_第6张图片

你可能感兴趣的:(modbus)