IMP Sprinkler

The idea for this project was seeded when a friend asked if it was possible to monitor the actual water usage of a sprinkler system on the the internet. The Flow measurement would tell you if a line was clogged or if a valve failed to close.

Having designed an Imp based controller for the Visible Energy NebulaMaster , I decided that the IMP would be the ideal platform for making this device. Inexpensive flow meters are available through E-Bay that output a pulse stream and fit standard 1 inch threaded PVC pipe. This is coupled in series with a standard Irrigation Valve [ actually up to eight valves in parallel in a complete system]. While searching for TRIAC circuits to use in this application I discovered the Open Sprinkler Project. This is a fairly complicated system that uses an ATMEGA chip, an Ethernet controller, and a ISM band radio.

Using an IMP simplifies the hardware design considerably. I designed a board that uses leaded thru-hole parts for easy assembly and provided for the use of the April Imp board for the surface mounted components. The IMP April is available through either Sparkfun or Adafruit along with the IMP SDcard. The board was laid out on Altium and fabricated at Sparkfun’s [ soon to be] I received at least 10 boards and have used 4 already.

To control the 8 channels of drive to the TRIACS , the IMP is operated in the SPI257 mode connected to a 73AHC595 serial shift in latch. The MISO pin2 is used as a reset for the shift register, while pin 8 is used to transfer the shifted data into the parallel output register. Pin1 is used as an accumulating pulse counter for measuring flow while Pin 9 is used to measure moisture in the soil connected like an ohmmeter with a resistor to VCC.

Preliminary tests show that the Imp can operated the TRIACS as designed and also measure the flow and moisture. at this point I’m trying to figure out how best to construct a server/webpage to control and schedule the IMP Sprinkler functionality

// Irrigation example for April on Sprinkler Board

// Variable to represent LED inhibit state
inhibit <- 0;

// SPI setup Pins 2.5.7
hardware.spi257.configure(SIMPLEX_TX | MSB_FIRST | CLOCK_IDLE_LOW, 200); // configure SPI_257 at about 4MHz

// pin7 (MISO) is used as a reset
hardware.pin2.write(0); //reset the 74HC595
hardware.pin2.write(1); //unreset the 74HC595

// pin8 (SPCS) is used as the chip select for the SPI

// Output port to send sensor readings
local out1 = OutputPort(“flow”, “number”);

local out2 = OutputPort(“rainsence”, “number”);

// Configure pin 1 as an input with internal pull up
hardware.pin1.configure(PULSE_COUNTER, 1 );

// Configure pin 9 (Rainsense) as an open drain output with internal pull up

// Configure pin 8 as an digital out

// Configure pin 9 as an Analog input
hardware.pin9.configure(ANALOG_IN );

//counter.configure(PULSE_COUNTER, 1); //read for 1 seconds

local counter = hardware.pin1;

function spiwrite (byte)
local triac_select;

hardware.pin2.write(0); // reset current value
hardware.pin2.write(1); // allow for change

hardware.pin8.write(0); // spi latch low

hardware.spi257.write(format("%c", byte)); // how do you write one byte?

hardware.pin8.write(1); // spi latch high


function sample() {
local lastRawValue =0;
local count =;
local rawValue =;

// check if this value is "different enough" from the last one so we don't send the same value over and over
if (math.abs(rawValue - lastRawValue) > 150) {
    // divide by 65535.0 to get a value between 0.0 and 1.0
    local potValue = rawValue / 65535.0;

    lastRawValue = rawValue;;

// Schedule the next state change
imp.wakeup(0.5, sample);


// input class for TRIAC control channel
class input extends InputPort

function set(value)
local valve = value;
local triac = 0;
if(value == 0)
//reset triacs
hardware.pin2.write(0); //zero shift reg
hardware.pin2.write(1); //un-zero shift reg
hardware.pin8.write(0); //get ready latch zero to output
hardware.pin8.write(1); //latch zero to output

      //value must be from 1 to 8
      valve = value & 0x0f;
      valve = valve - 1; //subtract 1 now is 0 to 7
      valve = valve & 0x07; // constrain 0 to 7"valve"+valve);
      triac = 0x01 <<valve;  //result is a single on bit shifter from 0 to 7"triac"+triac);
      hardware.pin7.write(1);  //disable reset
      spiwrite (triac)


// Register with the server
imp.configure(“Irrigation”, [input()], [out1, out2]);


// End of code

Nice, and looks just like our “Jane” board (which is also designed to fit into an open sprinker pre-cut case :slight_smile: ).

btw, to send one byte the format("%c",x) way is the best. SPI write wants a string or a blob. The alternative is to use a blob:

local b = blob(1); b[0]=x; spix.write(b);

Looks good, have you thought about linking it through some kind of weather api so it waters based on need, not just time?

not so good at that