@waynehead99 and @petewill,
I managed to whack this out, I debugged it, it works with the 74HC595. I was doing another project so I luckily had it wired up already.
It can do up to 8 Valves. If there is anyone out there with more than 8 zones, I’m happy to put this into a 16bit shift register, if you need help.
If it loses connection with the Vera, It will stop after the watering cycle finishes.
Look through the sketch, all the features are detailed in there.
Any suggestions to improve are appreciated.
I’ll post this on MySensors.org, too.
I cannot attach an .ino file so I embedded here
apologies for the update, I posted the wrong version (had not identified all the UL’s to do big math)
/*
Arduino Sprinkler Controller
June 2, 2014 12:00
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 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
* Compiles to ~12,000 Bytes, so will run on any Arduino
* 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.
* If you change your desired time intervals for your zones, simply restart your arduino
and it will self update
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 you valve count.
#define RESET_TIME 5000 // Change this (in milliseconds) for the time you need your valves to change state
unsigned long valveTime [9];
unsigned long valveSoloTime [9];
byte valveByte [8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int valveNumber;
byte state = 0;
unsigned long startMillis;
//
int latchPin = 8;
int clockPin = 4;
int dataPin = 7;
//
Sensor gw;
//
void setup()
{
Serial.begin(115200);
gw.begin();
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
//
gw.sendSketchInfo("Sprinkler", "1.0");
//
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);
}
Serial.println("Sensor Presentation Complete");
//
allValvesOff();
Serial.println("All Valves OFF");
//
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
valveSoloTime [i] = atol(gw.getStatus( i, V_VAR2));// Get each Valve Solo time
Serial.print("Watering times collected from device: ");
Serial.println(i);
}
for (int i = 0; i < NUMBER_OF_VALVES; i++)
{
Serial.print("Valve ");
Serial.print(i);
Serial.print(" cycle time=");
Serial.println(valveTime[i]);
Serial.print("Valve ");
Serial.print(i);
Serial.print(" solo time=");
Serial.println(valveSoloTime[i]);
}
Serial.println("READY");
}
//
void loop()
{
if (gw.messageAvailable()) {
message_s message = gw.getMessage();
setValveStatus(message);
}
if (state == 0)
{
allValvesOff();
}
if (state == 1) //Run all Valves
{
unsigned long nowMillis = millis();
if (nowMillis - startMillis < RESET_TIME)
{
allValvesOff();
}
else if (nowMillis - startMillis < (valveTime[valveNumber] * 60000UL))
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, valveByte [valveNumber]);
digitalWrite(latchPin, HIGH);
}
else if (nowMillis - startMillis > (valveTime [valveNumber] * 60000UL))
{
allValvesOff();
startMillis = millis();
gw.sendVariable( valveNumber, V_LIGHT, 0);
valveNumber++;
gw.sendVariable( valveNumber, V_LIGHT, 1);
if (valveNumber > NUMBER_OF_VALVES)
{
state = 0;
Serial.print("State = "); Serial.println(state);
gw.sendVariable( NUMBER_OF_VALVES + 1, V_LIGHT, 0);
}
}
}
if (state == 2)// Run single valve
{
unsigned long nowMillis = millis();
if (nowMillis - startMillis < RESET_TIME)
{
allValvesOff();
}
else if (nowMillis - startMillis < (valveSoloTime [valveNumber] * 60000UL))
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, valveByte [valveNumber]);
digitalWrite(latchPin, HIGH);
}
else if (nowMillis - startMillis > (valveSoloTime [valveNumber] * 60000UL))
{
allValvesOff();
state = 0;
Serial.print("State = "); Serial.println(state);
gw.sendVariable( valveNumber, V_LIGHT, 0);
}
}
}
//
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("All Valves Off");
Serial.print("state = ");
Serial.println(state);
}
else
{
if (valveNumber != NUMBER_OF_VALVES)
{
state = 2;
startMillis = millis();
Serial.print("Cycling Valve #: ");
Serial.println(valveNumber);
Serial.print("state = ");
Serial.println(state);
}
else
{
state = 1;
valveNumber = 0;
gw.sendVariable( valveNumber, V_LIGHT, 1);
startMillis = millis();
Serial.println("Cycling through ALL Valves");
Serial.print("state = ");
Serial.println(state);
}
}
}
}
//
void allValvesOff()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, 0x00);
digitalWrite(latchPin, HIGH);
}