Modbus I/O Mapping

Dear all,

This is my first project in codesys and I am experiencing a problem with reading data via Modbus TCP in a setup where one controller (PLC in the form of an HMI panel running CoDeSys) is connected to two WAGO couplers:


Coupler 1 (Modbus_TCP_Slave_Pump_starter)

  • 750-1405 – Digital Input, 16 channels (offset: 16#0000, using Read Discrete Inputs) – :white_check_mark: works
  • 750-430 – Digital Input, 8 channels (offset: 16#0002, using Read Discrete Inputs) – :cross_mark: does not work
  • 750-530 – Digital Output, 8 channels (offset: 16#0000, using Write Multiple Coils) – :white_check_mark: works
  • 750-474 – Analog Input, 2 channels (offset: 16#0000, using Read Holding Registers) – :white_check_mark: works
  • 750-515-1 – Digital Output, 4 channels (offset: 16#0001, using Write Multiple Coils) – :cross_mark: does not work
  • 750-515-2 – Digital Output, 4 channels (offset: 16#0002, using Write Multiple Coils) – :cross_mark: does not work
  • 750-515-3 – Digital Output, 4 channels (offset: 16#0003, using Write Multiple Coils) – :cross_mark: does not work

Coupler 2 (Modbus_TCP_Server_Mcc)

  • 750-508 – Digital Output, 2 channels (offset: 16#0000, using Write Multiple Coils) – :white_check_mark: works
  • 750-508 – Digital Input, 2 channels (offset: 16#0000, using Read Discrete Inputs) – :white_check_mark: works
  • 750-1405 – Digital Input, 16 channels (offset: 16#0001, using Read Discrete Inputs) – :cross_mark: does not work
  • 750-430 – Digital Input, 8 channels (offset: 16#0003, using Read Discrete Inputs) – :cross_mark: does not work
  • 750-1504 – Digital Output, 16 channels (offset: 16#0001, using Write Multiple Coils) – :cross_mark: does not work

The issue is that only the modules configured with offset 16#0000 are working correctly. Any module configured with offsets greater than 16#0000 (e.g. 16#0001, 16#0002, etc.) does not reflect any state changes in the PLC program – even though the physical input signal is received (as confirmed by the input module LED turning on).

There are no Modbus TCP communication errors, and the connection is active. All address assignments and lengths have been configured according to WAGO documentation. I suspect this may be related to address range limitations, but I have not found any setting in CoDeSys or the WAGO documentation that would explain or resolve this behavior.

Are there any additional configuration steps required to allow Modbus TCP to correctly access input/output modules at offsets beyond 16#0000?

I have attached screenshots showing the full configuration of the Modbus server and variable mappings.

Thank you in advance for your help.

Hello dabgregory,

for bit-based function codes, you must also specify the offset in a bit-based manner. Additionally, I would try to implement the query with as few jobs as possible. This generates significantly less load and you can take advantage of the limit for the function codes.

Example Coupler 1:
Read Coils FC1 → offset 0, reading length 24 (750-1405 + 750-430)
Read Holding Register FC3 → offset 0, reading length 2 (750-474)
Write Multiple Coils FC15 → offset 512, writing length 20 (750-530 + 3x750-515)

Example Coupler 2:
Read Coils FC1 → offset 0, reading length 28 (2x 750-508 DIAG + 750-1405 + 750-430)
Write Multiple Coils FC15 → offset 512, writing length 20 (2x 750-508 + 750-1504)

1 Like

Thank you for your clarification regarding using bit-based offsets with FC1/FC2 and grouping modules into fewer jobs to reduce load.

However, I have one follow-up question:
In your example, you suggest grouping multiple physical I/O modules (e.g., 750-1405 + 750-430) into a single channel with one offset (e.g., FC1, offset 0, length 24).

From what I understand, this would mean using only 2–3 channels per coupler, where each channel covers multiple modules — instead of defining one Modbus channel per module.

My current setup creates a separate channel for each I/O module, assigning an individual offset and length.
This approach aligns with how the configuration is structured in the CoDeSys interface (each module has its own ChannelConfig block).

My question is:

Should I consolidate several modules into one Modbus channel (e.g., one for all digital inputs on a coupler), or is it still recommended to keep one channel per module?

Also, how does the physical order of the modules on the coupler affect this? Should I strictly follow their physical arrangement to avoid overlapping or misaligned addresses?

Thank you again for your help —

Hello dabgregory,

in the end, you can do both variants. Personally, it is easier for me to simply count the number of digital inputs, for example, and project them. In extensive projects, where a lot of load is already generated or where quick queries are needed, I would always recommend summarizing the modules.