The topic is telling you which sensor triggered the message. So that is saying initially the largest was 26.6, then immediately a new message came along and 27.4 was then the largest, then another message arrived with 31.4. What happens if you let it run?
It doesn't work fine. Around the wanted value, it keeps turning on and off for short periods of time. This was happening when I was trying to feed all of them directly to the PID. The on/off switch version with my function gave the best result compared to this and feeding all directly to PID.
Is the function node now providing the max value of the three sensors, which is what this thread is all about?
If it is then the problem is that the PID loop is not stable for some reason, possibly due to not being correctly tuned. In which case then configure a chart showing
- The temperature input being fed to to the PID node
- The Output value from the PID node
Also screenshot the current settings in the PID node.
Then start a new thread for this problem, and post the chart and the screenshot and also tell us what the heater device is and how you are driving it.
By the way, if you wanted to control on the average of the sensors rather than the max then in the function node, instead of using Math.max use
msg.payload = (v1 + v2 + v3)/3
Yes, and no. Your function provides all values. Somehow, when I heat up one of them to 45 degrees, other 2 variables become 40.1, or similar values. They don't increase in gauges (this is expected, since I only heat up one of them). As it goes down, PID starts and ends in like 0.1 seconds every 9 seconds. This is not normal.
My function only returns the highest, and PID works perfectly fine.
Edit: PID is stable when I use it with my function. I just want to separate it from on/off switch, that is all. What I have is already working, and it is the best among recommendation, and other methods I have tried. I just need to learn how to activate a function without the need of a user. When the Pi starts, the page loads up, this function must start before the user presses start button, and won't get effected by it, as long as the system is powered up.
No, the value provided should always be the max. You will get three messages each time but the value should always be the max.
I don't understand. If one of them is 45 then the output of the function should be 45. Ignore the topic in the output of my function. It is not important.
It is not working properly like I have said. PID gets effected by the other values too. This is the same as connecting them directly to PID. Only difference is that if one of them is above the wanted value by a large amount, it takes a bit more time for PID to go crazy, and work for like 0.1 seconds every 9 second.
PID is stable when I use it with my function. I just want to separate it from on/off switch, that is all. What I have is already working, and it is the best among recommendation, and other methods I have tried. I just need to learn how to activate a function without the need of a user. When the Pi starts, the page loads up, this function must start before the user presses start button, and won't get effected by it, as long as the system is powered up.
So you are saying the output of the function is not always the maximum of the three input temperatures. I which case
- Connect all three sensors to a debug node.
- Connect the output of the function node to another debug node.
Show me a screenshot of the output from the debug nodes showing that the function node output is not the max of the inputs.
Function node output is all of them. One by one. Otherwise, this wouldn't have happened, I believe. I will be going for today. Tomorrow, I'll do this.
I will not use any other global values other than those 3 I was talking about at first. I still want to do it my way. I don't need to be careful with global variable usage, since they are the only ones. I just need something to trigger a trigger node constantly (other than timestamp, which ruins everything by randomly sending insanely large numbers).
So, can we focus on the 2nd paragraph here, not the first one?
Also, why -100 in the function? What does it do? Just give -100, if unable to read the sensor at that time?
Show me the debug node ouputs as requested. Until you do that I will believe your are mistaken.
The -100 is just to cope with the situation before all three have provided their first readings after startup. You should never see that on the output.
These 2 nodes before PID fixed it. Trigger is connected to another inject node (I use it only once to switch from the first page that shows only at the start, to the main page with sensors and buttons).
[{"id":"6f06bd28.261664","type":"trigger","z":"4cdd06f6.faf528","name":"","op1":"1","op2":"","op1type":"str","op2type":"nul","duration":"-10","extend":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":530,"y":340,"wires":[["ed704f4c.f27a5"]]},{"id":"ed704f4c.f27a5","type":"function","z":"4cdd06f6.faf528","name":"","func":"var k1 = global.get('k1');\nvar k2 = global.get('k2');\nvar k3 = global.get('k3');\n\nif(k1>=k2 && k1>=k3)\n{\n msg.payload = k1;\n}\nelse if(k2>=k1 && k2>=k3)\n{\n msg.payload = k2;\n}\nelse if(k3>=k1 && k3>=k2)\n{\n msg.payload = k3;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":800,"y":340,"wires":[["e5102467.06b418","7be3371.28d15c8"]]}]
Turns out, it wasn't a fix. I got a huge number with timestamp trigger, true with boolean trigger, 1 with integer trigger. I tried to set the highest value as another global variable, and put it in the trigger (before the function). Sometimes, my function output is this:
8/5/2020, 10:21:07 AMnode: 7be3371.28d15c8
msg : Object
{ _msgid: "9d7170e0.08806" }
This output turns on the fan that is connected to PID.
There is no payload at all. Why is this happening? Here is the flow with inject, trigger, function and debug nodes:
[{"id":"8eeabffc.803aa","type":"inject","z":"4cdd06f6.faf528","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"Home","payloadType":"str","x":90,"y":40,"wires":[["b31322c7.1876d","6f06bd28.261664"]]},{"id":"6f06bd28.261664","type":"trigger","z":"4cdd06f6.faf528","name":"","op1":"ktop","op2":"","op1type":"global","op2type":"nul","duration":"-9","extend":false,"units":"s","reset":"","bytopic":"topic","topic":"payload","outputs":1,"x":520,"y":340,"wires":[["ed704f4c.f27a5"]]},{"id":"ed704f4c.f27a5","type":"function","z":"4cdd06f6.faf528","name":"","func":"var k1 = global.get('k1');\nvar k2 = global.get('k2');\nvar k3 = global.get('k3');\nvar ktop;\nglobal.set('ktop',ktop);\n\nif(k1>=k2 && k1>=k3)\n{\n ktop = k1;\n msg.payload = k1;\n}\nelse if(k2>=k1 && k2>=k3)\n{\n ktop = k2;\n msg.payload = k2;\n}\nelse if(k3>=k1 && k3>=k2)\n{\n ktop = k3;\n msg.payload = k3;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":800,"y":340,"wires":[["e5102467.06b418","7be3371.28d15c8"]]},{"id":"7be3371.28d15c8","type":"debug","z":"4cdd06f6.faf528","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":380,"wires":[]}]
I am not entirely sure why you expect help when you steadfastly refuse to use the technique I have suggested. But if you read the node red docs page on writing functions then it will show you how to use node.warn()
to display the progress of the flow through a function to see what is going wrong.
My guess is that you are falling into one of the traps that are so easy to fall into using global/flow variables, that is one of the reasons I don't recommend using them when other techniques will do the job just as well.
I'll try your way again, and send the screenshots you asked. Also, it is working fine now. It is so random.
Proabably something to do with running the function before the global vars are setup, or forgetting to write a context var when you should. Something like that.
Should I show you the function, or did you check it? I don't think I forgot about context var. The other reason might be the case (at least at the start). But now, it happened a few more times. I'll add a delay before the function, and see what happens. Then, I'll switch back to your method, if this doesn't work.
Edit: For now, it works perfectly fine. I added a 5 second delay before the trigger. For now, I'll focus on the hall effect sensor issue.
Hint: It is always a good idea to put a final else on the end of an if then else sequence in case none of the conditions is met, as will be the case if one or more of the globals has not yet been setup or contains something other than a number (in the case of some error for example). That condition is coped with in the solution I proposed. Also it is better to use global.set()
after calculating the value of the local variable rather than before calculating it. A problem which does not arise at all my solution of course.
Have you considered what will happen if one of the sensors fails, will it continue using the other sensors?
I took the power cable out for one of the sensors. Temperature for that was 85 degree (C) for that moment. When I took the signal or ground cable out, I saw that empty payload again, and the fan started to work. Maybe, I just have a wiring issue, since I am working on a breadboard. Taking out signal or ground cable causes the same problem with the one I described.
How can I make it give an error message, if any one of the (or multiple) sensors are not working?
Two things I notice:
the first time the flow runs, thetrigger
node sends the contents of global.ktop but if it doesn't exist, then msg.payload will not exist and a msg is sent to the function node with no msg.payload.
In the function
node, you have var htop
which creates the variable with nothing in it. You then write that value to the global.htop
What will happen if any or all of global.k1, global.k2 or global.k3 doesn't exist?