Author Topic: Multiple Relay Irrigation Controller Arduino  (Read 21703 times)

Offline waynehead99

  • Sr. Member
  • ****
  • Posts: 296
  • Karma: +16/-1
Re: Multiple Relay Irrigation Controller Arduino
« Reply #30 on: June 15, 2014, 11:34:14 pm »
Correct, but no change at all on the relays, they all just remain on.

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #31 on: June 15, 2014, 11:37:57 pm »
Did you enter values in Variable1 and Variable2 on all devices?  I don't think they will come on at all if that value is zero. Update the values and restart Lua and refresh browser. Then, push reset on your arduino and turn on serial monitor. Verify that the values got into your arduino. It should report all your entries.


Sent from my iPhone using Tapatalk

Offline waynehead99

  • Sr. Member
  • ****
  • Posts: 296
  • Karma: +16/-1
Re: Multiple Relay Irrigation Controller Arduino
« Reply #32 on: June 15, 2014, 11:48:35 pm »
Thought the same thing so I put 5 in each. No change.

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #33 on: June 15, 2014, 11:55:17 pm »
Does the arduino report the values when you restart it with the serial monitor?

Offline waynehead99

  • Sr. Member
  • ****
  • Posts: 296
  • Karma: +16/-1
Re: Multiple Relay Irrigation Controller Arduino
« Reply #34 on: June 16, 2014, 12:45:34 pm »
This is what I receive:

Sensor Presentation Complete
All Valves OFF
Watering times collected from device: 0
Watering times collected from device: 1
Watering times collected from device: 2
Watering times collected from device: 3
Watering times collected from device: 4
Watering times collected from device: 5

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #35 on: June 16, 2014, 12:53:44 pm »
It should display both values you entered. This is telling me that it is not retrieving your values.

Jumping on a plane. Check for good radio, make sure you have saved values in the vera UI and restart your arduino with the serial monitor.

If still not working insert a delay of 2000 in the for loop where it gets the values. It may need a little time to grab those values.

Did you put a capacitor on the radio? 

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #36 on: June 16, 2014, 12:58:24 pm »
In setup like this:

Your values in vera need to be whole positive numbers.

Code: [Select]
  for (int i = 0; i < NUMBER_OF_VALVES + 1; i++)
  {
    gw.sendVariable( i, V_LIGHT, 0); //Display each Valve OFF
    valveTime [i] = atol(gw.getStatus( i, V_VAR1));// Get each Valve Cycle time
    delay(2000);
    valveSoloTime [i] = atol(gw.getStatus( i, V_VAR2));// Get each Valve Solo time
    delay(2000);
    Serial.print(F("Watering times collected from device: "));
    Serial.println(i);

Offline waynehead99

  • Sr. Member
  • ****
  • Posts: 296
  • Karma: +16/-1
Re: Multiple Relay Irrigation Controller Arduino
« Reply #37 on: June 16, 2014, 02:08:15 pm »
Ok making progress, realized i needed to have some patience as I see there is a delay in changes and the startup. Here is the monitor from startup:

Sensor Presentation Complete
All Valves OFF
Watering times collected from device: 0
Watering times collected from device: 1
Watering times collected from device: 2
Watering times collected from device: 3
Watering times collected from device: 4
Watering times collected from device: 5
Watering times collected from device: 6
Watering times collected from device: 7
Watering times collected from device: 8
Valve 0 cycle time=5
Valve 0 solo  time=10
Valve 1 cycle time=5
Valve 1 solo  time=10
Valve 2 cycle time=5
Valve 2 solo  time=10
Valve 3 cycle time=5
Valve 3 solo  time=10
Valve 4 cycle time=5
Valve 4 solo  time=10
Valve 5 cycle time=5
Valve 5 solo  time=10
Valve 6 cycle time=5
Valve 6 solo  time=10
Valve 7 cycle time=5
Valve 7 solo  time=10
READY


So now the issue is this. When I first plug everything in, all relays turn on and stay on. When I go into the vera UI and turn something on, it actually turns that relay off. So it appears it is all backwards. I am still looking to see what could be causing this, but at least things appear to be progressing now.

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #38 on: June 16, 2014, 03:11:50 pm »
Progress!

I can fix it programmatically, but do you have Normally Open and Normally closed selected properly on the relays?

Offline waynehead99

  • Sr. Member
  • ****
  • Posts: 296
  • Karma: +16/-1
Re: Multiple Relay Irrigation Controller Arduino
« Reply #39 on: June 16, 2014, 03:43:03 pm »
Ok I was going off the led lights on the relay board. Testing before hooking it up. All LEDs turn on when plugged in. I just tested by connecting it to one of my sprinklers and can get it to work the way it should. I should be good now, but was wanted the all relays off. Thanks again for all your help on this.

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #40 on: June 16, 2014, 03:47:41 pm »
No problem. Happy that you got it going.

Let me know how it goes.


Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #41 on: June 16, 2014, 05:25:35 pm »
Ok I was going off the led lights on the relay board. Testing before hooking it up. All LEDs turn on when plugged in. I just tested by connecting it to one of my sprinklers and can get it to work the way it should. I should be good now, but was wanted the all relays off. Thanks again for all your help on this.

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.



Code: [Select]
/*
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]);
  }
}

Offline waynehead99

  • Sr. Member
  • ****
  • Posts: 296
  • Karma: +16/-1
Re: Multiple Relay Irrigation Controller Arduino
« Reply #42 on: June 17, 2014, 11:14:48 pm »
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?

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #43 on: June 17, 2014, 11:38:36 pm »
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....

Code: [Select]
  shiftOut(dataPin, clockPin, LSBFIRST, value);
to

Code: [Select]
  shiftOut(dataPin, clockPin, MSBFIRST, value);
2) 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
« Last Edit: June 18, 2014, 12:56:14 am by BulldogLowell »

Offline BulldogLowell

  • Hero Member
  • *****
  • Posts: 1576
  • Karma: +191/-85
Re: Multiple Relay Irrigation Controller Arduino
« Reply #44 on: June 18, 2014, 08:27:34 am »
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?

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: [Select]
/*
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]);
  }
}