'Pymodbus Basic Example

I have a simple modbus device (Ebyte MA02-XACX0440) that I'm trying to learn how to work with. Using a third party GUI called serial port monitor (www.serial-port-monitor.org) I was able to more or less "stumble upon" the proper hexadecimal inputs needed to turn a discrete output on and then off. I don't understand these terms of unit, address, coils, registers, etc. and how it all relates when it comes to the hexadecimal aspect. To break down what I think I know so far (below is the hexadecimal string that will turn the first discrete output 'ON'):

0x20 0x05 0x00 0x00 0xFF 0x00 0x8A 0x8B

I know 0x20 is the device address in hex. The documentation of the Ebyte device stipulates that the default hardware address is '31' and that the first software address is '1'. If I understand that correctly, that means my first physical modbus device on the line has an address of '32', and if I were to put additional modbus devices on the line (either RS485 or TCP(?)) that the next device would be '33' and so on.

I know that the next byte 0x05 is 'write coil'.

I don't know what the next two bytes of '0x00' and '0x00' refer to.

The next two bytes are essentially on/off with '0xFF00' being 'ON' and 0x0000 being 'OFF'.

The final two bytes are simply the CRC checksum.

So up to this point I can get my DO (Discrete Output) to turn on, open up, and light up an LED as a simple proof of concept. Now when I take that approach over to using the pymodbus library (my ultimate goal), things don't seem to line up.

I am able to connect to my device using the pymodbus REPL using

pymodbus.console serial --baudrate 9600 --bytesize 8 --parity N --stopbits 1 --port /dev/cu.usbserial-AH01F4EN

I can confirm that the device is connected:

    ----------------------------------------------------------------------------
__________          _____             .___  __________              .__
\______   \___.__. /     \   ____   __| _/  \______   \ ____ ______ |  |
 |     ___<   |  |/  \ /  \ /  _ \ / __ |    |       _// __ \\____ \|  |
 |    |    \___  /    Y    (  <_> ) /_/ |    |    |   \  ___/|  |_> >  |__
 |____|    / ____\____|__  /\____/\____ | /\ |____|_  /\___  >   __/|____/
           \/            \/            \/ \/        \/     \/|__|
                                        v1.3.0 - [pymodbus, version 2.5.3]
----------------------------------------------------------------------------

> client.connect
true

However when I attempt to run the same commands that I did earlier with serial monitor, I'm having difficulty mapping the hexadecimal values to the integers expected by the 'client.write_coil' command in pymodbus:

    > client.write_coil address=32 value=255 unit=1
{
    "original_function_code": "5 (0x5)",
    "error": "[Input/Output] No Response received from the remote unit/Unable to decode response"
}

What is meant by address? Is this a coil/register address or a device address? For 'value' I put '255' as that would be all bits flipped to a '1' thinking that would be considered 'ON', and that a value of '0' would be off. I also tried '65280', which is what 0xFF00 would be in decimal. What is meant by a unit? Is that the previous value I determined to be '32' to target the specific device on the line? Or is it possible that the address would be '31' (which is the hardware address) and then the unit address is '1', making the overall 'address' 32?

EDIT: This is shown in the 'help' of the client.write_coil command, but still doesn't help me figure out how to put the right pieces in the right places. I don't know what a 'coil offset' is and how that relates to the discrete outputs. I don't see anything mapped to the hexadecimal string that would be considered a 'coil offset'. This is being provided for context to those that may know how to properly form the request.

enter image description here

I also sometimes get this error, and it's not consistent. If it was a permissions issue one would think you'd get it every single time? I don't think it makes sense to be either changing the permissions of the file indicated or to run the pymodbus server with root permissions.

    Unhandled exception in event loop:
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/input/vt100.py", line 170, in callback_wrapper
    callback()
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 708, in read_from_input
    self.key_processor.process_keys()
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 271, in process_keys
    self._process_coroutine.send(key_press)
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 186, in _process
    self._call_handler(matches[-1], key_sequence=buffer[:])
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 321, in _call_handler
    handler.call(event)
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 124, in call
    result = self.handler(event)
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/shortcuts/prompt.py", line 798, in _accept_input
    self.default_buffer.validate_and_handle()
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1877, in validate_and_handle
    self.append_to_history()
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1385, in append_to_history
    self.history.append_string(self.text)
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/history.py", line 74, in append_string
    self.store_string(string)
  File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/history.py", line 295, in store_string
    with open(self.filename, "ab") as f:

Exception [Errno 13] Permission denied: '../.pymodhis'
{ress ENTER to continue...


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source