I'm trying to set up an irrigation system for my daughter-in-law's gardens at our cottage. The garden area are separated so I need three or four sensors/relays. In addition the water pressure is low so we have an auxiliary 12 v pump in the battery shed that is about 20 meters from the gardens.
Essentially it will be three or four capacitance soil sensors that would be placed in various different gardens around the property. When the soil is dry it will turn on a sprinkler... either attached directly to the sensor, or through a relay. No problem there. The problem is that there is low water pressure. In order to get enough pressure the system will have to turn on the pump (in the shed) at the same time, then turn it off when the sensor tells it the specific site has enough water. Still easy enough.
The problem is that there are SEVERAL wireless sensors communicating with the pump, and they will inevitably conflict. For instance one sensor will say that it's finished, and want to shut off while another will say "Hey wait a minute! I'm still using this pump!" So I'm not sure how to design the system to deal with these conflicts.
I'm thinking of using nodemcu ESP8266 as the Arduino units. There would be a soil sensor/nodemcu/relay to turn on the sprinkler at each site. There would be a nodemcu/ relay at the pump site.
I've chosen ESP8266 rather than NRF24L01 units (which I have drawer full)because the next step would be to connect the system to the internet to send updates to her.
Hopefully that's enough information for anyone out there how to come up with a solution to solve
potential conflicts coming from the soil sensors.
There are multiple ways of course.
You could set a boolean for each sprinkler that's active and clear it when it's done.
When you turn one off, if no boolean indicators are set, turn the pump off too.
Alternatively, just do one sprinkler at a time - for watering, why do you care about doing them all.
Beware of overwatering - apparently it takes a while for the soil to soak up the water and indicate to the sensor that it's done. You might water each sensor that reads dry for a minute (or whatever) and then wait a while before checking again.
how far apart are the nodes?
does the area have global WiFi coverage
the ESP8266 only supports WiFi which has limited range - e.g. 10-20metres depends of environment (walls, trees, etc)
you could use ESP-MESH if the nodes are within range of each other
As long as one of the sensors demands that the pump is on, it will stay on. If you drive the relay with an open-collector/open-drain transistor connected to each sensor, or a relay driver such as a ULN2803, that will work.
Hi Horace:
The three gardens are about 10 meters apart - line of site
The gardens are about 50 meters from the pump/battery house - line of site
The nodes are all about 50 meters from the wifi router
We basically have metered internet. In the water tank system you helped me with last year I have it set up to turn on once an hour for a minute to get a reading and send it to the internet. I'd do the same with this system.
thanks for the reply. I AM aware of the distinction, sorry I didn't articulate clearly. Regarding of checking the garden myself, I'd happily do that (I enjoy watering) but because it's a summer cottage there is often no one there for a week to ten days.
think you need to carry out some WiFii tests with the nodes to determine transmission distance, e.g. set up an access point on a central node and see if others can access it
ESP-MESH could be a solution - one the nodes could switch to be a WiFi station to connect to the internet every hour to upload data
you may need to take account of overwatering one area while watering another
could you have a solenoid valve on each node to ensure areas are only watered when required?
the central pumps is switched on only when water is required
I thought that was sort of my plan. For instance lets say at 1:00 garden sensor A decides that it's area is dry so it turns on the relay which opens the sprinkler(valve) and at the same time sends a message to the pump to turn on. As a result Sensor A's area is now being watered.
At 1:30 Sensor B determines that it's area is dry and turns on its sprinkler(valve) and sends a message to the pump. However since the pump is already on it ignores the second request to turn on.
At 2:00 Sensor C determines it's dry and turns on its sprinkler and sends yet another message to the pump to turn on - which, since it's on, the pump ignores.
At 3:00 sensor A detrmines that the garden has enough water and turns of the valve and sends a message to the pump to turn off. Now this is where it gets interesting. Since Sensors B and C still want water, the pump has to ignore sensor A's command and keep the water on. Since sensor A turned off the sprinkler (valve) at its location no water is going to come through to that area, which is what we want. So the pump ignores the request and keeps running.
At 3:30 Sensor B has had enough and shuts off its sprinkler (Valve) and sends a command to the pump to shutoff, but since Sensor C still needs water, it keeps going until sensor C sends it's command and finally since no sensors no longer need water it finally shuts off.
My guess is (with my limited programming skills) that some sort of Boolean commands might be able to solve this.
Thoughts?
HI Horace:
As always, thanks for your help. You're right, using bytes makes more sense. I've altered the code to do that and added some more code so the sensors can turn on or off the relay controlling the sprinkler(valve) wired to them. Let me know what you think of the code or if you spot any errors.
// Sensor Node or Pump Controller Code
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
// Wi-Fi credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// Pump controller IP address and port
IPAddress pumpControllerIP(192, 168, 1, 100);
unsigned int pumpControllerPort = 3333;
// Sensor pin and relay pin (for sensor nodes)
const int sensorPin = A0;
const int relayPin = D1; // Pin connected to the relay for the sprinkler valve
// Sensor ID (0, 1, or 2 for sensor nodes, -1 for pump controller)
const int sensorId = -1;
// Pump relay pin (for pump controller)
const int pumpRelayPin = D1;
WiFiUDP udp;
// Keep track of active requests (for pump controller)
bool sensorRequests[3] = {false, false, false};
void setup() {
Serial.begin(115200);
connectToWiFi();
if (sensorId == -1) {
// Pump controller setup
udp.begin(pumpControllerPort);
pinMode(pumpRelayPin, OUTPUT);
digitalWrite(pumpRelayPin, LOW); // Initially turn off pump
} else {
// Sensor node setup
udp.begin(WiFi.localIP(), pumpControllerPort);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW); // Initially turn off the sprinkler valve
}
}
void loop() {
if (sensorId == -1) {
// Pump controller loop
int packetSize = udp.parsePacket();
if (packetSize) {
byte packet[2];
udp.read(packet, 2);
int sensorId = packet[0];
bool requestStatus = packet[1] == 1;
if (requestStatus) {
handleRequest(sensorId);
} else {
handleRequestRemoval(sensorId);
}
}
} else {
// Sensor node loop
int moisture = analogRead(sensorPin);
bool soilIsDry = moisture < 300; // Adjust threshold as needed
if (soilIsDry) {
sendRequest();
digitalWrite(relayPin, HIGH); // Turn on the sprinkler valve
} else {
removeRequest();
digitalWrite(relayPin, LOW); // Turn off the sprinkler valve
}
delay(3600000); // Check every hour
}
}
// Sensor node functions
void sendRequest() {
byte message[2] = {sensorId, 1};
udp.beginPacket(pumpControllerIP, pumpControllerPort);
udp.write(message, 2);
udp.endPacket();
}
void removeRequest() {
byte message[2] = {sensorId, 0};
udp.beginPacket(pumpControllerIP, pumpControllerPort);
udp.write(message, 2);
udp.endPacket();
}
// Pump controller functions
void handleRequest(int sensorId) {
sensorRequests[sensorId] = true;
digitalWrite(pumpRelayPin, needsWater()); // Turn on pump if any sensor needs water
}
void handleRequestRemoval(int sensorId) {
sensorRequests[sensorId] = false;
digitalWrite(pumpRelayPin, needsWater()); // Turn off pump if no sensor needs water
}
bool needsWater() {
return sensorRequests[0] || sensorRequests[1] || sensorRequests[2];
}
// Common function
void connectToWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}
Don't forget that UDP is send and forget - the pump controller may miss requests from the sensors. Consider carefully what will happen if one is dropped.
Does it matter for example if the sprinkler is turned off, but the master is still running the pump.