I'm currently facing some challenges with addressing holding registers in Modbus communication within the Ignition SCADA software. I've been working with the official Modbus specification, but I'm running into issues that I hope someone can help clarify.
Here's the context:
Address Ranges: According to the Modbus spec, The addresses are 20480-20735 (0x5000-0x51FF) are not holding registers. However, I understand that holding registers are typically in the 40xxx range (e.g., 40108-40110).
Error in Ignition: When I attempt to use the 20xxx addresses in Ignition, I receive an error, indicating these addresses may not be valid or recognized.
Clarification Needed: I need to understand how to correctly reference holding registers in Ignition. For example, in the Modbus documentation, addresses 108-110 are reference points and correspond to actual addresses 107-109 (in hex as 6B-6D).
Has anyone else encountered this issue or can guide how to properly configure and use holding register addresses in Ignition? Any examples or detailed explanations would be greatly appreciated.
Whose Modbus Spec? The officialModbus Specification disagrees with whatever you are looking at.
And device makers don't have to implement everything, so device-specific address ranges abound.
It seems to me you are stumbling on the "area prefix" the Modbus Spec calls out for various types of data. To summarize:
Area zero: Output coils and other writable booleans. Classic address range 00001 through 09999, expanded to 000001 through 065536, on the wire with function codes 0x01 and 0x05 and 0x0f as 0x0000 through 0xffff. In Ignition as Cn, where n is 1-65536 or 0-65535 depending on your zero-based-addressing setting.
Area one: Discrete inputs or other readonly booleans. Classic address range 10001 through 19999, expanded to 100001 through 165536, on the wire with function code 0x02 as 0x0000 through 0xffff. In Ignition as DIn, where n is 1-65536 or 0-65535 depending on your zero-based-addressing setting.
Area three: Analog input registers and other readonly short integers. Classic address range 30001 through 39999, expanded to 300001 through 365536, on the wire with function code 0x04 as 0x0000 through 0xffff. In Ignition as IRn, where n is 1-65536 or 0-65535 depending on your zero-based-addressing setting.
Area four: Holding registers and other writable short integers. Classic address range 40001 through 49999, expanded to 400001 through 465536, on the wire with function code 0x03 and 0x06 and 0x10 and 0x16 as 0x0000 through 0xffff. In Ignition as HRn, where n is 1-65536 or 0-65535 depending on your zero-based-addressing setting.
Any of the "classic" or "expanded" formats need to have their prefix digit stripped off before using with Ignition's character-based prefixes. You kind of have to read the device maker's programmers' minds sometimes, but when hexadecimal is shown for an address, it almost always means the zero-based offset intended for use "on the wire". And most commonly means it is a holding register.
Your device should have more information, possibly scattered or in examples, to help you decipher what they've done.
There's also an area six, "File Records", that isn't supported by Ignition's native driver. See my alternate driver if you need that:
It isn't, for sure, a holding register address. Offsets of addresses within the modbus protocol are 16-bit unsigned integer, where the first element is offset zero. 0x5017 could be an offset within any of the areas. Your engineers need to be explicit about what function code(s) go with that offset. Then you will know for sure what kind of address it is.
Have your engineers looked at Ignition's addressing documentation?
Consider also pointing your engineers at the documentation for my alternate driver, and the sections on "supported function codes" and "supported address formats".
As @pturmel points out, 0x5017 is an allowable offset for any of the primary tables in the Modbus data model. As described in the Modbus Application protocol (the document linked by @Thomas_Salisbury ) sections 4.3 and 4.4 describe how the data may be arranged and addressed. You will notice there is no mention of the numerical prefixes (e.g. 40xxx) in these sections.
Figuring out how to pull data from a Modbus device can be more difficult than it has to be at times, I sympathize with you. From the screenshot that @Emmanuel_Akinwale provided, we can see a write message for a holding register with offset 0x5017 from slave addresses 64, 65, & 66 on rows 11-13. The value in the write was 0.
It's hard for me to say what the cause of this is without more information. Could you provide the exact error you are seeing? 20XXX could be a valid offset for a holding register as far as Ignition is concerned, so it is likely the error you are seeing is related to the response we get from the device. I have no experience with Moxa MGate devices, but I would recommend checking to see if you have specified the correct unit id, if required.
If you can provide more information about your use case, I would be happy to help you figure this out.
I just went through reading some PAC3220 devices from SIEMENS via MODBUS TCP. I got BADs all day long until I used Chipkin Modbus Scanner that michael.flagler referenced and found out device 0 doesn't allow for any functions. Added a 1. in front of my path, for example, [Modbus Device]1.HRF7, and that got me going. Also had to set the config to start at 0 for offsets.
Yes, it is very common for the Modbus TCP server to require a unit id when it is serving as a gateway for multiple Modbus serial devices. I suggested checking this in an earlier reply. From the screenshot above, the use case would lead me to think a unit id is necessary.
I was confused when I was implementing it as I only have two devices. They each have their own IP. So in my mind there was just one device per connection.
In your case, it's possible the PAC3220 devices don't necessarily need a unit id, but reject 0 as the broadcast unit id. I believe the specification recommends using 255 when a unit id is not necessary, but the Modbus driver in Ignition defaults to 0. This isn't recommended, but is often accepted.