Multiple Relay Irrigation Controller Arduino

No problem. Happy that you got it going.

Let me know how it goes.

FYI, I have not tested this but I added a few things to the sketch. Basically I added an hourly call back to vera to look for changes in Variable1 and Variable2. This way you can make the updates without having to restart your Arduino; makes sense to have this, I’m thinking.

Not much else changed…

Again, I have not tested it so let me know if you come across a bug in either version… or if you would like to see something added.

/*
Arduino Sprinkler Controller
 
 June 16, 2014
 
 Version 1.2    added hourly read of Vera to update zone times (when state == 0)
                moved zone times update to function
                added debug Serial.prints
                added instructions
 
 Version 1.1    added F() macro to Serial.prints, storing text constants to flash memory
                added pushbutton activation on interrupt 1 (pin 3) to cycle state 1
                added LED status indicator
 Version 1.0     
 
 Arduino Multi-Zone Sprinkler Control
 
 Utilizing your Vera home automation controller and the MySensors.org gateway you can
 control up to an eight zone irrigation system with only three digital pins.  This sketch 
 will create n+1 devices on your Vera controller
 
 This sketch features the following:
 
 * Allows you to cycle through All zones or individual zone control.  
 * Use the (n+1)th controller to activate AllZone (each zone in numeric sequence zero to n) using 
   Variable1 as the "ON" time in minutes in each of the vera devices created.
 * Use the individual zone controller to activate a single zone.  This feature uses 
   Variable2 as the "ON" time for each individual device/zone.
 * Connect according to pinout below and uses an 74HC595 (or equiv) Shift Register as to 
   allow the MySensors standard radio configuration and still leave available digital pins
 * Turning on any zone will stop the current process and begin that particular process.
 * Turning off any zone will stop the current process and turn off all zones.
 * Sketch must collect your times so it takes several minutes to startup.
 * To push your new time intervals for your zones, simply restart your arduino 
   and it will self update, otherwise it will call to Vera once an hour and update accordingly
 * Pushbutton activation
 * LED status indicator
 
 INSTRUCTIONS:
 
 * After assembling your arduino, radio, decoupling capacitor, shift register, status LED, pushbutton and relays, load the sketch.
 * Following the instructions at MySensors.org, add the device to your MySensors Gateway.
 * Restart lua, wait for it to restart and refresh your browser.
 * Verify that each new device has a Variable1 and Variable2; they can be zero.  Populate data accordingly with whole minutes for 
   the AllZone routine and the SoloZone routines.
 * Once you have entered values for each zone and each variable, save the settings by pressing the red save button on your Vera.
 * Restart your arduino; verify the settings are loaded into your arduino with the serial monitor; the array will be printed
   on the serial monitor.
 * Your arduino should slow-flash, indicating that it is in ready mode.
 * There are multiple debug serial prints that can be monitored to assure that it is operating properly.
 
 by Jim (BulldogLowell@gmail.com) for free public use
 
 */
