1

I am trying to trigger/stop a water pump with the use of a 4-channel relay and a UC-SR04 distance sensor. I tried with some codes but I think I am missing something because although there was no error in the codes, the pump was not triggered.

The 12V water pump has a flow rate of 20l/min and works at max. 45W. The distance sensor works on its own, I am able to see data displaying on the monitor. The water pump can also work on its own with a relay and a 12V 5A power supply. I would like to incorporate the features from the distance sensor with that of the water pump.

Ideally, when the distance sensor detects that the water surface is < 10cm away from it, it gives signal to the pump to turn the pump on. When the sensor detects that the water surface is >10cm away from it, it turns the pump off.

Ideally the whole setup should be similar to what happens in this video, which I found on YouTube: https://www.youtube.com/watch?v=RTmbWMSiwiQ

The person in this video uses an Arduino though, I am using a Raspberry pi 3B.

These are my codes:

> import RPI.GPIO as GPIO
> import time
> import datetime
> init = False
> GPIO.setmode(GPIO.BOARD)
> GPIO.setwarnings(False)
> TRIG = 36
> ECHO = 38
> 
> def get_status(pin = 38):
>     GPIO.setup(pin, GPIO.IN)
>     return GPIO.input(pin)
> 
> def init_output(pin):
>     GPIO.setup(pin, GPIO.OUT)
>     GPIO.output(pin, GPIO.LOW)
>     GPIO.output(pin, GPIO.HIGH)
> 
> def auto_water(delay = 6, pump_pin = 7, water_sensor_pin = 8):
>     distance_count = 0
>     init_output(pump_pin)
>     print("press CTRL+C to exit")
>     try:
>         while 1 and distance_count > 10:
>             time.sleep(delay)
>             shallow = get_status(pin = water_sensor_pin) == 0
>             if not shallow:
>                 if distance_count < 10:
>                     pump_on(pump_pin, 1)
>                 distance_count += 1
>             else:
>                 distance_count = 0
>     except KeyboardInterrupt:
>         GPIO.cleanup()
> 
> def pump_on(pump_pin = 7, delay = 1):
>     init_output(pump_pin)
>     GPIO.output(pump_pin, GPIO.LOW)
>     time.sleep(1)
>     GPIO.output(pump_pin, GPIO.HIGH)
> 
> print "Distance measurement in progress"
> 
> GPIO.setup(TRIG,GPIO.OUT)                  
> GPIO.setup(ECHO,GPIO.IN)   
> 
> 
> while True:
> 
>     GPIO.output(TRIG, False)                 
>     print "Waiting For Sensor To Settle"
>     time.sleep(2)                            
> 
>     GPIO.output(TRIG, True)                  
>     time.sleep(0.00001)                      
>     GPIO.output(TRIG, False)  
>                
>     while GPIO.input(ECHO)==0:             
>         pulse_start = time.time()             
> 
>     while GPIO.input(ECHO)==1:              
>         pulse_end = time.time()                
> 
>     pulse_duration = pulse_end - pulse_start 
> 
>     distance = pulse_duration * 17150        
>     distance = round(distance, 2)            
> 
>     if distance > 0 and distance < 100:     
>         print ("Distance:"),distance - 0.5, ("cm")  
>     else:
>         print ("Out Of Range")       
> 
> GPIO.cleanup()

Here is a graph of the circuit. The setup in this graph is similar to mine, the only difference is that I am using a distance sensor, not a moisture sensor. Additionally, I am using slightly different pins. enter image description here

I think there is something missing in my code, as the pump cannot be triggered. Could you please help me out?

Thank you very much in advance.

  • 1
    Why is pump_on outputting LOW then HIGH? – CoderMike Jan 11 at 16:24
  • 1
    I thought there wouldn't be a problem if I set it as LOW then HIGH, sorry. – Sharyn Cao Jan 11 at 16:47
  • 1
    I changed it to HIGH then LOW but it did not give any response – Sharyn Cao Jan 11 at 16:47
  • 1
    Are you sure your relay is connected to board pin 7? pinout.xyz/pinout/pin7_gpio4 – CoderMike Jan 11 at 16:50
  • 1
    auto_water is never called - so you code will never work. – CoderMike Jan 11 at 17:23
2

Firstly does the following turn your relay on then off?

import RPi.GPIO as GPIO,time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(7,GPIO.OUT)

print('on')
GPIO.output(7,GPIO.LOW)

time.sleep(4)

print('off')
GPIO.output(7,GPIO.HIGH)

You also need to add timeouts to your distance sensing code otherwise your code could get stuck in a while loop:

pulse_start = time.time()
timeout = pulse_start + 0.04               
while GPIO.input(ECHO)==0 and pulse_start < timeout:             
    pulse_start = time.time()             

pulse_end = time.time()
timeout = pulse_end + 0.04               
while GPIO.input(ECHO)==1 and pulse_end < timeout:              
    pulse_end = time.time() 

It seems that you have just put two sections of code together without any thought as to how it would work.

I would do something like:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
TRIG = 36
ECHO = 38

def init_output(pin):
    GPIO.setup(pin, GPIO.OUT)
    GPIO.output(pin, GPIO.HIGH)

def pump_on(pump_pin):
    print('pump on')
    GPIO.output(pump_pin, GPIO.LOW)

def pump_off(pump_pin):
    print('pump off')
    GPIO.output(pump_pin, GPIO.HIGH)

print("Distance measurement in progress")

GPIO.setup(TRIG,GPIO.OUT)                  
GPIO.setup(ECHO,GPIO.IN)   

init_output(7)

while True:

    GPIO.output(TRIG, False)                 
    print("Waiting For Sensor To Settle")
    time.sleep(2)                            

    GPIO.output(TRIG, True)                  
    time.sleep(0.00001)                      
    GPIO.output(TRIG, False)

    pulse_start = time.time()
    timeout = pulse_start + 0.04               
    while GPIO.input(ECHO)==0 and pulse_start < timeout:             
        pulse_start = time.time()             

    pulse_end = time.time()
    timeout = pulse_end + 0.04               
    while GPIO.input(ECHO)==1 and pulse_end < timeout:              
        pulse_end = time.time()                

    pulse_duration = pulse_end - pulse_start 

    distance = pulse_duration * 17150        
    distance = round(distance, 2)            

    print('distance',distance)

    if distance < 10:
        pump_on(7)
    else:
        pump_off(7)
|improve this answer|||||
  • 1
    Thank you very much for your help, sir! As you said, the relay is actually connect to pin 37, and it worked with your method. I have been trying to find ways to trigger the pump and you provided me with the solution. Thank you again! – Sharyn Cao Jan 11 at 18:09
2

CoderMike's Answer addressed the problems in your code, but if you are actually using the relay module pictured and have wired it in a similar manner there are more concerns.

There are a number of similar (poorly-designed) relay modules on the market - they seem to infect ebay! They may work with Arduino (and TTL logic) BUT ARE A LOUSY DESIGN even for that purpose and totally unsuitable for the Pi as they are only controllable from 5V.

You are putting 5V on the GPIO - sooner or later the Pi will fail from this abuse. Many others have used similar modules and found they don't reliably turn off.

You can safely use the relay modules if you drive them with a transistor.

There ARE 3.3V logic controlled relays, unfortunately much less common.

|improve this answer|||||
  • why should there be 5V on the GPIO? The relay has no "backchannel". – fsp Jan 12 at 3:02
  • Thank you very much, I would take that into consideration. – Sharyn Cao Jan 13 at 7:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.