2016-11-03 10 views
0

Я использую библиотеку python Minimal Modbus для чтения счетчика энергии (RS-485).Modbus, python и минимальный modbus

Я пытаюсь использовать функцию для чтения нескольких регистров сразу

read_registers (registeraddress, numberOfRegisters, functioncode = 3)

Вот код библиотеки Python:

def read_registers(self, registeraddress, numberOfRegisters, functioncode=3): 
     """Read integers from 16-bit registers in the slave. 

     The slave registers can hold integer values in the range 0 to 65535 ("Unsigned INT16"). 

     Args: 
      * registeraddress (int): The slave register start address (use decimal numbers, not hex). 
      * numberOfRegisters (int): The number of registers to read. 
      * functioncode (int): Modbus function code. Can be 3 or 4. 

     Any scaling of the register data, or converting it to negative number (two's complement) 
     must be done manually. 

     Returns: 
      The register data (a list of int). 

     Raises: 
      ValueError, TypeError, IOError 

     """ 
     _checkFunctioncode(functioncode, [3, 4]) 
     _checkInt(numberOfRegisters, minvalue=1, description='number of registers') 
     return self._genericCommand(functioncode, registeraddress, \ 
      numberOfRegisters=numberOfRegisters, payloadformat='registers') 

Проблема, которую я получил, заключается в том, что регистры содержат данные как Long, но эта функция возвращает их как список int и глядя на значения, которые не кажутся правильными.

Это мой сценарий на данный момент:

##!/usr/bin/env python 

import minimalmodbus 
import time 
import glob 
import sys 
import MySQLdb 

instrument = minimalmodbus.Instrument('/dev/ttyUSB1', 7) 

#Debug Options 

#instrument.debug = True #debug modbus 

read = False 

def convert(value): 
     data=chr(value) 
     return data 

def read_registers_ime(): 
     data = instrument.read_registers(4096,20) 
     return data 

while True: 
     try: 
       while read == False: 
         data = read_registers_ime() 
         print data 
         time.sleep(0.11) 
         read = True 

       break 

     except KeyboardInterrupt: 
       print "Stopped" 
       sys.exit() 

     except TypeError: 
       print "TypeError" 

     except IOError: 
       print "IOError" 

В данный момент она возвращает следующее:

[3, 39192, 3, 44592, 3, 44592, 0, 423, 0, 0, 0, 0, 0, 0, 6, 19884, 6, 24584, 6, 19884]

Все, что я пробовал до сих пор, чтобы преобразовать данные обратно в исходный формат, не удался. Я бы очень признателен за помощь здесь.

Большое спасибо,

Bryan

ответ

1

Я уже сталкивался с такой проблемой работы с MODBUS использованием umodbus вместо минимальной Modbus. Я решил ее:

  • получать регистры парами
  • с использованием struct для преобразования пар в Интс

см ниже пример (Python 2.7):

import struct 

registers = [3, 39192, 3, 44592, 3, 44592, 0, 423, 0, 0, 0, 0, 0, 0, 6, 19884, 6, 24584, 6, 19884] 

def grouped(iterable, group_size): 
    """iterates on iterable, yielding groups of group_size elements""" 
    it = iter(iterable) 
    while True: 
     group = [next(it) for _ in range(group_size)] 
     yield group 

for group in grouped(registers, 2): 
    bytes = b"" 
    for word in group: 
     word_bytes = struct.pack("H", word) 
     bytes += word_bytes 
    bytes_hex = "0x" + "".join(["{:>02X}".format(ord(byte_)) for byte_ in bytes]) 
    print("{} -> {} -> {}".format(group, bytes_hex, struct.unpack("<i", bytes)[0])) 

печатает:

[3, 39192] -> 0x03001899 -> -1726480381 
[3, 44592] -> 0x030030AE -> -1372585981 
[3, 44592] -> 0x030030AE -> -1372585981 
[0, 423] -> 0x0000A701 -> 27721728 
[0, 0] -> 0x00000000 -> 0 
[0, 0] -> 0x00000000 -> 0 
[0, 0] -> 0x00000000 -> 0 
[6, 19884] -> 0x0600AC4D -> 1303117830 
[6, 24584] -> 0x06000860 -> 1611137030 
[6, 19884] -> 0x0600AC4D -> 1303117830 

В этом примере могут потребоваться некоторые настройки в соответствии с вашими точными потребностями, но это может помочь.