What is wrong with my function. Please


i'm fighting with my Flow. I'm receiving mqqt messages from ESP01 which reads BME280 and 32 ADC channels (NTC resistors for temprature readings). Additionally i hooked up PZEM-004 for power monitoring. All of that to tiny ESP01.
ESP01 firmware i wrote created topic in JSON form manually (i'm not using ArduinoJson lib).
My Flow receives it with no problem, parsing to object then i'm using Function node to make NTC calculations (to translate ADC reading of NTC to its resistances in Ohms and then, using Steinhart-Hart equation, to calculate temperature. In the same Function node im preparing output to InfluxDB.

The problem is i'm getting "NaN" instead of temperature readings...
Here is my function:

let device = msg.payload.dev;
msg.payload = {
       "cisnienie" : msg.payload.pre,
       "temperatura" : msg.payload.tem,
       "wilgotnosc" : msg.payload.hum,
       "napiecie_sieciowe" : msg.payload.vol,
       "pobor_pradu" : msg.payload.cur,
       "moc_pobierana" : msg.payload.pwr,
       "licznik_energii" : msg.payload.ene,
       "czestotliwosc" : msg.payload.frq,
       "PF" : msg.payload.p_f,
       "czujnik_gazu" : msg.payload.gaz,
       "ADC": msg.payload.ADC}
//now get 32 values from ADC
for (let i = 0; i < 32; i++)
    let U_ADC_int = Number(msg.payload.ADC[i]); //i have now 16-bit integer value from ADC in 
    if ((U_ADC_int >= 1000)&(U_ADC_int < 40000))  //if integer value is within the range (1000 is ca 
     50mV, 40000 is ca 2 V) then convert integers to volts (65536 is 3.3V)
    let U_zasil_int = Number(msg.payload.zas); //U_zasil  is measured power supply value
    var R = 10000 * (U_ADC_int / (U_zasil_int - U_ADC_int)) //10000 is for 10kOhm resistor used in 
    divider, calculation is just Ohm Law and voltage divider.
    //and then Steinhart-Hart:
    var R0 = 10000; //10k type NTC
    var T0 = 273.15 + 25;
    var B = 3950; //NTC coefficient
    var T = 1 / ( (1/T0) + (1/B) * Math.log(R/R0) );
    T = T - 273.15;
    msg.payload[`kanal_${(i+1)}`] = Number(T.toFixed(1));
    } else{
   //the rest of the code to process ADC values outside of range: i.e. when i put jumper instead of NTC so i can use ADC channel for switches or connect photoresistor and so on... 
delete msg.payload.ADC;
msg.payload = [msg.payload, {"deviceID" : device, "location": "basement"}];
return msg;

This is the continuation of the threat that was automatically closed... Well, i haven't had time to play with NodeRED... Here is the thread:

As you can see i've changed approach to reduce the amount of data sent via mqtt - shorter names and 16bit ADC values instead of floats. Now i need to calculate voltage value and then resistance value in NodeRed instead of in ESP8266. The reason for that is simplicity of changing things in NodeRED. Imagine i'm connecting photoresistor instead of NTC. In the old approach i would have to redo firmware and flash ESP. By sending raw ADC data to NodeRED i can modify Function node and go further.

The other thing is: sometimes some NTC will be disconnected or values are outside of the range - in this case i need to discard them and not to sent to InfluxDB so it will be not shown in Grafana trends.
For this i'm just using this:
msg.payload[kanal_${(i+1)}] = Number(T.toFixed(1));
inside the loop. Is there some different approach to achieve it? And regarding toFixed() method - this one is just truncating the value. But 21.19 C become 21.1 C. What is the method for Math rounding? I found too many confusion regarding rounding and in many places it is recommended to use toFixed(). But what about rounding?
I've checked JS Math methods. But Math.round(x) returns x rounded to its nearest integer but i need not integer but float with on decimal place accuracy. The only way i can think to sort it is multiplying my temmperature by 10, applying Math.round(x) and dividing by 10 to go back to float. Kinda stupid.

JavaScript is new to me. I'm C language amateur:)
Thank you for advices!

Only on a limb, but I think it is how the values are derived.

"cisnienie" : msg.payload.pre,

As an example.

Try (and NO promises)
"cisnienie" : parseInt(msg.payload.pre),

See if that makes a difference.

Feed the message going into the function into a debug node and show us what it says.

Without seeing input payload i can see two things wrong
1 Some of your comments are are on more than one line.
2 msg.payload.zas is referenced in the loop does not exist.

To round to 1 deciaml place use


Thanks Guys,
Colin - i'll put Function node input here when i get home.
Trying_to_learn - actually cisnienie" : msg.payload.pre, and others there work with no problem.
E1cid - ad. 1: it lloks like this only here on forum. Looks like "reply" window here on the forum is too narrow. In the Function node it is in the same line, properly commented out
For rounding looks logical - i'll use it. Thank you.

So far i found a problem here:

Whean i changed it to:

where 26500 is the value i get via mqtt and i can see this value in the Function node input(!), then the calculations are fine and all the temperatures are correct and parsed correctly to influxDB.

I bet you Guys are using Grafana as well - do you know how to solve the following problem: in case i loose some data (i.e. disconnect temperature probe) the value will go out of range and i have to filter it to not to send it to InfluxDB. I already know how to do it using < and > comparators and if out of scope i will just not create:

for that particular channel. However, on the Grafana side i'm having problems to properly visualize gaps in the trends... Any clue?

Thank you,

Not me sorry.

But all the best with getting it working.

It can be frustrating. Hang in there.

As stated msg.payload.zas does not exist. You overwrote msg.payload at the start of the code.

E1cid - you're right. i've moved it to the top and it's fine. Thanks!

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.