LINUX.ORG.RU

Чтение с прибора по Modbus RTU


0

1

Не совсем по теме, но все же.

Есть прибор Метран-910. Пытаюсь читать значения аналоговых входов. Функция в протоколе Modbus RTU - 04. Значение на одном из входов = 2,350 мА

def modbus_read(device_id, function, first_registr, registr_count):
    r=struct.pack("!2b2h", device_id, function, first_registr, registr_count)

    res = crc16(r)
    CRC1= "{:c}".format(res >> 8)
    CRC2= "{:c}".format(res & 0xFF)

    ser = serial.Serial(14, timeout=1, baudrate='115200')
    ser.flushInput()
    ser.flushOutput()
    ser.write(r+CRC2+CRC1)
    time.sleep(1)
    h=struct.unpack("=3b", ser.read(3))
        
    while ser.inWaiting() > 2:
        print struct.unpack(">f", ser.read(4))


    
    ser.close()                         


modbus_read(1,4,0,12)

Запрос: 01 04 00 00 00 0C F0 0F

Ответ: 01 04 18 00 00 00 00 6A E7 40 16 00 00 00 00 00 00 7F 80 00 00 7F 80 00 00 7F 80 12 C6

01 04 18 - шапка, содержащая адрес прибора, код функции, и количество байт с ответом (18=24)

Т.е. нужные мне значения шести каналов:

1.00 00 00 00	=0
2.6A E7 40 16	=2,350 Хранится в виде float 32bit
3.00 00 00 00	=0
4.00 00 7F 80	=обрыв
5.00 00 7F 80	=обрыв
6.00 00 7F 80	=обрыв

И тут я застрял.

    while ser.inWaiting() > 2:
        print struct.unpack(">f", ser.read(4))
Выдает "левые" значения:
(0.0,)
(1.3978225080712631e+26,)
(0.0,)
(4.573838187556203e-41,)
(4.573838187556203e-41,)
(4.573838187556203e-41,)

Из документации: Для чтения одного входа следует запросить значение двух последовательно расположенных 16-битных регистров и затем объеденить полученные значения. Данные разделены по двум регистрам следующим образом:

Регистр 1:
Байт1 - средний байт мантиссы (биты 8-15)
Байт2 - младший байт мантиссы (биты 0-7)

Регистр 2:
Байт1 - знак и порядок числа (биты 24-31)
Байт2 - старший байт мантиссы (биты 16-22)

В общем, такие сложности. Сам я не осилю.

Перемещено Pinkbyte из general


Не так давно писал на жабке приложение для чтения данных с мультиметра по modbus rtu. Писал с одногруппницей, для которой это первый проект на жабке, а когда начали поджимать сроки об элегантности кода как-то совсем забыл, т.ч. местами он довольно ужасен — сейчас бы я написал иначе, но, думаю, общую идею понять можно. Кстати, для чтения регистров пришлось использовать функцию 0x03 — не знаю, устройство ли с кривой поддержкой modbus или еще какая фигня (в документации было сказано, что нужно использовать 0x04, но методом тыка мы выяснили, что документация лжет и в принципе бесполезна).

https://code.google.com/p/jdmmon/

f1xmAn ★★★★★
()
Ответ на: комментарий от f1xmAn

В моем случае точно 04 функция. Я заблудился в байтах-битах.

qq6ka
() автор топика

В общем, разобрался.

    while ser.inWaiting() > 2:
        r1 = ser.read(2)
        r2 = ser.read(2)
        a= "{:c}".format(ord(r2[0])) #Регистр2, байт1
        b= "{:c}".format(ord(r2[1])) #Регистр2, байт2
        c= "{:c}".format(ord(r1[0])) #Регистр1, байт1
        d= "{:c}".format(ord(r1[1])) #Регистр1, байт2

        print struct.unpack(">f", a+b+c+d)

(6.230940341949463,)

qq6ka
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.