#include <Relay.h>
#include <SPI.h>
#include <EEPROM.h> 
#include <RF24.h>
//
#define NUMBER_OF_VALVES 8 // Change this to set your valve count.
#define RESET_TIME 5000    // Change this (in milliseconds) for the time you need your valves to hydraulically change state
unsigned long valveTime [NUMBER_OF_VALVES + 1];
unsigned long valveSoloTime [NUMBER_OF_VALVES + 1];
byte valveByte [8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };// this array is good up to eight valve positions, even if you select less.
int valveNumber;
byte state = 0;
unsigned long startMillis;
const unsigned long ledInterval = 100;
const unsigned long slowLedInterval = 1250;
unsigned long ledTimer;
unsigned long slowLedTimer;
unsigned long oneHour = 3600000UL;
unsigned long hourTimer;
//
int latchPin = 8;
int clockPin = 4;
int dataPin  = 7;
int pin = 3;//interrupt 1
int ledPin = 5; // LED status blinks fast while changing a valve; steady during valve open or initialization; and slow blink when in stand-by
boolean buttonPushed = false;
// 
Sensor gw;
//
void setup() 
{ 
  Serial.begin(115200);
  gw.begin();
  //
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(pin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  attachInterrupt(1, PushButton, CHANGE);
  //
  digitalWrite (ledPin, HIGH);
  gw.sendSketchInfo("Sprinkler", "1.1");
  //
  for (int i=0; i<NUMBER_OF_VALVES + 1; i++) // Register all valves to gw (they will be created as child devices)
  {
    gw.sendSensorPresentation(i, S_LIGHT);
    delay(250);
  }
  Serial.println(F("Sensor Presentation Complete"));
  //
  updateRelays(0x00);
  for (int i = 0; i < NUMBER_OF_VALVES + 1; i++)
  {
    gw.sendVariable( i, V_LIGHT, 0); //Display each Valve OFF
    delay(250);
  }
  Serial.println(F("All Valves OFF"));
  getTimesVera();
  hourTimer = millis();
  digitalWrite (ledPin, LOW);//ready
  Serial.println(F("READY"));
}
//
void loop()
{
  if (gw.messageAvailable()) 
  {
    message_s message = gw.getMessage();
    setValveStatus(message);
  }
  if (buttonPushed)
  {
    state = 1;
    valveNumber = 0;
    gw.sendVariable( valveNumber, V_LIGHT, 1);
    gw.sendVariable( NUMBER_OF_VALVES, V_LIGHT,1);
    startMillis = millis();
    buttonPushed = false; 
    Serial.println(F("AllZone Cycling through ALL Valves"));
    Serial.print(F("state = ")); 
    Serial.println(state);  
  }
  if (state == 0) 
  {
    unsigned long nowMillis=millis();
    if ( (nowMillis - slowLedTimer) >= slowLedInterval)
    {
      slowToggleLED ();
    }
    updateRelays(0x00);
    //Get updated variables once an hour
    if (millis() - hourTimer >= oneHour)
    {
      getTimesVera();
      hourTimer = millis();
    } 
  }//End of state 0
  if (state == 1) //Cycle throug all Valves
  { 
    unsigned long nowMillis = millis();
    if (nowMillis - startMillis < RESET_TIME)
    {
      if ( (nowMillis - ledTimer) >= ledInterval)
      {
        toggleLED ();
      }
      updateRelays(0x00);
    }
    else if (nowMillis - startMillis < (valveTime[valveNumber] * 60000UL))
    {
      digitalWrite (ledPin, HIGH);
      updateRelays(valveByte [valveNumber]);
    }
    else if (nowMillis - startMillis > (valveTime [valveNumber]  * 60000UL))
    {
      updateRelays(0x00);
      startMillis = millis();
      gw.sendVariable( valveNumber, V_LIGHT, 0);
      valveNumber++;
      gw.sendVariable( valveNumber, V_LIGHT, 1);
      if (valveNumber > NUMBER_OF_VALVES) 
      {
        state = 0;
        digitalWrite (ledPin, LOW);
        Serial.print(F("State = ")); 
        Serial.println(state);
        gw.sendVariable( NUMBER_OF_VALVES + 1, V_LIGHT, 0);
      }
    }
  }//End of State 1
  //
  if (state == 2)// Run single valve
  {
    unsigned long nowMillis = millis();
    if (nowMillis - startMillis < RESET_TIME)
    {
      if ( (nowMillis - ledTimer) >= ledInterval)
      {
        toggleLED ();
      }
      updateRelays(0x00);
    }
    else if (nowMillis - startMillis < (valveSoloTime [valveNumber] * 60000UL))
    {
      digitalWrite (ledPin, HIGH);
      updateRelays(valveByte [valveNumber]);
    }
    else if (nowMillis - startMillis > (valveSoloTime [valveNumber] * 60000UL))
    {
      updateRelays(0x00);
      ;
      state = 0;
      digitalWrite (ledPin, LOW);
      Serial.print(F("State = ")); 
      Serial.println(state);
      gw.sendVariable( valveNumber, V_LIGHT, 0);
    }
  }//End of State 2
}//End of loop ()
//
void setValveStatus(message_s message) 
{
  if (message.header.messageType==M_SET_VARIABLE && message.header.type==V_LIGHT) 
  {
    valveNumber = message.header.childId;
    int incomingRelayStatus = atoi(message.data);
    if (incomingRelayStatus != 1)
    {
      state = 0;
      Serial.println(F("All Valves Off"));
      Serial.print(F("state = ")); 
      Serial.println(state);
    }
    else
    { 
      if (valveNumber < NUMBER_OF_VALVES)
      {
        state = 2;
        startMillis = millis();
        Serial.print(F("SingleZone Cycling Valve #: ")); 
        Serial.println(valveNumber);
        Serial.print(F("state = ")); 
        Serial.println(state);
      }
      else 
      {
        state = 1;
        valveNumber = 0;
        gw.sendVariable( valveNumber, V_LIGHT, 1);
        startMillis = millis();
        Serial.println(F("Cycling through ALL Valves"));
        Serial.print(F("state = ")); 
        Serial.println(state);
      }
    }
  }
}
//
void updateRelays(byte value)
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, value); 
  digitalWrite(latchPin, HIGH);
}
//
void PushButton(){ //interrupt with debounce
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  if (interrupt_time - last_interrupt_time > 200)
  {
    Serial.println(F("interrupt"));
    buttonPushed = true;
  }
  last_interrupt_time = interrupt_time;
}
//
void toggleLED ()
{
  if (digitalRead (ledPin) == LOW)
    digitalWrite (ledPin, HIGH);
  else
    digitalWrite (ledPin, LOW);
  ledTimer = millis ();  
}
//
void slowToggleLED ()
{
  if (digitalRead (ledPin) == LOW)
    digitalWrite (ledPin, HIGH);
  else
    digitalWrite (ledPin, LOW);
  slowLedTimer = millis ();  
}
//
void  getTimesVera()
{
  for (int i = 0; i < NUMBER_OF_VALVES + 1; i++)
  {
    valveTime [i] = atol(gw.getStatus( i, V_VAR1));// Get each Valve Cycle time
    delay(250);
    valveSoloTime [i] = atol(gw.getStatus( i, V_VAR2));// Get each Valve Solo time
    delay(250);
    Serial.print(F("Watering times collected from device: ")); 
    Serial.println(i);
  }
    for (int i = 0; i < NUMBER_OF_VALVES; i++)
  {
    Serial.print(F("Valve ")); 
    Serial.print(i); 
    Serial.print(F(" cycle time=")); 
    Serial.println(valveTime[i]);
    Serial.print(F("Valve ")); 
    Serial.print(i); 
    Serial.print(F(" solo  time=")); 
    Serial.println(valveSoloTime[i]);
  } 
}

