Multiple Relay Irrigation Controller Arduino

I am trying to setup the 8 channel relay board on a nano and curious the best way to do this. I am using the current sketch for the relay and see that you can add the number of relays you want to use. I set it up to use 6 without issue, but don’t see how I can add the last 2 since the other digital pins are being used for the radio.

So can I use the analog pins be used for digital to get the last two put in place and if I can, how can I update the sketch for the nano to use those?

There are 14 pins that can be outputs:

[ul][li]2 are used by the serial connection[/li]
[li]6 are used by the radio[/li][/ul]

That leaves 6 for the relays, as you have found out. The analog pins cannot be used to drive relays. The radio IRQ pin is not used and doesn’t need to be connected. So that pin could potentially be used by disconnecting it from the radio. Then checking everything still works before reprogramming. Then change this line in the sketch:

#define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)

to

#define RELAY_1  2  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)

The RX/TX pins could be used but it would be best to leave these alone as they are pretty much permanently dedicated to the serial functionality and would require much stuffing around to get things working.

Another approach would be to use a single 8bit shift register (like the 74HC595). You can control 8 relays (per shift register) with just three digital pins.

There is an excellent tutorial on the Arduino website.

The component is very inexpensive and there are even breakout boards or shields to assist your wiring it in.

b[/b] I am sure we can get you the sketch modifications worked out too!

Thanks guys. I am using them to replace my sprinkler controller. I don’t know much about coding and since I need to get the sprinklers up I just used two nanos for now. I will look at the links though and build another.

OK, that is a solid approach too. :wink:

Knowing that you plan on running your irrigation helps, since you are likely not wanting to run more than a single zone at one time, yes?

I will post an 8 relay (multi) example with a shift register, I have been meaning to get to that myself. I have an etherrain 8 at one house, I wanted to use an arduino solution for the vacation house.

Great to know you have it working!

Yea. One zone at a time. The person that we bought the house from put a 6 zone controller in for 8 zones and doubled a few of them. So it never worked right and thought it a perfect time to add to my arduino network.

Appreciate the help and will look forward to the sketch.

An Arduino Mega 2560 might be another approach? Plenty of I/O there.

absolutely, and then some!

another good idea.

I was also thinking about doing this. I have been working on other projects so I haven’t had a chance to work on it yet but I thought I’d throw out an idea I had. I have had another relay node fail a couple of times (although since I upgraded to the latest build it had been rock solid for the last month). Because water costs much more than a light staying on for a couple more hours I was thinking of adding some code that would send the time and zone that should run to the Arduino instead of a simple on/off. That way if it stops communicating it would still shut itself off. I’m not good at coding so I don’t even know if this is possible but I thought I’d at least share the idea since others are doing the same thing.

Pete

That is a good point and I have been trying to brain storm ideas as well. For sure to use pleg because of random Vera restarts. But never thought about if you can have a timer set and pushed to the arduino as a fail safe.

@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); 
}

Like your shift register idea … only using 3 lines …

The approach can be generalized and you can cascade N 74HC595 to get multiples of N * 8 outputs.

Your sketch needs some changes to support a RELAY driver (mixed on/off states) … as opposed to a valve sequencer (only one output at a time on).

[quote=“RichardTSchaefer, post:12, topic:181385”]Like your shift register idea … only using 3 lines …

The approach can be generalized and you can cascade N 74HC595 to get multiples of N * 8 outputs.

Your sketch needs some changes to support a RELAY driver (mixed on/off states) … as opposed to a valve sequencer (only one output at a time on).[/quote]

Thanks for the comments. For this, I only want to 1)sequence the valves as there isn’t enough pressure to open them all at once and get good flow and 2) allow for hydraulic equilibrium between OFF and ON states of the valves.

This is a good one to put my old ME skills together with Arduino and some C++ :wink:

Wow thanks for that… question I have… looks like it still presents itself as a light (which is fine and expected), but confused by the notes at the beginning about updating time and sequence on/off. Can you explain a little more to me how in practice this would be used? I am ordering the parts for this right now :).

Thanks again for the help.

[quote=“waynehead99, post:14, topic:181385”]Wow thanks for that… question I have… looks like it still presents itself as a light (which is fine and expected), but confused by the notes at the beginning about updating time and sequence on/off. Can you explain a little more to me how in practice this would be used? I am ordering the parts for this right now :).

Thanks again for the help.[/quote]

Sure, since we are working with 8, I’ll use that example.

This will create 9 devices. Zero through 7 are the individual relays. Eight is the Sequencer, so to speak (refer to attachment).

Once you create this and add it using the gateway, go to each of zero through 7 and edit Variable1 and Variable2 for what time you want to use for the Sequencer or Zone respectively. Then save the settings. Then, restart your arduino; your arduino will extract these settings and save them to an array.

When you turn on device 8 (aka the Sequencer) the relays will actuate in order from zero to seven, each one staying on for the period entered in the Variable1 field. There is a 5 second delay at the start of a new zone to allow for the valves to hydraulically reset.

When you turn on any of devices zero through 7, it will run that zone only for the period of time entered in Variable2.

Selecting any new zone (0-8) will stop the current process and start as per above.

Does that make sense?

and yes, it looks like a light on the Vera UI. :-\

That is clear. Thanks for that… really helps clean up what I wanted to program in pleg too with those added options.

Would this work for those of us to don’t care to solder very much?

http://www.ebay.com/itm/Dual-Shift-Register-Breakout-Board-x2-74HC595-Arduino-Picaxe-Raspberry-Pi-/261486371179?pt=UK_BOI_Electrical_Components_Supplies_ET&hash=item3ce1cd616b

[quote=“waynehead99, post:16, topic:181385”]That is clear. Thanks for that… really helps clean up what I wanted to program in pleg too with those added options.

Would this work for those of us to don’t care to solder very much?

http://www.ebay.com/itm/Dual-Shift-Register-Breakout-Board-x2-74HC595-Arduino-Picaxe-Raspberry-Pi-/261486371179?pt=UK_BOI_Electrical_Components_Supplies_ET&hash=item3ce1cd616b[/quote]

Yes, that board will be fine. Realize that you will only use one of the two on-board shift registers, though.

That is a very nice board because it includes the capacitors wired close to the SR, which you will want in this application. The relays will draw some power.

I chose this way to program because I have one zone that I like to run an extra day when we are in the dry season.

Let us know how it works out.

ps

Wayne, would you mind to re-title this post something like" Multiple Relay Irrigation Controller Arduino" so that folks will find it if they search?

Another ask if it’s possible. Is there a way to had function to the sketch so that I could add a button to my box that could send an event to trigger a cycle on the sprinklers? Even if it was to just switch a virtual switch I could trigger off of. Be nice to have a manual way to kick of the sprinklers without my phone.

Okay.

Good idea. Maybe a status led too

Thanks again. Really appreciate the help. I have updated the first post heading as well.