A Wireless Sump Pump Not Working Alarm Using MicroPython and NodeMCU
A Wireless Flood Alarm Using MicroPython and NodeMCU

Several times over the years our sump pump or float switch has failed and part of our basement started to flood. This is especially nasty, as the flood isn't just water. It's sewer water. I purchased a cheap electronic alarm in the past, but it wasn't really what we needed. I don't know if this will be just what we need either, but since I built this one, I can at least adapt it as I see faults. Basically the system consists of a NodeMCU wireless device using an ESP8266, (costing about $3.00 from AliExpress), with a float switch that when tripped loads a web page on my local web server, an Odroid C1, running headless Ubuntu, and when that php web page is loaded, an email is sent to me (and anyone else I choose) saying the flood alarm went off, etc. I think I can find a way to get an email to be forwarded to our cell phones too, but at this point, I haven't done that.

On the Odroid C1, I installed the mailutils package, as well as php and apache2. I don't have any domain, so I just left that blank. The email just says it came from www-data, when it arrives in my Inbox. I put a web_page.php in /var/www/html that contains this kind of thing:

This is where I can put some email commands for the rest of my family, and SMS texts, so nobody runs any more water downstairs until the problem is resolved. It also makes a terrible racket at about 250 Hz through a speaker driven by an H bridge so anyone in the vicinity of the alarm will hear it as well and in case the emails and texts don't work for some reason.

To get MicroPython on the NodeMCU, I followed the instructions at the MicroPython github repository. First the development tools built nicely on my Ubuntu 16.10 laptop, then in the esp8266 directory, MicroPython built. I erased the flash as suggested, and used make deploy to flash the NodeMCU with MicroPython 1.8.6. I'm total newbie at python, and found the mu editor very helpful to eliminate syntax errors. I couldn't get it to flash the files to the NodeMCU, and had to go in to mu/mu/logic.py to help it find my device at /dev/ttyUSB3 as I described on the forum. Hopefully these issues are fixed sometime. In the meantime I cloned the webrepl repository, and was able to get it connected to the NodeMCU through my home router. It has a way to download files to the NodeMCU. I used this to test things out after getting the syntax to pass mu's test.

The float switch was purchased from AliExpress for about a dollar. The kind I have is seen below:

float switch
I connected it between D1 and ground on the NodeMCU. D1 is GPIO5 and is just abbreviated as 5 in MicroPython. The H bridge and with speaker are hooked to GPIO12 and GPIO14 (for IN_A and IN_B), and 3.3V and GND. I'm still a bit puzzled why I can't use the Vin pin to supply the H bridge with 5 volts, but when I hook it up there the voltage falls to zero. The schematic of the NodeMCU seemed to indicate it would supply voltage there when powered over USB, but it doesn't. I need to look into this some more, because 5 volts should make the alarm even louder, which would be better.

I found that MicroPython is a work in progress. It might have been easier in Lua that comes with NodeMCU, but I wanted to try MicroPython out, and to get some experience in Python. For the ESP8266 used on the NodeMCU, the most complete documentation at this time is the pdf on version 1.8.6. I found that a number of the things, even there, are not yet functional on the ESP8266 at this time (December 2016), but by testing, I found what works, and enough does. I was initially using a simple pin interrupt for this project, but after testing I found the the jerk that happens when the sump pump turns on caused the float switch to momentarily lose connection and trip the interrupt. To remedy this I went to checking to see if the float switch was up for consecutive seconds. My code is shown below. I put it in main.py, which the NodeMCU executes after boot.py upon start-up.

# This program in MicroPython for the NodeMCU is for sounding the # alarm if the sump pump fails. It will load a web page causing # emails to be sent; it also goes from blinking to solid blue LED; # Lastly if the alarm happens, it will make a racket at about 250 Hz # through the speaker. # # Rob Frohne, December 2016 from machine import Pin, Timer import socket import time import esp # Functions def toggle(p): # Toggle pin p.value(not p.value()) def http_get(url): # Get the web page at url _, _, host, path = url.split('/', 3) addr = socket.getaddrinfo(host, 80)[0][-1] s = socket.socket() s.connect(addr) s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')) while True: data = s.recv(100) if data: print(str(data, 'utf8'), end='') else: break def alarmSound(p): # This is to vibrate the speaker. global in_a global ib_b a = in_a.value() a = 0 if a else 1 # Toggle a b = 0 if a else 1 # b = not a in_a.value(a) in_b.value(b) # Initialization esp.osdebug(None) # turn off vendor O/S debugging messages esp.sleep_type(esp.SLEEP_LIGHT) notifyNow = False notificationSent = False notBuzzingYet = True secondsFlooded = 0 led = Pin(2, Pin.OUT) pin = Pin(5, Pin.IN, Pin.PULL_UP) tim = Timer(-1) in_a = Pin(12, Pin.OUT) # To H-Bridge IN_A in_b = Pin(14, Pin.OUT) # To H-Bridge IN_B print('This is the sump alarm program.') # Forever loop while True: time.sleep(1) if pin.value() == 1: secondsFlooded += 1 if secondsFlooded == 2: print('Sewage is up!') http_get('http://192.168.2.155/water.php') if secondsFlooded >= 2: led.low() if notBuzzingYet: tim.init(period=1, mode=Timer.PERIODIC, callback=alarmSound) else: toggle(led) secondsFlooded = 0 tim.deinit()

The blue LED on the NodeMCU flashes toggles on and off every second when no alarm has been reported, but when an alarm has been reported, it is on solid, and the speaker is making an annoying racket.

The NodeMCU is powered by a USB power supply. The float switch is normally closed, and is mounted in the sump .

Hopefully this keeps us from another problem the next time the sump pump or its float switch fails.