Hey Jim, have a quick question. On your setup do all your relays stay on, and then turn off when selected? This is what mine is doing and at first it didn’t bother me, but now that I am trying to put it into an enclosure, I am noticing that the heat is a little concerning leaving all the relays on.

Is there something I could do to help with this?

It should not be energizing the relays except when they are active. It isn’t good to enclose this or use it this way.

Can you send the specs for the relay board. It should not be activating relays with zero voltage, but perhaps either your shift register or relays are different than I expect.

0x00 is equivalent to sending a zero to all eight pins on the shift register, and therefore all pins should be LOW

I’d like you to try a couple of things:

  1. Edit the LSBFIRST to MSBFIRST. It should have no effect on the 0x00 byte, but maybe your shift register is looking for that order. I wouldn’t expect this to matter…

shiftOut(dataPin, clockPin, LSBFIRST, value);

to

  shiftOut(dataPin, clockPin, MSBFIRST, value); 
  1. replace 0x00 (every occurrence) with 0xFF. This changes the zero state byte from B00000000 to B11111111. (all off to all on)

if either of these work (try #1 first). Let me know and I’ll tell you what to do, we have to edit your sketch (and scratch our heads)

please check the relays for me, looking to see that it is wired correctly, especially.

Are there any jumpers on your relay board?

Can you please shoot me a photo? you have my email in the sketch if the photos are too big

Sent from my iPhone using Tapatalk

[quote=“waynehead99, post:43, topic:181385”]Hey Jim, have a quick question. On your setup do all your relays stay on, and then turn off when selected? This is what mine is doing and at first it didn’t bother me, but now that I am trying to put it into an enclosure, I am noticing that the heat is a little concerning leaving all the relays on.

Is there something I could do to help with this?[/quote]

If #2 works to de-energize the relays then try this modified sketch.

I noticed on Hek’s website that his relay bank says “Active Low” so we may need to invert the bytes on the sketch (not sure you used that relay).

I cannot test it so please do that. It includes the fetch for Variable1 and Variable2, which I have not tested either…

fingers crossed. :-\

[code]/*
Arduino Sprinkler Controller

June 16, 2014

Version 1.2a converted to active LOW

Version 1.2 added hourly read of Vera to update zone times (when state == 0)
moved zone times update to function
added debug Serial.prints
added instructions

Version 1.1 added F() macro to Serial.prints, storing text constants to flash memory
added pushbutton activation on interrupt 1 (pin 3) to cycle state 1
added LED status indicator
Version 1.0

Arduino Multi-Zone Sprinkler Control

Utilizing your Vera home automation controller and the MySensors.org gateway you can
control up to an eight zone irrigation system with only three digital pins. This sketch
will create n+1 devices on your Vera controller

This sketch features the following:

  • Allows you to cycle through All zones or individual zone control.
  • Use the (n+1)th controller to activate AllZone (each zone in numeric sequence zero to n) using
    Variable1 as the “ON” time in minutes in each of the vera devices created.
  • Use the individual zone controller to activate a single zone. This feature uses
    Variable2 as the “ON” time for each individual device/zone.
  • Connect according to pinout below and uses an 74HC595 (or equiv) Shift Register as to
    allow the MySensors standard radio configuration and still leave available digital pins
  • Turning on any zone will stop the current process and begin that particular process.
  • Turning off any zone will stop the current process and turn off all zones.
  • Sketch must collect your times so it takes several minutes to startup.
  • To push your new time intervals for your zones, simply restart your arduino
    and it will self update, otherwise it will call to Vera once an hour and update accordingly
  • Pushbutton activation
  • LED status indicator

INSTRUCTIONS:

  • After assembling your arduino, radio, decoupling capacitor, shift register, status LED, pushbutton and relays, load the sketch.
  • Following the instructions at MySensors.org, add the device to your MySensors Gateway.
  • Restart lua, wait for it to restart and refresh your browser.
  • Verify that each new device has a Variable1 and Variable2; they can be zero. Populate data accordingly with whole minutes for
    the AllZone routine and the SoloZone routines.
  • Once you have entered values for each zone and each variable, save the settings by pressing the red save button on your Vera.
  • Restart your arduino; verify the settings are loaded into your arduino with the serial monitor; the array will be printed
    on the serial monitor.
  • Your arduino should slow-flash, indicating that it is in ready mode.
  • There are multiple debug serial prints that can be monitored to assure that it is operating properly.

by Jim (BulldogLowell@gmail.com) for free public use

*/
#include <Relay.h>
#include <SPI.h>
#include <EEPROM.h>
#include <RF24.h>
//
#define NUMBER_OF_VALVES 8 // Change this to set your valve count.
#define RESET_TIME 5000 // Change this (in milliseconds) for the time you need your valves to hydraulically change state
unsigned long valveTime [NUMBER_OF_VALVES + 1];
unsigned long valveSoloTime [NUMBER_OF_VALVES + 1];
byte valveByte [8] = { B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111 };// this array is good up to eight valve positions, even if you select less.
int valveNumber;
byte state = 0;
unsigned long startMillis;
const unsigned long ledInterval = 100;
const unsigned long slowLedInterval = 1250;
unsigned long ledTimer;
unsigned long slowLedTimer;
unsigned long oneHour = 3600000UL;
unsigned long hourTimer;
//
int latchPin = 8;
int clockPin = 4;
int dataPin = 7;
int pin = 3;//interrupt 1
int ledPin = 5; // LED status blinks fast while changing a valve; steady during valve open or initialization; and slow blink when in stand-by
boolean buttonPushed = false;
//
Sensor gw;
//
void setup()
{
Serial.begin(115200);
gw.begin();
//
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(pin, OUTPUT);
pinMode(ledPin, OUTPUT);
attachInterrupt(1, PushButton, CHANGE);
//
digitalWrite (ledPin, HIGH);
gw.sendSketchInfo(“Sprinkler”, “1.1”);
//
for (int i=0; i<NUMBER_OF_VALVES + 1; i++) // Register all valves to gw (they will be created as child devices)
{
gw.sendSensorPresentation(i, S_LIGHT);
delay(250);
}
Serial.println(F(“Sensor Presentation Complete”));
//
updateRelays(0xFF);
for (int i = 0; i < NUMBER_OF_VALVES + 1; i++)
{
gw.sendVariable( i, V_LIGHT, 0); //Display each Valve OFF
delay(250);
}
Serial.println(F(“All Valves OFF”));
getTimesVera();
hourTimer = millis();
digitalWrite (ledPin, LOW);//ready
Serial.println(F(“READY”));
}
//
void loop()
{
if (gw.messageAvailable())
{
message_s message = gw.getMessage();
setValveStatus(message);
}
if (buttonPushed)
{
state = 1;
valveNumber = 0;
gw.sendVariable( valveNumber, V_LIGHT, 1);
gw.sendVariable( NUMBER_OF_VALVES, V_LIGHT,1);
startMillis = millis();
buttonPushed = false;
Serial.println(F(“AllZone Cycling through ALL Valves”));
Serial.print(F("state = "));
Serial.println(state);
}
if (state == 0)
{
unsigned long nowMillis=millis();
if ( (nowMillis - slowLedTimer) >= slowLedInterval)
{
slowToggleLED ();
}
updateRelays(0xFF);
//Get updated variables once an hour
if (millis() - hourTimer >= oneHour)
{
getTimesVera();
hourTimer = millis();
}
}//End of state 0
if (state == 1) //Cycle throug all Valves
{
unsigned long nowMillis = millis();
if (nowMillis - startMillis < RESET_TIME)
{
if ( (nowMillis - ledTimer) >= ledInterval)
{
toggleLED ();
}
updateRelays(0xFF);
}
else if (nowMillis - startMillis < (valveTime[valveNumber] * 60000UL))
{
digitalWrite (ledPin, HIGH);
updateRelays(valveByte [valveNumber]);
}
else if (nowMillis - startMillis > (valveTime [valveNumber] * 60000UL))
{
updateRelays(0xFF);
startMillis = millis();
gw.sendVariable( valveNumber, V_LIGHT, 0);
valveNumber++;
gw.sendVariable( valveNumber, V_LIGHT, 1);
if (valveNumber > NUMBER_OF_VALVES)
{
state = 0;
digitalWrite (ledPin, LOW);
Serial.print(F("State = "));
Serial.println(state);
gw.sendVariable( NUMBER_OF_VALVES + 1, V_LIGHT, 0);
}
}
}//End of State 1
//
if (state == 2)// Run single valve
{
unsigned long nowMillis = millis();
if (nowMillis - startMillis < RESET_TIME)
{
if ( (nowMillis - ledTimer) >= ledInterval)
{
toggleLED ();
}
updateRelays(0xFF);
}
else if (nowMillis - startMillis < (valveSoloTime [valveNumber] * 60000UL))
{
digitalWrite (ledPin, HIGH);
updateRelays(valveByte [valveNumber]);
}
else if (nowMillis - startMillis > (valveSoloTime [valveNumber] * 60000UL))
{
updateRelays(0xFF);
;
state = 0;
digitalWrite (ledPin, LOW);
Serial.print(F("State = "));
Serial.println(state);
gw.sendVariable( valveNumber, V_LIGHT, 0);
}
}//End of State 2
}//End of loop ()
//
void setValveStatus(message_s message)
{
if (message.header.messageType==M_SET_VARIABLE && message.header.type==V_LIGHT)
{
valveNumber = message.header.childId;
int incomingRelayStatus = atoi(message.data);
if (incomingRelayStatus != 1)
{
state = 0;
Serial.println(F(“All Valves Off”));
Serial.print(F("state = "));
Serial.println(state);
}
else
{
if (valveNumber < NUMBER_OF_VALVES)
{
state = 2;
startMillis = millis();
Serial.print(F("SingleZone Cycling Valve #: "));
Serial.println(valveNumber);
Serial.print(F("state = "));
Serial.println(state);
}
else
{
state = 1;
valveNumber = 0;
gw.sendVariable( valveNumber, V_LIGHT, 1);
startMillis = millis();
Serial.println(F(“Cycling through ALL Valves”));
Serial.print(F("state = "));
Serial.println(state);
}
}
}
}
//
void updateRelays(byte value)
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, value);
digitalWrite(latchPin, HIGH);
}
//
void PushButton(){ //interrupt with debounce
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 200)
{
Serial.println(F(“interrupt”));
buttonPushed = true;
}
last_interrupt_time = interrupt_time;
}
//
void toggleLED ()
{
if (digitalRead (ledPin) == LOW)
digitalWrite (ledPin, HIGH);
else
digitalWrite (ledPin, LOW);
ledTimer = millis ();
}
//
void slowToggleLED ()
{
if (digitalRead (ledPin) == LOW)
digitalWrite (ledPin, HIGH);
else
digitalWrite (ledPin, LOW);
slowLedTimer = millis ();
}
//
void getTimesVera()
{
for (int i = 0; i < NUMBER_OF_VALVES + 1; i++)
{
valveTime [i] = atol(gw.getStatus( i, V_VAR1));// Get each Valve Cycle time
delay(250);
valveSoloTime [i] = atol(gw.getStatus( i, V_VAR2));// Get each Valve Solo time
delay(250);
Serial.print(F("Watering times collected from device: "));
Serial.println(i);
}
for (int i = 0; i < NUMBER_OF_VALVES; i++)
{
Serial.print(F(“Valve “));
Serial.print(i);
Serial.print(F(” cycle time=”));
Serial.println(valveTime[i]);
Serial.print(F(“Valve “));
Serial.print(i);
Serial.print(F(” solo time=”));
Serial.println(valveSoloTime[i]);
}
}
[/code]

