Saturday, January 14, 2012

Remote Control Sprinklers: The Irrduino Project

So... I connected my lawn to the internet.



More specifically, I built an internet-based control for the thing that most contributes to the on-going health of my lawn. That is, the sprinklers.

I call this project Irrduino, because at the core of it is an Arduino microcontroller that lets me remotely control the irrigation zones at my house. Irrduino communicates via Ethernet and standard html requests and responses (specifically a REST interface with JSON responses, for you web geeks out there) which means I can control my sprinklers from anywhere on the planet with a web browser and an internet connection, or any smartphone with the same.

Why the heck would I want to do that?

Well, first and foremost, because I can. I wanted to see if I could do it. Beyond that, there are some very practical reasons for wanting to do this, which should be readily understood by anyone who has ever had to do maintenance on sprinklers. They need to be tested regularly, and when you test sprinklers, it’s best to be able to chose exactly where you are standing when the water comes on. So being able to turn them on from my phone is very handy for testing. But that’s not the best part.

The best part, by far, is being across the street at my neighbor’s house and seeing the neighborhood cat preparing to use my lawn as a a toilet, pulling out my phone, pushing a button and watching the feline fur fly.

Hardware


I started with the Android Accessory Development Kit (ADK) as my Arduino platform. In retrospect, this board is massive overkill for the project, but it’s nice to have a extra headroom just in case. I knew early on that I didn’t want to have the ADK plugged into my phone so I invested in an Ethernet Shield so I could connect it to my home network. After it arrived, I spent about a week trying to figure out why it didn’t work, until I discovered that the shield needs to be plugged into the Arduino ISCP header pins, which don’t exist, as such, on the ADK. Luckily those connections can be made separately, and once I figured that out, it was off to the races with a teeny, tiny little web server.

Next, I needed a way to control the higher voltage circuits of the sprinkler value solenoids. Sprinkler systems typically run at 24 volts and somewhere between 700 and 1000 milliamps. After a bit of research on the topic, I figured out the electronic component I needed to control these higher power circuits was called a relay. Being rather new to electronics engineering, I settled on something that was prebuilt and designed to work with Arduino. For that reason, I bought a few of Seeed Studio’s Relay Shields, waited for them to show up, then hooked them up and once again spent another a week trying to figure out why they didn’t work.

Turns out the Relay Shields are a bit power hungry. Running them off the 5-ish volts of USB power that easily runs the ADK and the Ethernet Shield, is not enough to run the Relay Shields. It’s a bit annoying, but easily solved with 9 volt wall adapter plug connected to the ADK, and then connecting the Vin power pin and neighboring ground to a power bus connected to the power inputs for the Relay Shields.

Wiring


After bringing all this hardware together, I started wiring it all up and writing the Arduino control software. The first task (after figuring out that the the shields needed 9 volts of power) was connecting the control wires to the Relay Shields signal inputs. After a quite a bit of experimentation, I settled on using standard Arduino pins 2 though 9 for controlling the first two shields, and pins 11 and 12 for the third shield.

There were a couple of key learnings from the wire-up process:

  • Don’t Use Pins 0, 1, 10, 13: These pins receive quite a bit of signalling for other purposes, so don’t try to use these as output controls for the relays. Pin 13 on the ADK, in particular, gets flashed quite a bit when you upload new programs, which I spend a lot of time doing. Once you have a program that you are happy with and don’t need to update, it may be OK to use it.
  • NC, NO: What’s that? On the Seeed Studios Relay shield the big, green screw terminals are labeled NC#, COM#, NO#. This stands for Normally Open (NO), common wire (COM) and Normally Closed (NC). For use with a sprinkler system, the control circuits are usually disconnected (Open) and only connected when the sprinkler valves are open, so I used the NO terminals to connect the sprinkler valve circuits.

Software


