Python, используя переменные в pymodbus.utilities.computeCRC

Я ищу дни, если я использовал неправильные строки поиска, извините.

Я хочу использовать "pymodbus.utilities.computeCRC" для вычисления значения CRC для связи с устройством Modbus, которое использует собственный код, поэтому никакие функции "чтение регистра" по умолчанию не могут быть использованы.

Правильный CRC - 0x34bb

Проблема в том, что он работает только с версией 1, дает шестнадцатеричные значения непосредственно для computeCRC, но ни одна из "переменных" опций не работает.

import pymodbus.utilities
meins=[]
meins.append('10')
meins.append('33')
meins.append('01')
meins.append('01')

meins1=''
for i in meins:
        meins1 = meins1 + "\\x" + i

meins2='\x10\x33\x01\x01'

meins3=bytearray.fromhex("10330101")

crc=hex(pymodbus.utilities.computeCRC('\x10\x33\x01\x01'))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins1))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins2))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins3))
print(crc)

Выход:

  • 0x34bb
  • 0x2a9c
  • 0xdc0b
  • 0x9c0a
  • 0x5dca

2 ответа

Решение

Вот как вы можете использовать генератор CRC для ваших нужд. Существует небольшая разница в том, как вводить нужно в зависимости от версии Python (2.7 или 3.x).

Python3 и Pymodbus==1.3.2

Обратите внимание, что для python3 и pymodbus требуются строки байтов для генерации CRC .

import pymodbus.utilities
from pymodbus.compat import int2byte
meins=[]
meins.append(0x10)
meins.append(0x33)
meins.append(0x01)
meins.append(0x01)

meins1=b''
for i in meins:
    meins1 = meins1 + int2byte(i)

meins2=b'\x10\x33\x01\x01'

meins3=bytearray.fromhex("10330101")

crc=hex(pymodbus.utilities.computeCRC(b'\x10\x33\x01\x01'))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins1))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins2))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins3))
print(crc)

Выход

0x34bb
0x34bb
0x34bb
0x34bb
0x34bb

Python2 и pymodbus==1.3.2

import pymodbus.utilities
from pymodbus.compat import int2byte
meins=[]
meins.append(int2byte(0x10))
meins.append(int2byte(0x33))
meins.append(int2byte(0x1))
meins.append(int2byte(0x1))

meins1=''
for i in meins:
        meins1 = meins1 + i

meins2='\x10\x33\x01\x01'

meins3=bytearray.fromhex("10330101")
meins3=''.join(str(meins3))

crc=hex(pymodbus.utilities.computeCRC('\x10\x33\x01\x01'))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins1))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins2))
print(crc)
crc=hex(pymodbus.utilities.computeCRC(meins3))
print(crc)

Выход

0x34bb
0x34bb
0x34bb
0x34bb
0x34bb

Для информации, вот "уродливый питон начинающий" версия моего запроса к устройству. В этом случае запрос устанавливает выходную мощность инвертора батареи на 50 Вт. Значение правильно хранится в устройстве.

Код

import minimalmodbus
import struct
import sys
import string
import serial
import pymodbus.payload
import time

#Wattage to program to the modbus device in hex format
watt = '{0:04X}'.format(50)

#combine the wattage to the rest of the string
string='103F0D'+watt+'01AE01F400960000000000'

#convert to a format computeCRC can work with
stringh=bytearray.fromhex(string)
stringh=''.join(str(stringh))
crc=pymodbus.utilities.computeCRC(stringh)

#convert crc to HEX String
crc='{0:04X}'.format(crc)

#combine Payload with CRC
string=string+crc

#debug:
#print(string)

#convert to a Format ser.write can send
stringh=bytearray.fromhex(string)
stringh=''.join(str(stringh))

ser = serial.Serial('/dev/ttyUSB0', 57600)
ser.write(stringh)
time.sleep(0.1)
anz=ser.inWaiting()
str=ser.read(anz)
for char in str:
               mm = int(char.encode('hex'), 16)
               print(hex(mm))
# Wait for inverter to accept command
time.sleep(1)
# Status 3E
# Send Status check command
ser.write("\x10\x3E\x01\x01\xA5\x78")
# wait for answer
time.sleep(0.1)
# how many bytes came back
anz=ser.inWaiting()
# read all bytes
str=ser.read(anz)
# extract the 2 bytes with the current load setting
str1=str[13]+str[14]
# convert
p=int(str1.encode('hex'), 16) / 10
print(p)

Выход

0x10
0x3f
0x1
0x1
0xf4
0xb8

50

Байты

  • 0x10 - адрес устройства
  • 0x3F - команда, которую мы отправили раньше
  • 0x1 0x1 - Команда принята
  • 0xf4 0xb8 - CRC

    50 - значение считывается с устройства

Другие вопросы по тегам