Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)

前端 未结 2 533
小鲜肉
小鲜肉 2020-12-19 05:39

Problem

pymodbus master/client can send a request to the slave/server. The slave/server make the things to return ready and is waiting for the maste

2条回答
  •  醉酒成梦
    2020-12-19 06:08

    Just as Marcos G. above suggest, did I modify pymodbus to control the GPIO chosen.

    I chose the software solution as I just need some quick working stuff now without ordering new hardware and wait for that. I will later find a suitable/better hardware.

    software solution that modifies pymodbus

    Find the file "sync.py" in the folder "client", to modify the client/master side of your setup.

    I modify the client/master here, as I have the 'poor' RS485 hardware on that side. If you have two of these 'poor' hardware things, you might need to modify the server side too.

    The file sync.py can probably be found in

    ~/.local/lib/python3.5/site-packages/pymodbus/client

    This may vary according to the python version you use. Mine is 3.5 for now. The "~/" part means that it is in your home folder. The dot in front of "local" makes the file hidden as standard. In a terminal can you use the command "ls -al" to show hidden files too. The graphical user interface of your Linux distribution will surely be able to show hidden files too somehow.

    In the beginning of the file "sync.py", ad the following code:

    import RPi.GPIO as GPIO
    pin_de_re = 7
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(pin_de_re, GPIO.OUT, initial=GPIO.HIGH)
    

    This can look somehow like the following:

    more imports ...
    
    from pymodbus.transaction import ModbusSocketFramer, ModbusBinaryFramer
    from pymodbus.transaction import ModbusAsciiFramer, ModbusRtuFramer
    from pymodbus.client.common import ModbusClientMixin
    
    import RPi.GPIO as GPIO
    pin_de_re = 7
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(pin_de_re, GPIO.OUT, initial=GPIO.HIGH)
    
    # --------------------------------------------------------------------------- #
    # Logging
    # --------------------------------------------------------------------------- #
    import logging
    _logger = logging.getLogger(__name__)
    
    ...more code
    

    Set the pin number as you choose. I have my control pin as GPIO4 - that is pin 7 in the Raspberry Pi/BananaPi.

    Next you scroll down and find the section called

    # --------------------------------------------------------------------------- #
    # Modbus Serial Client Transport Implementation
    # --------------------------------------------------------------------------- #
    

    I modify this section, as I use Modbus RTU and hence serial for transmission of the data.

    In that section you have to find the definition of "send":

        def _send(self, request):
            """ Sends data on the underlying socket
    

    Inside that function, find the line:

                size = self.socket.write(request)
    

    And embrace it with the control of the pin:

                _logger.debug("GPIO - Setting pin high")
                GPIO.output(pin_de_re, 1)
                time.sleep(.300)
                size = self.socket.write(request)
                time.sleep(.300)
                _logger.debug("GPIO - Setting pin low")
                GPIO.output(pin_de_re, 0)
    

    The reason I use the lines '_logger.debug("GPIO - Setting pin high/low")' is that I then can see in the log in the terminal, that the program executes these things, and I can be assured if they are performed. If they don't show up in the log, I have done it in the false place - or something else...

    The reason to use time.sleep(.300) is to let the hardware have time for act. .300 is 0.3 seconds. A big number in this context.

    When I use the above solution, I get the following logs.

    Slave/server:

    2019-07-07 23:08:43,532 MainThread      DEBUG    sync           :45       Client Connected [/dev/ttyUSB0:/dev/ttyUSB0]
    2019-07-07 23:08:43,533 MainThread      DEBUG    sync           :522      Started thread to serve client
    2019-07-07 23:08:47,534 MainThread      DEBUG    rtu_framer     :232      Frame check failed, ignoring!!
    2019-07-07 23:08:47,535 MainThread      DEBUG    rtu_framer     :128      Resetting frame - Current Frame in buffer - 0x3 0x4 0x0 0x1 0x0 0x82
    2019-07-07 23:08:59,543 MainThread      DEBUG    rtu_framer     :180      Getting Frame - 0x4 0x0 0x1 0x0 0x2
    2019-07-07 23:08:59,544 MainThread      DEBUG    factory        :137      Factory Request[ReadInputRegistersRequest: 4]
    2019-07-07 23:08:59,544 MainThread      DEBUG    rtu_framer     :115      Frame advanced, resetting header!!
    2019-07-07 23:08:59,544 MainThread      DEBUG    context        :64       validate: fc-[4] address-2: count-2
    2019-07-07 23:08:59,544 MainThread      DEBUG    context        :78       getValues fc-[4] address-2: count-2
    2019-07-07 23:08:59,545 MainThread      DEBUG    sync           :143      send: [ReadRegisterResponse (2)]- b'030404000500050846'
    
    

    Master/client:

    ModbusSerialClient(rtu baud[115200])
    2019-07-07 23:08:55,839 MainThread      DEBUG    pymodbus_sync_client_example_2019.07.05-1319:165      ===================================
    2019-07-07 23:08:55,840 MainThread      DEBUG    pymodbus_sync_client_example_2019.07.05-1319:166      Read input registers
    2019-07-07 23:08:55,841 MainThread      DEBUG    pymodbus_sync_client_example_2019.07.05-1319:167      
    2019-07-07 23:08:55,842 MainThread      DEBUG    transaction    :111      Current transaction state - IDLE
    2019-07-07 23:08:55,842 MainThread      DEBUG    transaction    :116      Running transaction 1
    2019-07-07 23:08:55,843 MainThread      DEBUG    transaction    :215      SEND: 0x3 0x4 0x0 0x1 0x0 0x2 0x21 0xe9
    2019-07-07 23:08:55,843 MainThread      DEBUG    sync           :79       New Transaction state 'SENDING'
    2019-07-07 23:08:55,844 MainThread      DEBUG    sync           :538      GPIO - Setting pin high
    2019-07-07 23:08:55,845 MainThread      DEBUG    sync           :541      GPIO - Setting pin low
    2019-07-07 23:08:55,845 MainThread      DEBUG    transaction    :224      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
    2019-07-07 23:08:59,516 MainThread      DEBUG    transaction    :300      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
    2019-07-07 23:08:59,518 MainThread      DEBUG    transaction    :229      RECV: 0x3 0x4 0x4 0x0 0x5 0x0 0x5 0x8 0x46
    2019-07-07 23:08:59,519 MainThread      DEBUG    rtu_framer     :180      Getting Frame - 0x4 0x4 0x0 0x5 0x0 0x5
    2019-07-07 23:08:59,519 MainThread      DEBUG    factory        :266      Factory Response[ReadInputRegistersResponse: 4]
    2019-07-07 23:08:59,520 MainThread      DEBUG    rtu_framer     :115      Frame advanced, resetting header!!
    2019-07-07 23:08:59,521 MainThread      DEBUG    transaction    :379      Adding transaction 3
    2019-07-07 23:08:59,522 MainThread      DEBUG    transaction    :390      Getting transaction 3
    2019-07-07 23:08:59,522 MainThread      DEBUG    transaction    :189      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
    ReadRegisterResponse (2)
    

    The transmission does MAYBE not always, but it pinpoints the cause of the problem and hence potential solutions.

    I do not yet know what I will end up with. More stable hardware is for sure.

    Regards modifying pymodbus or other software with respect to this issue, would I like to quote from the following post in another threat:

    Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

    A solution on the hardware side is preferable.

    Thanks to Marcos G.

提交回复
热议问题