Modbus analog negative register value

I am modbus polling an RTAC with openHistorian to store the power flows of multiple sources. As these flows change direction the values recorded within the RTAC holding registers as positive or negative. When polled by the openHistorian the negative values are captured as FFFF (65535) minus actual value from the RTAC. Does the modbus adapter have the capability to handle these type of analog values so as to not max out the register? Not sure what I am overlooking.

Individual registers are read as ushort in the base code - are you dealing with two states, i.e., 0x0000 and 0xFFFF representing a positive (0) and negative (-1) value?

Otherwise the first bit would represent the “sign” of the value.

Just asking so I can best guide a proper solution.

Sounds to me like this may just be a two’s complement integer, given the description of 0xFFFF minus the actual value.

@StephenCWills: yeah could be.

@jthompson: also assuming you are reading an input or holding register, not a discrete input or coil as these are more like “boolean” values.

Yes, I am reading an analog from a holding register. The 2’s complement is what I am experiencing. My confusion is how to get OH to interpret the register appropriately. I thought by using the analog input in OH the interpretation would occur.

Currently experiencing this.
The raw data would be +100 = 100 (int) and -100 = 65435 (int). Thus when I represent the info in grafana the chart range explodes for the negative value.

I also forgot to mention the register be read from the RTAC is a 16-bit signed MSB.

The list of derived types for the MODBUS adapter does not include a 16-bit signed integer type, so that explains the difficulty you’re having. We’ll work to add the functionality ASAP, but we can’t provide a schedule for the fix. As a workaround, you may be able to use some of the Grafana functions to conditionally adjust the value so you can fix the range on your Grafana chart.

Grafana Functions (

Thanks for the quick follow up. I appreciate you guys’ assistance. I will dig into the grafana functions in the meantime.

FYI, it might not be immediately obvious how to use the Grafana functions here since there aren’t any explicit conditional functions. Ritchie and I discussed this offline, and we decided that you might be able to use the IncludeRange and ExcludeRange functions to make this work. However, my initial thought when I made the suggestion was instead to use some mathematical trickery to fix your series. The following is untested, but should theoretically work.

So let’s say you’re working with a series identified by the PPA:12 measurement key. The following expression will essentially create a mask of zeros and ones based on the size of each value in the original series.
Ceiling(Divide(32768, Floor(Divide(32768, PPA:12))))

With a mask like that, you can multiply by -65536 and then add it back to the original series to produce the series of corrected values.
SliceAdd(0, Multiply(-65536, Ceiling(Divide(32768, Floor(Divide(32768, PPA:12))))) ; PPA:12)

I hope this helps, good luck!

@StephenCWills, The Grafana functions assistance was quite helpful. I had not come across the link you provided for those definitions before. The graphing is working great based information provided. Thanks for all of yours and @ritchiecarroll assistance. I look forward to the adapter adjustment in the future to handle signed 16 bit.

Slight modification to your Grafana query syntax to make the expression work:
SliceAdd(0, PPA:12, Multiply(-65536, Ceiling(Divide(32768, Floor(Divide(32768, PPA:12))))); PPA:12)

I guess I was thinking of SliceSum rather than SliceAdd. Also, while we’re tweaking things, it occurs to me that the Ceiling(Divide(...)) is likely unnecessary.
SliceSum(0, Multiply(-65536, Floor(Divide(32768, PPA:12))); PPA:12)