Hello, I am trying to convert a hexadecimal number from my PLC and having trouble doing it. The numbers are for a temperature sensor. The number in the PLC is 775 which means 77.5 degrees. When send over Modbus to Home assistant the number reads as 1,909. This is what I have for code so far. Any help would be great, thanks.
I believe you need to set the sensor’s scale option to 0.1 so that the 775 is understood to be 77.5.
However, there is the other issue of correctly representing the value’s units. Is your Home Assistant configured for metric or imperial units? (See Configuration > General > Unit System)
I think there’s also a conversion taking place as well (although not quite Celsius to Fahrenheit because 775 C is 1427 F, not 1909 F). That’s why I had asked what is the default unit system metric or imperial.
Anyway, you don’t appear to be interested in my suggestion to experiment with scale, or answer my question, so I’ll step aside. Hopefully someone else will assist you.
I stated the PLC data appeared to be in hexadecimal and the conversion from hex to decimal was the right number. Scaling would not work in that case I would assume. Maybe to move the decimal. I am interested but your not giving me much to work with here. I am not a YAML coder. Default imperial.
I’m a volunteer like everyone else here who offers assistance. In fact, I don’t even use the Modbus integration but read its documentation in order to help you. However, I do agree that using scale alone probably won’t produce the result you want. That’s why I am leaving the discussion and hopefully someone with far more Modbus experience will help you.
Blockquote
I’m a volunteer like everyone else here who offers assistance.
I understand. There are also people that don’t know where to look for the answers to the questions you are asking, like myself. I had to dig around.
Thanks for trying anyway.
FWIW, you might want to investigate the structure option. Unfortunately, there’s only one example of its usage in the documentation but it seems to suggest that you can indicate the data’s type. Sorry I can’t be of more help.
I searched the forum for “Modbus structure” and found this example:
data_type: custom
structure: ">1f"
However, you might also need to use the precision option to specify the number of decimal places. Here’s the source of the information (maybe its author can help you):
Not clue about the modbus hex/dec mismatch, but here is a crude way to go back from 1909 (i.e. 0x775) to 775:
Tested in template debugger.
{% set hex = 1909 %}
{% set m = hex // 4096 %}
{% set hex = hex - m *4096 %}
{% set c = hex // 256 %}
{% set hex = hex - c *256 %}
{% set d = hex // 16 %}
{% set u = hex - d *16 %}
{{ m*1000 + c*100 + d*10 + u }}
If you prepend 0x to an integer, the Jinja2 interpreter understands how to convert it to decimal.
You can’t add it to the Modbus configuration. You would have to create a Template Sensor to convert the value of sensor.temp1 to display the desired value. However, none of that is needed if you can get data_type and structure configured correctly.
I don’t think it’s a matter of format. An int is an int, ie.a bunch of bits at the end of the day. You can display it in base 2, 10 or 16, it’s still the same value.
There is likely a logic error somewhere, maybe in the PLC, that did a wrong conversion.
My reply was in reference to the example you posted containing several lines of calculations in Jinja2. It isn’t necessary to use all of that to make the Jinja2 interpreter convert a hex value into decimal (it just needs a hint that the value is hexadecimal).
As for the Modbus sensor, based on reading related posts, it’s not uncommon to receive hex values that must be converted to decimal. The solution lies in the correct use of the available options (notably data_type and structure) but I can’t experiment with them because I don’t have anything based on Modbus. It should not be necessary to employ a Template Sensor to perform the conversion.
If the sensor reports 775, this prepends 0x to ensure it’s understood to be a hex value and then converted to an integer but informing the int function that it’s dealing with a base 16 (hex) value.