I attempted to follow the instructions given in this video
but the pump seems to be operating in reverse. It activates when the sensor is submerged in water and deactivates when it is removed. I suspect that the issue lies with the 5v relay board, as the module I am using features (S+, -) instead of (VCC, GND, IN). Could you offer any assistance?
Just modify the code that tests the sensor and/or controls the motor. Rather than setting the output HIGH to turn on the motor, set it LOW. Opposite for turning it off.
Since you didn't post your code, only you know for sure.
you can factor out a lot of that code. Not really necessary to continuously write the same text to your LCD.
Also, when testing different ranges with a series of if() statements, it makes the code cleaner and easier to change if you start at the highest value and work your way down. This eliminates having to test both the upper and lower bounds.
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.clear();
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
delay(1000);
lcd.setCursor(0, 0);
lcd.print("IRRIGATION");
lcd.setCursor(0, 1);
lcd.print("SYSTEM IS ON ");
lcd.print("");
delay(3000);
lcd.clear();
}
void loop() {
int value = analogRead(A0);
Serial.println(value);
if (value > 950) {
digitalWrite(2, HIGH);
lcd.setCursor(0, 0);
lcd.print("Water Pump is ON ");
} else {
digitalWrite(2, LOW);
lcd.setCursor(0, 0);
lcd.print("Water Pump is OFF");
}
if (value < 300) {
lcd.setCursor(0, 1);
lcd.print("Moisture : HIGH");
} else if (value > 300 && value < 950) {
lcd.setCursor(0, 1);
lcd.print("Moisture : MID ");
} else if (value > 950) {
lcd.setCursor(0, 1);
lcd.print("Moisture : LOW ");
}
}
The pump and screen are functioning correctly as required, and all appears to be in order. However, the logic of the code seems flawed since the pump should be turned off when the value exceeds 950
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.clear();
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
delay(1000);
lcd.setCursor(0, 0);
lcd.print("IRRIGATION");
lcd.setCursor(0, 1);
lcd.print("SYSTEM IS ON ");
lcd.print("");
delay(3000);
lcd.clear();
}
void loop() {
int value = analogRead(A0);
Serial.println(value);
if (value > 950) {
digitalWrite(2, LOW);
lcd.setCursor(0, 0);
lcd.print("Water Pump is ON ");
} else {
digitalWrite(2, HIGH);
lcd.setCursor(0, 0);
lcd.print("Water Pump is OFF");
}
if (value < 300) {
lcd.setCursor(0, 1);
lcd.print("Moisture : HIGH");
} else if (value > 300 && value < 950) {
lcd.setCursor(0, 1);
lcd.print("Moisture : MID ");
} else if (value > 950) {
lcd.setCursor(0, 1);
lcd.print("Moisture : LOW ");
}
}
-The sensor gives me a reading of 1016 when removed from water, but when submerged in water, the reading increases to 3247.
-Upon taking the sensor out of the water, the screen displays the message "the pump is ON," however, the pump remains inactive and the relay lamp fails to illuminate.
Conversely,
-When I dip the sensor into the water, the screen shows a message indicating that the pump is OFF, but in reality, the pump is working and the relay lamp is lit.
-The sensor gives me a reading of 1016 when removed from water, but when submerged in water, the reading increases to 3247.
-Upon taking the sensor out of the water, the screen displays the message "the pump is ON," however, the pump remains inactive and the relay lamp fails to illuminate.
Conversely,
-When I dip the sensor into the water, the screen shows a message indicating that the pump is OFF, but in reality, the pump is working and the relay lamp is lit.
Now lets say you want the pump to energize when the sensor is completely dry and deenergize when the sensor is completely wet.
if (sensorvalue =< 1016 )
{
pump on
}
if ( sensor value => 3247 )
{
pump off
}
You'll most likely want to energize the pump before the water has completely dried off or has completely wetted the soil but that value is to be determined by you.
What I do is run the pump for an amount of time, say 11 seconds, then I wait one minute to allow the water to seep into the nooks and crannies, then I read the sensor value to see if the soil needs more water, if so then run the pump for another 11 seconds.
You could also look to create a formula for a % of moisture. Consider that 1016 is 0% moisture and 3247 is 100% moisture. You could use the map function, map() - Arduino Reference, to determine a percentage of moisture remaining in the soil to energize the pump for x amount of seconds and then check for a threshold % of moisture to keep the pump off.
Anyways here is how I do the thing.
void fDoMoistureDetector1( void * parameter )
{
//wait for a mqtt connection
while ( !MQTTclient.connected() )
{
vTaskDelay( 250 );
}
int TimeToPublish = 5000000; //5000000uS
int TimeForADreading = 100 * 1000; // 100mS
uint64_t TimePastPublish = esp_timer_get_time(); // used by publish
uint64_t TimeADreading = esp_timer_get_time();
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10; //delay for 10mS
float RemainingMoisture = 100.0f; //prevents pump turn on during start up
bool pumpOn = false;
uint64_t PumpOnTime = esp_timer_get_time();
int PumpRunTime = 11000000;
uint64_t PumpOffWait = esp_timer_get_time();
uint64_t PumpOffWaitFor = 60000000; //one minute
float lowMoisture = 23.0f;
float highMoisture = 40.0f;
for (;;)
{
xSemaphoreTake( sema_WaterCactus, portMAX_DELAY );
//read AD values every 100mS.
if ( (esp_timer_get_time() - TimeADreading) >= TimeForADreading )
{
xEventGroupSetBits( eg, evtADCreading0 );
TimeADreading = esp_timer_get_time();
}
xQueueReceive(xQ_RM, &RemainingMoisture, 0 ); //receive queue stuff no waiting
//read gpio 0 is water level good. Yes: OK to run pump : no pump off. remaining moisture good, denergize water pump otherwise energize water pump.
if ( RemainingMoisture >= highMoisture )
{
WaterPump0_off();
}
if ( !pumpOn )
{
log_i( "not pump on ");
if ( gpio_get_level( GPIO_NUM_0 ) )
{
if ( RemainingMoisture <= lowMoisture )
{
//has one minute passed since last pump energize, if so then allow motor to run
if ( (esp_timer_get_time() - PumpOffWait) >= PumpOffWaitFor )
{
gpio_set_level( GPIO_NUM_5, HIGH); //open valve
WaterPump0_on();
log_i( "pump on " );
pumpOn = !pumpOn;
PumpOnTime = esp_timer_get_time();
}
}
//xSemaphoreGive( sema_RemainingMoisture );
} else {
log_i( "water level bad " );
WaterPump0_off();
gpio_set_level( GPIO_NUM_5, LOW); //denergize/close valve
PumpOffWait = esp_timer_get_time();
}
} else {
/*
pump goes on runs for X seconds then turn off, then wait PumpOffWaitTime before being allowed to energize again
*/
if ( (esp_timer_get_time() - PumpOnTime) >= PumpRunTime )
{
log_i( "pump off " );
WaterPump0_off(); // after 5 seconds turn pump off
gpio_set_level( GPIO_NUM_5, LOW); //denergize/close valve
pumpOn = !pumpOn;
PumpOffWait = esp_timer_get_time();
}
}
// publish to MQTT every 5000000uS
if ( (esp_timer_get_time() - TimePastPublish) >= TimeToPublish )
{
xQueueOverwrite( xQ_RemainingMoistureMQTT, (void *) &RemainingMoisture );// data for mqtt publish
TimePastPublish = esp_timer_get_time(); // get next publish time
}
xSemaphoreGive( sema_WaterCactus );
xLastWakeTime = xTaskGetTickCount();
vTaskDelayUntil( &xLastWakeTime, xFrequency );
}
vTaskDelete( NULL );
}// end fDoMoistureDetector1()