There are several separate software projects that contribute to the functionality of Irrduino:

  • IrrduinoController - This software runs on the ADK / Arduino microcontroller and is the core of the Irrduino project. It runs a small web server, handles the http REST requests, activates and deactivates the relays to turn the sprinkler values on and off.
  • IrrduinoRemote - This Android application is what I'm using in the video to activate the IrrduinoController. There is not much to this application, because there doesn't need to be. I wrote the original, functional version in about 3 days.
  • IrrduinoServer - This Google App Engine server application acts as a reporting backend and alternative controller it was written in Python by my partner in crime on this project, JJ Behrens.

The IrrduinoController software presents REST-like interface for client applications like the IrrduinoRemote app, the IrrduinoServer, or anyone with a web browser. The software call for turning on a sprinkler valve drives digital output HIGH, thereby activating a relay, closing a circuit for one of the valve pumps and turning on the water. Once you know which sprinkler zone to activate and the digital pin associated with it, all you need to do is call:

// turn on selected zone
digitalWrite(pin, HIGH);

More challenging is receiving and interpreting a REST command to turn on a zone, and running a sprinkler zone for a specified amount of time without blocking the processing thread. Luckily, I had some help and inspiration for interpreting REST commands from Jason Gullickson’s excellent RESTduino project. For the non-blocking timer, the Arduino forums were quite helpful in suggesting setting a end time with the millis() function and running a check function on each loop.

There was a lot of trial and error and rework for the Arduino code, and I’m already planning a major refactor to make extension of the Irrduino code. I’ll let the code speak for itself, with the caveat that it is not particularly elegant but, it works.


Irrduino 2.0


As I was working on this project, it became clear to me that the Irrduino system could easily do more than just remotely activate my sprinklers; it could actually run them, full time, and thus allow me to replace my commercial controller with a completely open source, open hardware solution that would give me way more control and flexibility in how I watered my landscape. I could give it a regular schedule to run, and then give it enough smarts to adjust watering based on seasonal timing, predicted weather, actual rain (rain sensor), or do even smarter things like automatic soak-wait-soak scheduling, water budgeting and more.

For Irrduino 2.0, I plan to add timed scheduling, and after that the sky's the limit.

Friday, November 4, 2011

Irrduino Project Open Sourced!

As of today, I have found a co-conspirator in my remote control irrigation project, which I have christened, Irrduino. (irrigation + Arduino = Irrduino! Get it?)

Due to this 100% expansion in support staff for this project, I have moved my code out onto code.google.com so my new colleague can help me extend it:


http://code.google.com/p/irrduino/


This code is probably not useful to anyone except me, and possibly other folks who are already working on using Arduino to control their sprinkers (of which there are a few), but it is exciting (and a little scary) to put it out there in the world.

Friday, September 23, 2011

Calculating Dates with Java Calendar

Found a tricky problem with Java Calendars today. Essentially, I discovered that you can't reuse Calendar objects in a calling function, because they are singletons. Take this code, for example:

How NOT to do it

// give me the date X days from the day represented by cal
public static String getOffsetDate(Calendar cal, int daysOffset){
    cal.add(Calendar.DATE, daysOffset);
    return dateFormat.format(cal.getTime());
}

This function appears to work until you call it a second and third time, and find out (like I did) that the new calendar value is being retained each time, and so increasing the daysOffset incrementally results in dates that are additively further out:

Today :2011-01-15
1 days ago     : 2011-01-14
2 days ago     : 2011-01-12 
3 days ago     : 2011-01-09
4 days ago     : 2011-01-05
5 days ago     : 2010-12-31 // wait. what?!

Apparently the Calendar.getInstance() gives you a singleton. Try passing it around to other methods, expecting it to make a new instance of itself and you'll run into problems. I found this to be extremely annoying and non-intuitive, and the Java Doc does not warn you about this, either.

Solution

So what's the solution? You have to create a new instance, or clone() the instance of the calendar before making the calculation (see sample code below).

