Greenhouse irrigation

Use a range node to scale it up.

scale

150 seconds ? I'm sorry :pleading_face: I just don't understand what the output of the PID node refers to

It's the number of seconds that the pump would be activated for.
...or should I say the number of seconds that should elapse before switching the pump off.

More seconds = more water!

So if your PID outputted 1, that would be scaled up to 150, which in turn would activate the water pump for 150 seconds.

1 Like

Is the scaling based on you personal choice, based on your experience or on a reference ? Thanks in a advance

Trial & error!! it depends upon what rate you are delivering water, the type of soil etc.
I started with minimal water delivery and gradually increased until I was happy that the PID could gain control, and maintain the moisture level that I wanted.

1 Like

All right, Thank you very much!!

In fact my suggestion is to use node-red-contrib-pid as you originally suggested. If you feed the output of the PID into that then it will generate an on/off time proportioned signal (effectively a very slow PWM) which you can use to control the water valve. So if for example the pid asks for 25% (actually 0.25) then it will switch the relay on for 25% of the time and off for 75% of the time, with the cycle time as set in the timeprop node. So if the max flow rate is set to that which is required in the worst case then it should do the job. Alternatively if you think you will never want the valve on for more than, say, 10% of the time you can use a Range node to convert the pid 0:1 to the range 0:0.1 and feed that into the timeprop node.

1 Like

That makes a lot of sense, thank you !

more expensive but perhaps better acurate : sht sensor for soil humidity

What do you think about it ?

I'm not that familiar with those devices, but a quick google search suggests that they aren't intended for long term exposure to submersion/high humidity conditions.
It appears to be a SHTx sensor mounted in a fine metal mesh, intended to allow air to blow through, but fine enough to prevent short term water ingress.

Paul

Hi Paul, did you usenode-red-node-smooth or the RC filter function in @Colin's flow or something else ?

Hello guys, I recently bought a capacitive soil moisture sensor , but I just can't calibrate it, I tried to take analog values when it is dry (0) and when it is dipped in water (100) but it didn't turn out accurate, also I have another question, as in @Colin's blog in order to obtain the time at which the first peak occurs you have to start out from 0, does that mean that I have to put the sensor in a very dry soil as a start ?

@nassima100 I've used Colin's RC filter, as I want the most recent readings to have a greater impact on the readings (because the soil will be progressively getting moister).

1 Like

@sakura instead, try measuring soil samples of the extremes of the expected soil humidity.
For example, the soil humidity when a plant would be wilting through dryness, and another when the soil has been saturated and allowed to drain a while.
Once you get those two readings, use a range node to scale it 0 to 100 ( or 100 to 0 depending upon your process).

1 Like

I willl, thank you.

hello @Paul-Reed i'm working on somthing similar to yours and using the same hardware,would you please share your flow with us ...thanke you

@ima The flow would not really help you as it's closely tied into the ESP firmware.
For example; the ESP via MQTT tells node-RED what the soil humidity is, and node-RED calculates and tells the ESP how much water to administer.

So one won't work without the other, and you would need the ESP hardware & firmware for the flow to run.

I honestly didn't understand how his RC filter works, I tried to debug it and it only gives me bigger and bigger values each time, I think it is for simulation sake but how to make it filter real sensor's values and return logical values according to that?

Which one do you mean? Post a small flow showing the problem.

I'm talking about these two nodes:

[{"id":"582764f9.714ecc","type":"function","z":"2aaf6568.86263a","name":"10 sec RC","func":"// Applies a simple RC low pass filter to incoming payload values\nvar tc = 10*1000;       // time constant in milliseconds\n\nvar lastValue = context.get('lastValue');\nif (typeof lastValue == \"undefined\") lastValue = msg.payload;\nvar lastTime = context.get('lastTime') || null;\nvar now = new Date();\nvar currentValue = msg.payload;\nif (lastTime === null) {\n    // first time through\n    newValue = currentValue;\n} else {\n    var dt = now - lastTime;\n    var newValue;\n    \n    if (dt > 0) {\n        var dtotc = dt / tc;\n        newValue = lastValue * (1 - dtotc) + currentValue * dtotc;\n    } else {\n        // no time has elapsed leave output the same as last time\n        newValue = lastValue;\n    }\n}\ncontext.set('lastValue', newValue);\ncontext.set('lastTime', now);\n\nmsg.payload = newValue;\nreturn msg;","outputs":1,"noerr":0,"x":501.5,"y":2815,"wires":[["43a52c92.e81ba4","3ca8f1a3.f9029e"]]}]
[{"id":"43a52c92.e81ba4","type":"function","z":"2aaf6568.86263a","name":"30 sec RC + 20","func":"// Applies a simple RC low pass filter to incoming payload values\nvar tc = 30*1000;       // time constant in milliseconds\n\nvar lastValue = context.get('lastValue');\nif (typeof lastValue == \"undefined\") lastValue = msg.payload;\nvar lastTime = context.get('lastTime') || null;\nvar now = new Date();\nvar currentValue = msg.payload;\nif (lastTime === null) {\n    // first time through\n    newValue = currentValue;\n} else {\n    var dt = now - lastTime;\n    var newValue;\n    \n    if (dt > 0) {\n        var dtotc = dt / tc;\n        newValue = lastValue * (1 - dtotc) + currentValue * dtotc;\n    } else {\n        // no time has elapsed leave output the same as last time\n        newValue = lastValue;\n    }\n}\ncontext.set('lastValue', newValue);\ncontext.set('lastTime', now);\n\nmsg.payload = newValue + 20;\nreturn msg;","outputs":1,"noerr":0,"x":677,"y":2815,"wires":[["2ab907f7.bc74c8","8439448e.1a4318"]]}]