Modbus TCP with register array > 255

Hi @derekyu

Can you try writing to Modbus holding register 1004h with a value greater than one and then try writing to one of your ADIs to see if the callback issue is still occurring?

I am not sure I understand what you want me to do?

  1. Do you want me to write to holding register 1004h after I removed the mappings of ADIs ?
  2. How do I write to one of the ADIs?

Could you write 1 to HR 0x1004, then attempt to write the ADI?

In this mode the read process data area will not be active. But you should be able to write HR 4256 or 5264 (I believe these map to his ADI 10 and 73) and only these individual ADIs’ callbacks should be triggered.

After removed the ADI mappings, I tried to write to HR #4100, HR #4256 and HR #5264. None of the callbacks were being triggered. After these tests, I added callbacks to all instances (from FIRST_INSTANCE to FIRST_INSTANCE+77) and rerun the tests. Again, none of the callbacks were being triggered.

How do I write the ADI?

We forgot to include the offset that you were using when we did our example. With your MOD_IA_RW_OFFSET_WRITE_VALUE and MOD_IA_RW_OFFSET_READ_VALUE set to 0xFBE0 in the SDK you should:

  • Write a value of 1 to holding register #5156 to put the slave into IDLE.
  • Write ADI #10 using holding register #5312 And ADI #73 with holding register #6320

This is also assuming that the ADI indexing bits attribute in the Modbus host object is using the default value which translates to 16 Modbus registers per ADI.

One other thing,

It’s important for the whole ADI to be written to in order for the write to be accepted by the compactcom. Since your ADIs use 64 elements as set by your “NUM_REGS”, you’ll need to write 64 modbus registers to completely address your ADI. You should be able to do this using the write mulitple registers modbus command.

I wrote 1 to the HR #5156, HR #5312 and HR #6320. None of them triggered the callbacks.

I made no change to the ADI indexing bit so it is using the default value.

This is unrealistic. Our application will never write 64 modbus registers at the same time. Are you saying that I cannot write to only 1 modbus register?

Hi Derek,

Unfortunately if you want to write into the ADI area you’ll need to make sure that you’re writing to each element of that modbus register at once or the CompactCom won’t allow the Write.

These seem to be our options:

  • Make each modbus register represent 1 ADI, this way you would only be doing write single registers
    Advantage: Can do individual callbacks, Can do individual register writes
    Disadvantage: Lots of ADIs

  • Use process data like you were originally
    Advantage: Same amount of ADIs, Can write to individual ADIs
    Disadvantage: Can’t trigger individual callbacks. A counter measure for this would be to no use the ADI callback functionality of the SDK and use your own logic.

  • Write to the ADIs with write Multiple registers
    Advantage: Same number of ADIs, Can Trigger Indivual Callbacks
    Disadvantage: Can’t write to single registers

I really don’t understand why something that I can do easily using the WEB interface is so difficult to do in the Modbus API. This is unacceptable. Can I talk to someone who is more knowledgeable in the Modbus API?

I see that there is an option to Enable Modbus message forwarding so that all Modbus messages, addressed to this node are routed to the application. Can you tell me the mechanic to receive these messages (register callback??) and if possible, response to these messages.

This is something that would be possible but it would require you to write how the Modbus would be communicating instead of modifying the SDK.

You’ll need to implement the Modbus “Process-modbus-message” command that is called by the ABCC to the modbus host object at instance 0.

I want to know how I can get notified on modbus messages received. There is no description on this feature in the documentation.

It looks like Process-modbus-message is the command that gets called.

In the SDK the abp.h file has a define “ABP_MOD_CMD_PROCESS_MODBUS_MESSAGE” You’ll need to add this to the modbus host object’s handler in abcc_obj/nw_obj/mod.c

In the document it states, this object is “Valid for: object” so this means the command is to be added to the ObjectCommand (not the InstanceCommand) handler

So in ObjectCommand there is a switch-case for ABCC_GetMsgCmdBits() this is where you would add a new case for this command and handle it according to the documentation in the modbus network guide

However, this does assume that MOD_IA_MESSAGE_FORWARDING_VALUE is enabled

I was able to intercept the incoming Modbus TCP messages. How can I send back the response messages to the caller?

Hi @derekyu

The example we’re providing for you currently assumes various uint16 variables in the modbus payload as being ordered in Big Endian notation.

mod.c (16.4 KB)

this is a modified version of the mod.c section of the SDK that should be be found in abcc_obj\nw_obj\mod.c
(This assumes that your abcc object configuration header file has been configured to enable forwarding of process message commands)

This code should provide you with an example on how to respond to Process Modbus Message commands.

It may be useful to take a look at the Software design guide on section 10 if you’re unfamiliar with the Anybus Object messaging system.

It looks like I have no choice but to use message forwarding and handling the Modbus commands myself. The M40 module simply becomes a regular network interface. It really defeats the purpose of using the M40 module.

In my opinion, the Modbus API design is convoluted. If I use Process Data, all callbacks will be triggered and I have no easy way to determine which registers have been updated. If I use the ADI, the Modbus client need to update all 64 elements to trigger the callback. This is not Modbus protocol anymore. Please consider improving the APIs. In its current form, it really is of little values to the customers.