package com.test.calendar;

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class CalendarTestDaysAgo {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance(); // today
        
        // set to January 15
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DAY_OF_MONTH, 15);
        
        System.out.print("Today :"+getOffsetDate(cal,0) + "\n");
        for (int d = 1; d < 32; d++){
            System.out.print(d + " days ago: " + getOffsetDate(cal, d * -1) + "\n");
        }
    }

    // give me the date X days hence from the day represented by cal
    public static String getOffsetDate(Calendar cal, int daysOffset){
                                          // this clone() call is required
                                          // otherwise subsequent changes are additive 
        Calendar newCal = (Calendar) cal.clone();
  
        newCal.add(Calendar.DATE, daysOffset);
        return dateFormat.format(newCal.getTime());
    }

}
Results in:
Today :2011-01-15
1 days ago     : 2011-01-14
2 days ago     : 2011-01-13
3 days ago     : 2011-01-12
4 days ago     : 2011-01-11
5 days ago     : 2011-01-10 // that's better.
...

Tuesday, September 20, 2011

Arduino Remote Control Irrigation Rig - Prototype 2

Last night I finished Prototype 2 of my Arduino irrigation remote control rig. Added the screw terminal headers so I can connect the irrigation control wires. The very last screw terminal on the right with the white wire is my power bus. It's wired into the COM terminals of all the relay boards.



For those of you who may be wondering, this iteration is mounted on an old IKEA cutting board. I needed the extra physical strength, because the 18 gauge wire used for the irrigation wires is stiff and heavy.

I drilled holes in the cutting board that are just big enough for 4-40 machine screws to poke through (7/32 drill bit, I think). The relay boards have long pins on the bottom, so they need be elevated off the board. I found some 1-inch spacer nuts at Fry's, and that's what the relay boards are mounted on top of. It worked so well, I will be doing the same for the Arduino ADK and Ethernet Shield.

Next step: Wire it up to my irrigation control box and try real hard not the burn the house down. The real trick will be to tap into my irrigation controller's 24-volt power supply without disabling the controller. Fun times!

Saturday, August 27, 2011

It Works! Remote Controlled Irrigation via Arduino

Success! I can now remotely turn on my sprinkler zones via my Arduino-powered web server.

The picture does not do justice to the amazing amount of wiring nuts I used to make this work. I think there are nearly a dozen of them holding all the wires together.



I did not manage to hook the Toro controller's 24-volt power supply into my rig. Sharp-eyed readers might be able to spot the two 9V batteries I clipped into my valve control circuits as a temporary power supply.

Anyway, it works! Awesome! Now to write the native Android controller app...

Edit: I have since torn down this setup so that I can mount my Arduino hardware on something a little more substantial (and less flammable) than cardboard. Stay tuned...

Friday, August 19, 2011

Google Authorship with Blogger

In the last couple of weeks, I have taken an interest in Google's attempt to register authorship for articles published on the web. This initiative allows web authors to essentially claim ownership of a particular piece of content that they publish.

I think this a great way to recognize folks who are serious about the content they publish on the web and a way to help folks looking for good content to find it faster. I'm all in for that. Now, how to get it working?

Caution: This process is a bit fiddly using Blogger, which is ironic 'cause it's a Google web property, right? I have sent some feedback to the Googlers who will hopefully make this easier in the future. If you are not comfortable editing raw html, I recommend you wait until the "register my authorship" option (or whatever they call it) is implemented in Blogger. Also, the solution is not suitable for a multiple-author blog. Fair warning. If you manage to get it working in that scenario, please leave a comment as to how you accomplished it.

How to Plug into Authorship with Blogger

