Pi + привод - Ошибка Modbus: [Вход / Выход] Ошибка Modbus: [Недопустимое сообщение] Получено неполное сообщение, ожидается не менее 2 байтов (получено 0) - PullRequest
0 голосов
/ 20 января 2020

У меня проблемы с чтением и записью на привод, как я сейчас объясню.

Проблема:

Использование pymodbus на моем Raspberry Pi I ' Мы пытались управлять моим приводом с помощью команд Modbus, но, несмотря на то, что соединение установлено, мастер пытается вернуть следующую ошибку при попытке чтения или записи:

Сообщение об ошибке: Ошибка Modbus: [Вход / Выход] Modbus Ошибка: [Неверное сообщение] Получено неполное сообщение, ожидается не менее 2 байт (получено 0)

Настройка:

Я использую Raspberry Pi 4 как мастер со следующим экраном, подключенным для включения RS485: https://raspberrypi.dk/en/product/rs485-can-hat-for-raspberry-pi/, который я тестировал, может читать и записывать через Modbus, прежде чем я включил привод с этим программным обеспечением симулятора: http://www.simplymodbus.ca/RTUslave.htm

Я использую следующий привод, который я тестировал для работы с собственным программным обеспечением компании. https://www.linak.com/products/linear-actuators/la36/# / productdescription У которых есть Руководство по установке: https://manualzz.com/doc/11480918/linak-modbus-installationsguide Я также использовал это программное обеспечение, чтобы придать приводу следующие свойства: https://i.imgur.com/ZQKJeVC.png

Мои разъемы M12 задерживаются, поэтому я подключил Pi и привод, вставив провода от моего кабеля в отверстие моего Y-разъема и закрепив его большим количеством ленты (после проверки с помощью мультиметра, что кабель и разъем были подключены) следующим образом: https://i.imgur.com/CjpDiKe.jpg (следуя схеме, используемой в руководстве по установке на стр. 7). Затем я подключил другой конец провода к экрану RS485 (A1, B1 и GND_485).

Версия python на моем Pi - Python 3.7.3, и я выполняю программу из Thonny Python IDE.

Я запускаю следующую программу на мой Pi / master:

## To install dependencies:
## sudo pip3 install modbus-tk
##################################################################################################
import serial
import time

#For rs485_enable
import fcntl
import array

#For pymodbus
import pymodbus
from pymodbus.pdu import ModbusRequest
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.transaction import ModbusRtuFramer

import logging

# RS485 ioctls define
TIOCGRS485 = 0x542E
TIOCSRS485 = 0x542F
SER_RS485_ENABLED = 0b00000001
SER_RS485_RTS_ON_SEND = 0b00000010
SER_RS485_RTS_AFTER_SEND = 0b00000100
SER_RS485_RX_DURING_TX = 0b00010000
# rs 485 port
ser1 = serial.Serial("/dev/ttySC0",19200)
#ser1 = serial.Serial("/dev/ttySC0",9600)
ser2 = serial.Serial("/dev/ttySC1",9600)

def rs485_enable():
    buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
    #enable 485 chanel 1
    fcntl.ioctl(ser1, TIOCGRS485, buf)
    buf[0] |=  SER_RS485_ENABLED|SER_RS485_RTS_AFTER_SEND
    buf[1]  = 0
    buf[2]  = 0
    fcntl.ioctl(ser1, TIOCSRS485, buf)

    #enable 485 chanel 2
    fcntl.ioctl(ser2, TIOCGRS485, buf)
    buf[0] |=  SER_RS485_ENABLED|SER_RS485_RTS_AFTER_SEND
    buf[1]  = 0
    buf[2]  = 0
    fcntl.ioctl(ser2, TIOCSRS485, buf)
#end of rs485_enable():

logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

if __name__ == '__main__':

    rs485_enable()

    client = ModbusClient(method = "rtu", port = "/dev/ttySC0", parity = 'E', baudrate = 19200, bytesize = 8, stopbits = 1, timeout = 1, strict = False)
    connection = client.connect()
    print("Connection is:",connection,)

    #READ
    status = client.read_input_registers(40003, 1, unit=0x01)
    #client.write_register(30001, 100, unit = 1)

    if not status.isError():    
    #print(status)
        print(status.registers)
    else:
        print('Error message: {}'.format(status))

