08 Dec

Fairmount Water Works Sensor

Now on display at the Fairmount Water Works—a simple soil moisture sensor with an LCD display to keep track of a plant’s watering needs. This is just a first step in developing some really interesting ways to monitor plants and get feedback on plant health. Working with two 10th grade students at Science Leadership Academy, we’ll be investigating how to use visuals, audio, and Twitter to communicate environmental data.  (We’ll also be investigating why we didn’t put the electronics in a waterproof case, because what’s more awesome than an unprotected circuit board next to a plant that’s being watered?)

This setup uses an Arduino Uno ($25), a Grove base shield ($10), a Grove LCD display ($14) and a Vegetronix VH400 soil moisture sensor ($37, though you can find soil moisture sensors for under $10; we like the performance of the VH400). The Grove shield stacks on top of the Arduino and lets you use snap-in wires to connect sensors and displays. The Arduino code is after the jump; it’s basically modified code from the Grove website.

We did a rudimentary calibration of the soil moisture sensor and got readings for the sensor in air, in dry soil, in wet soil, and immersed in water. From those measurements, we estimated readings below 200 would probably indicate the plant needs watering. It’s not an exact science, but we’ll learn more about what the sensor output means as we go along.

#include <SerialLCD.h>
#include <SoftwareSerial.h> //this is a must
#include <math.h>
// initialize the library
SerialLCD slcd(11,12);//this is a must, assign soft serial pins

const int soilPin = 0; // Connect soil moisture sensor to pin A0

void setup() {
// set up
// Print a message to the LCD.
slcd.print(“Moisture Reading is:”);
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
int sensorValue = analogRead( soilPin );
slcd.setCursor(0, 1);
// print the number of seconds since reset:
SLCDprintFloat( sensorValue ,1);
//  delay(1000);

void SLCDprintFloat(double number, uint8_t digits)
// Handle negative numbers
if (number < 0.0)
number = -number;

// Round correctly so that slcd.print(1.999, 2) prints as “2.00”
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;

number += rounding;

// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
float remainder = number – (float)int_part;
slcd.print(int_part , DEC); // base DEC

// Print the decimal point, but only if there are digits beyond
if (digits > 0)

// Extract digits from the remainder one at a time
while (digits– > 0)
remainder *= 10.0;
float toPrint = float(remainder);
slcd.print(toPrint , DEC);//base DEC
remainder -= toPrint;


Leave a Reply

Your email address will not be published. Required fields are marked *