That worked… Thanks again.

Great. Let me know if it works out okay, particularly the hourly fetch.

One question I have as I want to learn more about this stuff. Do you think there is a way to add an LCD panel to the thing? I might be asking too much of the arduino at this pony but if it’s possible I might start trying to do some research on how to program it.

You can add an LCD, because you still have a lot of outputs. Look at a 16X2 LCD display with an on-board I2C interface and you can easily add it to your arduino and to your sketch. It will use pins A4 and A5.

This Book is a great resource.

Hey Jim,
Sorry to be a pest again, but I updated my system to the new 1.4 beta. I was holding off as long as I could, but I found an issue with 1.3 that kept causing my vera to restart. Upgrading resolved this issue. Now though, my sprinkler system that you setup for me doesn’t communicate anymore. I was able to update all my other sketchs for other sensors without issues because they are simple. This one appears to be above my head on updating. I think its referencing some things in the RF24 folder that isn’t in the new 1.4 builds. Think you could help me out in updating the sketch to work with 1.4?

[quote=“waynehead99, post:50, topic:181385”]Hey Jim,
Sorry to be a pest again, but I updated my system to the new 1.4 beta. I was holding off as long as I could, but I found an issue with 1.3 that kept causing my vera to restart. Upgrading resolved this issue. Now though, my sprinkler system that you setup for me doesn’t communicate anymore. I was able to update all my other sketchs for other sensors without issues because they are simple. This one appears to be above my head on updating. I think its referencing some things in the RF24 folder that isn’t in the new 1.4 builds. Think you could help me out in updating the sketch to work with 1.4?[/quote]

Wayne,

I haven’t upgraded yet, but I am thinking about doing that over the weekend or next week.

Let me look at the updated IDE and give it a go for you. Also, we discussed it but I don’t remember, did you eventually add the LCD display to your controller? I just need to know which version to update.

I’m glad you are happy with the improvements in the new IDE. I’m looking forward to getting that installed too. Lots of power interruptions this summer have caused me trouble with my gateway staying connected.

Bet Regards,

Jim

Thanks. I haven’t added the LCD yet. Life keeps getting in the way. No rush. I reverted back to 1.3 for now just to get them going again. Here in Denver we have been pushing 100 for the past week with more to come so I needed to keep them running. Thanks again for all your help.

as it happens, Hek’s site is down anyways, so once that’s back up, I’ll take a look.

that’s too hot…

Wayne, I have the Irrigation Controller for MySensors converted to 1.4.1 to control your sprinklers.

I added an LCD display to the sketch (you asked about that) and it will now control up to 16 valves.

Check out the updated device with new features… Great demo and build tutorial by @PeteWill can help anyone build this!

Irrigation Controller for Vera on YouTube