There are a few steps you need to complete to get authorship set up:
  1. Setup a Google Profile (you don't have to be on Google+ to do this). If you are on Blogger, you probably already have one.
  2. Add your Blogger site to your Links list. Make sure you:
    • Click the This page is specifically about me option.
    • Set the visibility of the Links list to Anyone on the web.
  3. For each page of your blog, make sure there is a link to your Google Profile, and make sure the anchor text starts or ends with "+". (See specific instructions for Blogger in the next section.)
  4. Test your implementation using this page.
  5. Fill out this form for the Googlers.
  6. Wait.
  7. Wait.
  8. Wait some more.
  9. Obsessively run Google searches on your blog posts.
  10. Finally see your mug next to a search result, declare success and drink a celebratory beverage of your choice.

Add a Google+ Profile Link to Your Blogger Byline

Here's how I changed my byline to include a link to my Google+ profile. You have to manually edit your Blogger template to do this.
  1. Log into Blogger
  2. Go to your blog dashboard and click Design > Edit HTML)
  3. In the Edit HTML page, go down to the Edit Template section and make sure you click on the Expand Widget Templates option on the top right of the edit box.
  4. In the edit box, find the section containing a div with class='post-footer-line post-footer-line-1'
  5. Wrap the <data:post.author/> tag with an "a" tag containing a url to your Google Profile, followed by "?rel=author":
    ...
        <div class='post-footer'>
        <div class='post-footer-line post-footer-line-1'><span class='post-author vcard'>
            <b:if cond='data:top.showAuthor'>
              <data:top.authorLabel/>
              <span class='fn'>
                <a href='https://plus.google.com/103507786235300238642?rel=author'>
                +<data:post.author/></a>
              </span>
            </b:if>
          </span> <span class='post-timestamp'>
          ...
    
  6. Also, you need to put a "+" at the beginning or end of the anchor text for Google to accept this as a valid author reference. (No, that "+" is not a typo; It's required.)

Props to the Kevin & Amanda blog for providing the blogger signature template tips that lead to this solution.

Further Thoughts

As a writer, I think this a great initiative for content producers to get credit for their contributions to the sea of knowledge that is the interweb. I think it also has the potential to help folks looking for information to sort out the real sources of information from the increasing numbers of republishers, SEO hackers and link farmers out there.

If that describes you, then hey, I realize we all need to make a living, but ask yourselves; are you actually contributing any new value to this great interweb thing we all share? If not, then maybe it's time to rethink your strategy.

Wednesday, August 10, 2011

Arduino Remote Control Irrigation Rig Update

Last night I tried hooking up my Arduino irrigation remote control rig to all three of the SeeedStudios Relay Shield I bought a while ago. Now here's a nice hack:



I took a piece of cardboard and some unused 1/8 inch rivets, poked the non-rivet end into the cardboard and set the Relay Shield on top of them using the mounting holes. Not a good long term solution, obviously, but it kept the boards from sliding a round while I was wiring everything up.

This project is going to need a much more solid base because the wires for the irrigation system are pretty heavy. I'm thinking about getting a nice, thick sheet of clear acrylic for mounting. I will also have to go find a screw terminal block and use that in between the relay boards and the irrigation wire. Fun! And, I also need to figure out how to get an ethernet connection into my garage where the current irrigation controller lives. Heh.

Arduino Pin Use Limitations: Pin 10, 13

I have a total of 12 relays I can control with the Relay Shields, and I was hoping to use pins 2 to 13 for that purpose. Well, trying that didn't go so well. Apparently the Arduino Ethernet Shield lays claim to pin 10 and so I cannot use it for output. Also, pin 13 (which is connected to the ADK board's LED) gets flashed a lot during program uploads. So, if I connect one of my relays to pin 13, it gets opened and closed dozens of times a second while I'm uploading a new Arduino program. That's going to cause unwanted wear and tear on the relay and possibly overheat it as I noticed when connecting the relays to pin 0 and 1.

So now I'm down to using only 10 relays of my 12. That's more than enough for my project, and if I really need them the ADK lot's more digital outputs. I was hoping to be able to control twelve relays with just the pins available on a Arduino Uno though. Maybe I can use the analog pins to control the relays?