Hi, I want to control a heater with multiple temperature sensors.
so I have a goal temperature to reach.
for turning off the heater I use <||> sign, because I have to be sure that in case of going up temperature in one section, the heater goes off.
for turning on, Im using <&&> sign to wait until all of the values are below goal temperature.
the problem raises when I get false values from sensors.
lower values don’t cause any problem. it will pass both of above rules but higher values cause the turning on section never happen.
rule "dryerprocess"
when
Item t1 received update or
Item t2 received update or
Item t3 received update or
Item t4 received update
then
goaltemp.sendCommand(theArray1.get((tm.state as Number).intValue))
if(dryer.state == ON) {
if(dryer_pause.state == OFF) {
if(((t1.state as DecimalType) > (goaltemp.state as DecimalType)+3) || ((t2.state as DecimalType) > (goaltemp.state as DecimalType)+3) || ((t3.state as DecimalType) > (goaltemp.state as DecimalType)+3) || ((t4.state as DecimalType) > (goaltemp.state as DecimalType)+3)) {
if(Heater.state != OFF) Heater.sendCommand(OFF)
}
if(((t1.state as DecimalType) < (goaltemp.state as DecimalType)+1) && ((t2.state as DecimalType) < (goaltemp.state as DecimalType)+1) && ((t3.state as DecimalType) < (goaltemp.state as DecimalType)+1) && ((t4.state as DecimalType) < (goaltemp.state as DecimalType)+1)) {
if(Heater_Thermo.state != ON) Heater_Thermo.sendCommand(ON)
}
}
}
end
So, I delete && part and use jus one sensor data and use Thread::sleep for 10 seconds to wait for other sensors to get lower than goal temperature but thread::sleep doesn’t work, so when one sensor is lower than goal temp and the others are upper, heater will turn on and off until all of them comes down …
rule "dryerprocess"
when
Item t1 received update or
Item t2 received update or
Item t3 received update or
Item t4 received update
then
goaltemp.sendCommand(theArray1.get((tm.state as Number).intValue))
if(dryer.state == ON) {
if(dryer_pause.state == OFF) {
if(((t1.state as DecimalType) > (goaltemp.state as DecimalType)+3) || ((t2.state as DecimalType) > (goaltemp.state as DecimalType)+3) || ((t3.state as DecimalType) > (goaltemp.state as DecimalType)+3) || ((t4.state as DecimalType) > (goaltemp.state as DecimalType)+3)) {
if(Heater.state != OFF) Heater.sendCommand(OFF)
}
if((t1.state as DecimalType) < (goaltemp.state as DecimalType)+1) {
Thread::sleep
if(Heater_Thermo.state != ON) Heater_Thermo.sendCommand(ON)
}
}
}
end
I know this method is wrong even if thread::sleep worked.
You don’t a rules problem, you have a hardware problem…
What kind of sensors are you using?
Why to you get false values?
What kind of false values do you get?
thanks. I want to use coding to cover the sensor failure temporarily to replace the sensor after that.
I use pt100 with sensor with nodemcu esp8266.
if pt100 amplifier has problem or something else… the value goes down to zero or between 0-30 C
or in some cases goes up like 1200 degrees
rule "dryerprocess"
when
Item t1 received changed or
Item t2 received changed or
Item t3 received changed or
Item t4 received changed
then
val temp = triggeringItem.state as Number
if (temp > 50) {
triggeringItem.postUpdate(triggeringItem.previousState.toString)
}
end
That’s tricky. While you can eliminate outliers with some simple math, how would you detect broken sensor that gives a normal looking value? Not rhetorical, I mean how YOU know it’s broken, so you can code similar method. One way might be to flag a fault if the value doesn’t change over some time period.
This is a hard problem. As with all hard problems, you need to break it into multiple parts.
As rossko57 indicates, you need to figure out how to know that a sensor is not working. Then write code/configuration to reliably detect this in your Rules. You will probably need to use a Proxy Item and a Rule. And of course how you do this depends greatly on the behavior the sensor exhibits when it is not working correctly. Does it stop reporting? Does it momentarily report an unreasonable value? What constitutes an unreasonable value? If it just stops reporting then you can use the Expire binding to set that Item to UNDEF if it doesn’t report for awhile. If it reports one odd value then comparing the current reading to the last reading might be sufficient. But you might need to use a bunch of complicate math and Markov chaining and the like to estimate where the temp reading should be based on past readings and if the actual is too far beyond the estimate then you reject it.
To start, just write a Rule that logs out when it senses a bad sensor reading and double check that it is right.
rule "Filter out likely bad readings"
when
Item t1 received changed or
Item t2 received changed or
Item t3 received changed or
Item t4 received changed
then
if(Math::abs(triggeringItem.state as Number - previousState as Number) < 50)
postUpdate(triggeringItem.name+"_Proxy", triggeringItem.state)
else
logWarn("temp", triggeringItem.name + " returned an unreasonable sensor reading: curr = " + triggeringItem.state + " prev = " + previousState)
end
The above Rule triggers when any of the sensors changes. Only if the change between the current reading and the previous reading is less then 50 is the sensor reading forwarded on to the Proxy Item.
Once you can reliably detect a bad sensor reading you need to figure out what is the correct way to handle it. Do you just ignore it? Do you estimate the value based on the other sensors (e.g. assume it’s the average of the other ones)? Do you shut everything down? etc.
Finally, you need to implement the Rule that combines 1 and 2 as appropriate.
Honestly, having done this with my own heating to just handle the case where a sensor goes offline, it will be far far less work and far more reliable to fix the problem in hardware if that is an option.