Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modbus feature request: scaling and offset #9725

Closed
wz2b opened this issue Sep 6, 2021 · 5 comments · Fixed by #13227
Closed

Modbus feature request: scaling and offset #9725

wz2b opened this issue Sep 6, 2021 · 5 comments · Fixed by #13227
Assignees
Labels
area/modbus feature request Requests for new plugin and for new features to existing plugins

Comments

@wz2b
Copy link

wz2b commented Sep 6, 2021

This feature request expands on #9279 to add one additional feature: scale/offset of registers.

I would like to propose adding optional 'scale' (default 1.0) and 'offset' (default 0.0). The use case for this is devices that report in integers but with some scaling, usually a power of 10. An example of this is the main power factor register set on a PowerLogic PM800 which is an integer register that reports a value of 0-2000. This value corresponds to the power factor of 0 to 2, so to get that number you have to multiply by 0.001. A second use case is unit conversion - for example reading a register that is in celsius but outputting it as Fahrenheit.

The output of any scaled value has to be either a double or a float. Ideally we would store these internally as doubles to minimize the ULPS of a float being misleading (you want to report 12 but because of floating point error it comes out as 11.99998).

When converting:

  1. Read the register in the register format specified by the user, then convert it to a double
  2. Multiply by the scale (may be a fraction)
  3. Add the offset (may be negative)
  4. Output the result as a double

In this example register 2000 is a floating point number in degrees C and I want to convert it to degrees F. In the second example, the power factor is a number from 0 to 2000 that needs to be converted to a power factor which means 0 to 2 with 1 being unity power.

  fields = [
    { address=2000, name = "degreesF", type = "FLOAT32", scale = 1.8, offset = 32 },
    { address=2004, name = "power_factor", type = "UINT", scale =0.001, offset = 0}
  ]

image

In this example, register 1190 (read as a 16-bit signed integer) has to be divided by 1000 to yield a result (the power factor) between -1 and +1.

Note that this is not at all specific to the PM800. That was just the first device I had access to. Three are quite a few devices that operate this way, in part because floats weren't supported in many early Modbus devices.

Playing devil's advocate, you could do this transmogrification in a processor but this behavior is so common across modbus devices that it really becomes cumbersome. Most off the shelf devices you can use for this kind of conversion - for example the CCS Babel Buster - allow you to specify scale/offset conversions in the manner I describe, so I think it should be part of the Modbus plugin itself.

@wz2b wz2b added the feature request Requests for new plugin and for new features to existing plugins label Sep 6, 2021
@srebhan
Copy link
Member

srebhan commented Sep 6, 2021

@wz2b: Just for your information, a scale factor already exists doing exactly what you describe. However, currently we do not support an offset but I can see that this might be a reasonable feature.

@srebhan srebhan self-assigned this Sep 6, 2021
@TimurDela
Copy link
Contributor

Another use case for an offset is when I am reading analogue signals for which the offset and scale can be tuned in the device.
For instance, I have a power meter that outputs 4 analogue signals via Modbus RTU.
I have set Channel 1 to give the voltage (V) but the signal Telegraf receives is an intensity (I) in mA. The conversion is V = a × I +b where 'a' and 'b' can be set in the settings of my power meter.
If I am to do the conversion in the queries, this means I have to log 'a' and 'b' as well which is not convenient at all. Having them as tags is not very convenient are they are numerical values. I'd rather directly log via Telegraf the quantity I am interested in rather than 3 numbers that are meaningless if taken separately.

The 'scale' feature is great, please also add 'offset'.

@srebhan
Copy link
Member

srebhan commented May 6, 2022

@TimurDela the question is a bit where to stop. You can currently do the computations using the starlark plugin. But maybe should probably do the offset thing... Are you willing to cook up a PR please?

@TimurDela
Copy link
Contributor

TimurDela commented May 6, 2022

@srebhan I now see that indeed the starlark plugin can be used for this. Can I suggest writing a more explicit description for that plugin so people looking for mathematics, operation, offset, scale, gain etc get a chance to understand that this plugin is for them? I was not able to identify this plugin was for me by searching for some keywords in the processor plugin catalogue.

TimurDela pushed a commit to TimurDela/telegraf that referenced this issue May 8, 2022
Minor changes:
* remove unused functions (type conversions without scale)
* reorder some checks (name was called in error message before checking it existed)
* adds new 'shift' property to add a constant to the register value
@srebhan
Copy link
Member

srebhan commented May 9, 2022

@TimurDela can you please submit a PR for the starlark processor with improved docs? I already check your PR, comments there...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/modbus feature request Requests for new plugin and for new features to existing plugins
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants