Electronics‎ > ‎

Water level meter

Overview

Since access to our rain water basin is at best inconvenient, we want to create an easy way to monitor the water level.  We use the rain water for flushing toilets and for washing clothes.  Obviously, it's important we know when we're close to running out of water.

Originally our plan was to use eTape Liquid Level Sensor as described here:
However, that required us to create a solution with more than one of these eTape components, since the basis is close to  1 meter deep.  In addition, we'd have to be very careful with the installation since the tape would be directly in contact with the water.  This effectively creates contact between our circuitry and the rain water!

So we decided to use the Ultrasonic Ranger SRF04.  Both the connecting and programming for this component is very straight forward.

Detecting water level

Connecting the SRF04 to Arduino is described here: http://www.robot-electronics.co.uk/htm/arduino_examples.htm#SRF04 Ultrasonic Ranger.  And it comes with some demo code that works as is:

#define ECHOPIN 2                            // Pin to receive echo pulse
#define TRIGPIN 3                            // Pin to send trigger pulse

void setup() {
  pinMode(ECHOPIN, INPUT);
  pinMode(TRIGPIN, OUTPUT);
}

void loop() {
  digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
  delayMicroseconds(2);
  digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
  delayMicroseconds(10);
  digitalWrite(TRIGPIN, LOW);                   // Send pin low again
  int distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
  distance= distance/58;                        // divide by 58 gives cm.

//... more to come ...

}

Adding a display

Now we still need a way to visualize the water level.  For that purpose, we add an old 16x2 LCD display we had lying around.  Arduino IDE comes with a library that can drive the LCD display (based on Hitachi HD44780 driver).  We connect the Arduino IO as follows:

Arduino  
 PIN 2  SRF04 - Echo
 PIN 3  SRF04 - Trigger
 PIN 4  LCD - D7
 PIN 5  LCD - D6
 PIN 6  LCD - D5
 PIN 7  LCD - D4
 PIN 11  LCD - Enable
 PIN 12  LCD - RS

Application code for the Arduino

#include <LiquidCrystal.h>

#define ECHOPIN 2                            // Pin to receive echo pulse
#define TRIGPIN 3                            // Pin to send trigger pulse

#define STATUSPIN 13                        // Use for troubleshooting

int highWater = 36;        // These values allow to calculate % of full
int lowWater = 121;        // SRF04 hangs above water (lower distance = more water)

byte symbol[8] = {         // Custom character for LCD display
  B00000, 
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B00000,
};

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);    // Assign pins

// Utility function for flashing STATUSPIN
void flashLed(int pin, int times, int wait) {

  for (int i = 0; i < times; i++) {
    digitalWrite(pin, HIGH);
    delay(wait);
    digitalWrite(pin, LOW);

    if (i + 1 < times) {
      delay(wait);
    }
  }
}


void setup() {
  xbee.begin(9600);
  lcd.begin(16,2);
  lcd.print("Water level 1.0");
  lcd.createChar(0, symbol);
  pinMode(ECHOPIN, INPUT);
  pinMode(TRIGPIN, OUTPUT);

  delay(3000);       // Show application name for 3 seconds.

}

void loop() {
  // Measure distance
  digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
  delayMicroseconds(2);
  digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
  delayMicroseconds(10);
  digitalWrite(TRIGPIN, LOW);                   // Send pin low again
  int distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
  distance= distance/58;                        // divide by 58 gives cm.
  
  // Convert measured value to value between 0-16, to display on LCD
  // Use Arduino built-in map and constrain functions
  int scaledValue = map(constrain(distance, highWater, lowWater), lowWater, highWater, 0, 16);
  lcd.clear();
  lcd.print("Water niveau:");
  lcd.setCursor(0,1);
  while (scaledValue > 0) {
     lcd.print((char)0);
     scaledValue--;
  }
      
   delay(2000);  // Wait 2 seconds before measuring again. We're in no hurry!
}

This is the result on the LCD display:

Other

  • I've soldered a longer ethernet cable to the SRF04 and to the Arduino board.  Only the SRF04 sensor goes into the rain water basin.  The Arduino goes together with the LCD in a housing (still todo)
  • Not sure how 'humid proof' the SRF04 will be.  It's quite humid in the water basin, with drops hanging off the basin ceiling.  So we'll have to see how long it holds ;-)
  • Those of you paying attention might have noticed an XBee shield connected to the Arduino as well.  I expanded the project to have it send values wirelessly to my server. This allows me to integrate water level into my home automation user interface.  I might document that part of the document later.  XBee rocks!


Comments