brainelectronics / micropython-modbus

MicroPython Modbus RTU Slave/Master and TCP Server/Slave library
GNU General Public License v3.0
104 stars 45 forks source link

Allow client register access and setting at any position #53

Closed brainelectronics closed 1 year ago

brainelectronics commented 1 year ago

Added

Fixed

brainelectronics commented 1 year ago

@beyonlo this now resolves all your issues regarding not following the specification on client side, #15, #24 and #35

brainelectronics commented 1 year ago

You can test the changes in 2.3.1-rc26.dev53 available from Test PyPi MicroPython Modbus

beyonlo commented 1 year ago

Excellent!!!! Works like a charm! :tada: :balloon: You are the best @brainelectronics

Everything works fine in this PR! I tested using COILS and HOLDING REGISTERS. Very nice, that's working is so beautiful!

register_definitions = {
    "COILS": {
        "RESET_REGISTER_DATA_COIL": {
            "register": 42,
            "len": 1,
            "val": 0
        },
        "EXAMPLE_COIL": {
            "register": 123,
            "len": 26,
            "val": [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0]
        }
    },
    "HREGS": {
        "EXAMPLE_HREG": {
            "register": 93,
            "len": 9,
            "val": [29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456]
        }
    },
    "ISTS": {
        "EXAMPLE_ISTS": {
            "register": 67,
            "len": 1,
            "val": 0
        }
    },
    "IREGS": {
        "EXAMPLE_IREG": {
            "register": 10,
            "len": 1,
            "val": 60001
        }
    }
}

Slave:

$ mpremote run tcp_client_example.py 
Running ModBus version: 2.3.1-rc26.dev53
Waiting for WiFi connection...
Waiting for WiFi connection...
Waiting for WiFi connection...
Connected to WiFi.
('192.168.1.4', '255.255.255.0', '192.168.1.1', '192.168.1.1')
Setting up registers ...
Register setup done
Serving as TCP client on 192.168.1.4:502
Custom callback, called on getting COILS at 123, currently: [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0]
Custom callback, called on setting COILS at 148 to: [False]
Custom callback, called on getting COILS at 123, currently: [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, False]
Custom callback, called on setting COILS at 148 to: [True]
Custom callback, called on getting COILS at 123, currently: [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, True]
Custom callback, called on getting HREGS at 93, currently: [29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Custom callback, called on getting HREGS at 93, currently: [29, 38, 0, 1600, 2150]
Custom callback, called on getting HREGS at 93, currently: [29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456]
Custom callback, called on getting HREGS at 93, currently: [29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456, 0]
Custom callback, called on getting HREGS at 98, currently: [5067]
Custom callback, called on getting HREGS at 95, currently: [0]
Custom callback, called on getting HREGS at 101, currently: [3456]

Master:

$ mpremote 
Connected to MicroPython at /dev/ttyACM1
Use Ctrl-] to exit this shell
>>> from umodbus import version
>>> print('Running ModBus version: {}'.format(version.__version__))
Running ModBus version: 2.3.1-rc26.dev53
>>> 
>>> 
>>> from umodbus.tcp import TCP as ModbusTCPMaster
>>> host = ModbusTCPMaster(slave_ip='192.168.1.4', slave_port=502, timeout=5)
>>> host.read_coils(slave_addr=10, starting_addr=123, coil_qty=26)
[True, True, True, True, True, True, True, False, True, True, True, True, True, True, False, True, True, True, True, True, False, True, True, True, True, False]
>>> host.write_single_coil(slave_addr=10, output_address=148, output_value=0)
True
>>> host.read_coils(slave_addr=10, starting_addr=123, coil_qty=26)
[True, True, True, True, True, True, True, False, True, True, True, True, True, True, False, True, True, True, True, True, False, True, True, True, True, False]
>>> host.write_single_coil(slave_addr=10, output_address=148, output_value=1)
True
>>> host.read_coils(slave_addr=10, starting_addr=123, coil_qty=26)
[True, True, True, True, True, True, True, False, True, True, True, True, True, True, False, True, True, True, True, True, False, True, True, True, True, True]
>>> host.read_holding_registers(slave_addr=10, starting_addr=93, register_qty=50, signed=False)
(29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
>>> host.read_holding_registers(slave_addr=10, starting_addr=93, register_qty=5, signed=False)
(29, 38, 0, 1600, 2150)
>>> host.read_holding_registers(slave_addr=10, starting_addr=93, register_qty=9, signed=False)
(29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456)
>>> host.read_holding_registers(slave_addr=10, starting_addr=93, register_qty=10, signed=False)
(29, 38, 0, 1600, 2150, 5067, 2564, 8450, 3456, 0)
>>> host.read_holding_registers(slave_addr=10, starting_addr=98, register_qty=1, signed=False)
(5067,)
>>> host.read_holding_registers(slave_addr=10, starting_addr=95, register_qty=1, signed=False)
(0,)
>>> host.read_holding_registers(slave_addr=10, starting_addr=101, register_qty=1, signed=False)
(3456,)
>>>
beyonlo commented 1 year ago

@brainelectronics those tests above I started using RTU (RS485), but as I had many CRC errors I changed to TCP mode, and works fine. I will now to do that tests requested by you in the #52