Часть моего кода предназначена для запуска экрана RS485 и поставляется из этой демонстрационной программы:

#################################################################################################

## Description :  This codes is for test the Modbus communication
##                via RS485 function on 485&CAM module from innom-maker     
##                Set one RS485 port as master and the other as slave.
##                master can read data and control the slave.

## Author      :  Calvin (calvin@inno-maker.com)/ www.inno-maker.com


## Date        :  2019.11.25

## Environment :  Hardware            ----------------------  Raspberry Pi 4
##                SYstem of RPI       ----------------------  2019-09-26-raspbian-buster-full
##                Version of Python   ----------------------  Python 3.7.3(Default in the system)

## To install dependencies:
## sudo pip3 install modbus-tk
##################################################################################################
import serial
import fcntl
import os
import struct
import termios
import array
#import modbus lib
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus as modbus
#import modbus_tk.modbus_rtu as modbus_rtu
from modbus_tk import modbus_rtu

# RS485 ioctls define
TIOCGRS485 = 0x542E
TIOCSRS485 = 0x542F
SER_RS485_ENABLED = 0b00000001
SER_RS485_RTS_ON_SEND = 0b00000010
SER_RS485_RTS_AFTER_SEND = 0b00000100
SER_RS485_RX_DURING_TX = 0b00010000
# rs 485 port
ser1 = serial.Serial("/dev/ttySC0",9600)    
ser2 = serial.Serial("/dev/ttySC1",9600)

def rs485_enable():
    buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
    #enable 485 chanel 1
    fcntl.ioctl(ser1, TIOCGRS485, buf)
    buf[0] |=  SER_RS485_ENABLED|SER_RS485_RTS_AFTER_SEND
    buf[1]  = 0
    buf[2]  = 0
    fcntl.ioctl(ser1, TIOCSRS485, buf)

    #enable 485 chanel 2
    fcntl.ioctl(ser2, TIOCGRS485, buf)
    buf[0] |=  SER_RS485_ENABLED|SER_RS485_RTS_AFTER_SEND
    buf[1]  = 0
    buf[2]  = 0
    fcntl.ioctl(ser2, TIOCSRS485, buf)
#end of rs485_enable():


if __name__ == '__main__':

    logger = modbus_tk.utils.create_logger("console")

    rs485_enable()

    #set modbus master
    master = modbus_rtu.RtuMaster(
           serial.Serial(port= '/dev/ttySC0',
           baudrate=9600,
           bytesize=8,
           parity='N',
           stopbits=1,
           xonxoff=0)
       )

    master.set_timeout(5.0)
    master.set_verbose(True)
    logger.info("connected")

    logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 4))

    #send some queries
    #logger.info(master.execute(1, cst.READ_COILS, 0, 10))
    #logger.info(master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 8))
    #logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 100, 3))
    #logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 100, 12))
    #logger.info(master.execute(1, cst.WRITE_SINGLE_COIL, 7, output_value=1))
    #logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 100, output_value=54))
    #logger.info(master.execute(1, cst.WRITE_MULTIPLE_COILS, 0, output_value=[1, 1, 0, 1, 1, 0, 1, 1]))
    #logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 100, output_value=xrange(12)))

#end of if __name__ == '__main__':

Журналы от Pi / master:

>>> %Run actuator_test1.py
Connection is: True
DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x1 0x4 0x9c 0x43 0x0 0x1 0xee 0x4e
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)) 
DEBUG:pymodbus.framer.rtu_framer:Frame - [b''] not ready
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Error message: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)

Попытки решения:

Я пытался изменить четность, стоп-биты, время ожидания и адрес подчиненного устройства (1-5 и 40000-40005). Я пытался перейти от чтения к письму, но я получаю ту же ошибку. Я попытался включить в свой клиент слово 'strict = False' после того, как оно было предложено в другом шаге, который пытался решить похожую проблему.

Так что же я упускаю? Чтобы заставить работать мой привод, мне нужно иметь возможность прочитать входной регистр и записать в два регистра хранения.

Я полагаю, что это программная проблема.

Редактировать: Хорошо, это, вероятно, аппаратная проблема. Просто попытался отключить мастер от подчиненного и запустить программу и получил точно такой же вывод. Так что, возможно, скотч не удерживает. Тем не менее, я скоро получу свои разъемы, поэтому, если кто-нибудь увидит будущую проблему, я буду рад услышать об этом.

...