I’m trying to use Modbus RTU over TCP for the first time but so far I’m not able to read values.
I’m trying to read data from a flow meter. The flow meter can communicate with RS485, so we installed an USR-TCP232-306 to convert to TCP so that Ignition can read it.
I connected a laptop to the USR, and using Modbus Poll I was able to read some values and confirm they are good values. The register I’m interested to read has 175 as address, and the device ID of the flow meter is 2.
I can see in Ignition that the USR is connected, and I tried to add a tag with OPC item path ‘ns=1;s=[Bubbler]2.HR175’ (I believe the path is supposed to be ‘deviceID**.HR**register’) but the quality of the tag is bad and I have ‘Bad("Bad_NotConnected: The variable should receive its value from another variable.")’
Am I missing something ?
In addition to Kevin's advice, make sure the converter is buffering complete messages, I have no specific recommendations for USR, but I have an appendix for my alternate driver with related advice for Moxa converters.
However the quality of the tags is doing a back and forth between Good and Bad, I assume it’s because Ignition is doing the request.
How do you usually convert what you are reading from the registers to the correct value ? The flow meter has several registers: 175 for flow rate, 280 for total flow. I assumed that I have to use registers 175 and 176 to calculate the flow rate, and 280 and 281 for the total flow, so I added this script for register 280 and 281 on On Value Changed:
`import struct
register280 = system.tag.readBlocking(["[default]Monitoring/Bubbler/Register 280"])[0].value
register281 = system.tag.readBlocking(["[default]Monitoring/Bubbler/Register 281"])[0].value
if isinstance(register280, (int, long)) and isinstance(register281, (int, long)):
bytes_reg1 = struct.pack('>H', int(register280))
bytes_reg2 = struct.pack('>H', int(register281))
float_bytes = bytes_reg2 + bytes_reg1
flow_rate_bytes = struct.unpack('>f', float_bytes)[0]
ratio = 0.0037854118
total = flow_rate_bytes / ratio
system.tag.writeBlocking(["[default]Monitoring/Bubbler/Total Flow"], [total])`
This is just temporary for now, later I’m planning to run this script just once per day (don’t need more).
For the ratio, I’ve read several Total Flow values on the flow meter and the values of the registers 280 and 281, and I calculated a ratio based on that, and at the end I’m able to find the same Total Flow value than on the flow meter with a one decimal precision. But I don’t feel this is the right way of doing. Is there another way of doing it ?
Thanks
The script is unnecessary, just use the right address syntax to address a 32-bit value instead, e.g. 2.HRUI175 or 2.HRI175. Maybe 1.HRF175 if it's actually in floating point format and not an integer that needs scaling.
You may also want to try turning off the "Span Gaps" setting. It's not uncommon for devices to not respond or close the connection if you request a register that doesn't exist.