gsrpi
Posts: 1
Joined: Mon May 11, 2015 3:18 am

Well Pump Control

Mon May 11, 2015 3:42 am

Hello,

I am building a system to remotely control a well pump. My Pi will be set up at remote water tanks and is programmed to sense what level the tanks are at (using 3 float switches) and trigger the pump on and off appropriately. I also have 3 indicator lights that will be triggered to indicate the current tank level. After sensing a change, the Pi activates a radio link to the well pump and sends a DTMF tone that is received by a DTMF relay board that does the switching of the pump and indicator lights.

My problem.... I am using event detect functions to do the sensing and triggering. I need a way for the script to auto detect the current tank level and act appropriately. For example... after a power failure, I need the pi to reboot, read its sensors and update the well's level indicators and pump control.

Redundancy is the name of the game here. I am fairly new to programming so there is some clean up to be done here.... but the biggest problem I am having is auto sensing on start up.

Thanks!

Code: Select all

import time
import RPi.GPIO as GPIO
import pygame
from subprocess import call

GPIO.setmode(GPIO.BOARD)

# 100% Pin
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# 2/3 Pin
GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# 1/3 Pin
GPIO.setup(15, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# KILL
GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

def my_callback(channel):
    if GPIO.input(11):
        print ('Tank was FULL - Now DRAINING')

        GPIO.setup(16, GPIO.OUT)
        time.sleep(4)
        GPIO.setup(18, GPIO.OUT)
        time.sleep(1)

        call(["aplay","/home/pi/Desktop/DTMF/3off.wav"])

        time.sleep(2)

        call(["aplay","/home/pi/Desktop/DTMF/3off.wav"])
        
        time.sleep(1)
        GPIO.setup(18, GPIO.IN)
        GPIO.setup(16, GPIO.IN)

        time.sleep(3)
    else:
        print ('Tank FULL')

        GPIO.setup(16, GPIO.OUT)
        time.sleep(4)
        GPIO.setup(18, GPIO.OUT)
        time.sleep(1)
        
        call(["aplay","/home/pi/Desktop/DTMF/3on4off.wav"])

        time.sleep(2)

        call(["aplay","/home/pi/Desktop/DTMF/3on4off.wav"])
       
        time.sleep(1)
        GPIO.setup(18, GPIO.IN)
        GPIO.setup(16, GPIO.IN)
        
        time.sleep(3)

def my_callback2(channel):
    if GPIO.input(13):
        print ('Tank 2/3 and DRAINING')

        GPIO.setup(16, GPIO.OUT)
        time.sleep(4)
        GPIO.setup(18, GPIO.OUT)
        time.sleep(1)

        call(["aplay","/home/pi/Desktop/DTMF/4on2off.wav"])

        time.sleep(2)

        call(["aplay","/home/pi/Desktop/DTMF/4on2off.wav"])
        
        time.sleep(1)
        GPIO.setup(18, GPIO.IN)
        GPIO.setup(16, GPIO.IN)
        
        time.sleep(3)
    else:
        print ('Tank 2/3')

        GPIO.setup(16, GPIO.OUT)
        time.sleep(4)
        GPIO.setup(18, GPIO.OUT)
        time.sleep(1)

        call(["aplay","/home/pi/Desktop/DTMF/2on.wav"])

        time.sleep(2)

        call(["aplay","/home/pi/Desktop/DTMF/2on.wav"])
        
        time.sleep(1)
        GPIO.setup(18, GPIO.IN)
        GPIO.setup(16, GPIO.IN)
        
        time.sleep(3)

def my_callback3(channel):
    if GPIO.input(15):
        print ('Tank 1/3 and DRAINING')

        GPIO.setup(16, GPIO.OUT)
        time.sleep(4)
        GPIO.setup(18, GPIO.OUT)
        time.sleep(1)

        call(["aplay","/home/pi/Desktop/DTMF/1off4on.wav"])

        time.sleep(2)

        call(["aplay","/home/pi/Desktop/DTMF/1off4on.wav"])

        time.sleep(1)
        GPIO.setup(18, GPIO.IN)
        GPIO.setup(16, GPIO.IN)
        
        time.sleep(3)
    else:
        print ('Tank 1/3')

        GPIO.setup(16, GPIO.OUT)
        time.sleep(4)
        GPIO.setup(18, GPIO.OUT)
        time.sleep(1)
        
        call(["aplay","/home/pi/Desktop/DTMF/1on4on.wav"])

        time.sleep(2)

        call(["aplay","/home/pi/Desktop/DTMF/1on4on.wav"])

        time.sleep(1)
        GPIO.setup(18, GPIO.IN)
        GPIO.setup(16, GPIO.IN)
        
        time.sleep(3)

#raw_input("Press Enter when ready\n>")

GPIO.add_event_detect(11, GPIO.BOTH, callback=my_callback, bouncetime=30000)

GPIO.add_event_detect(13, GPIO.BOTH, callback=my_callback2, bouncetime=30000)

GPIO.add_event_detect(15, GPIO.BOTH, callback=my_callback3, bouncetime=30000)

try:
    print('Waiting for input...')
    GPIO.wait_for_edge(7, GPIO.RISING)
    print('Program killed.')

except KeyboardInterrupt:
    GPIO.cleanup()
    
finally:
    GPIO.cleanup()

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Well Pump Control

Mon May 11, 2015 7:14 am

This problem has been solved zillions of times... without raspberry pi(s)... take a look at this:

http://www.next.gr/microcontrollers/805 ... 25613.html


Try to avoid using moving parts. Avoid using interrupts and callbacks. Make a simple event loop that starts running as soon as the PI boots and runs avery few minutes (30) this could be fired off from a crontab entry. Have the PI scan the sensor mcu (use a pyboard with micro python, or some other) and log, lights, signal whatever... then go back to sleep... the PI is free to do other things (not just be dedicated to your pumphouse).
marcus
:ugeek:

paulv
Posts: 563
Joined: Tue Jan 15, 2013 12:10 pm
Location: Netherlands

Re: Well Pump Control

Mon May 11, 2015 8:29 am

Gsrpi, this will not be so easy, if it needs to be a 100% solution.

An improvement to your current solution would be to store every detected event in a file. When the Pi boots, you can read the last event back in and continue. However, the weakness in your system remains, because you may miss an event while the Pi is rebooting.

The solution is to make absolutely sure you never miss an event, otherwise you don't know what the level is.

This would mean that you need to do the event detection at the tank, not by the Pi, and turn that event into a level the Pi can read. An edge triggered flip-flop could do that. You need to make sure that the level indicator gets reset when the level is above or below the sensor, or gets to another level. This calls for a state-machine. Google it if you don't know what that is.

An even better solution would be to create/use a level indicator that is contineous(analog), so you cannot miss an event. Now it's getting even more complicated, but more secure.

ame
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: New Zealand

Re: Well Pump Control

Mon May 11, 2015 10:57 am

The solution is not to use interrupts at all. Just poll the switches in a loop.

You don't even need a fast loop. Once per second would be more than adequate.

When the program starts, read the state of the three switches and store that* (it is your last_state). Next, make an infinite loop. At the beginning of the loop read the switch states. This is your current_state. If current_state differs from last_state then do the Right Thing. Then replace last_state with current_state, wait for one second or so and go round the loop again.

Simples.

* you don't even need to read the initial state. Just set last_state to NULL or something, then you will get a change of state immediately at the beginning of your loop, which you can use to set up your initial conditions.

Return to “Python”