Arduino-Based Curtain Automation

I built a controller so that I can open and close my curtains from the command line!

My apartment has a 16' wide floor-to-ceiling window, and a correspondingly-huge curtain. I wanted to put the curtain under software control so I could do things like, for example, have it automatically open in the morning to help me get out of bed.

Cut to the chase.

Photos! And a welcome excuse to use my macro lens:

First, I bought an Add-a-Motor Model 80 Drapery and Blind Controller, as a starting point. It looked like this would do most of what I wanted: open and close the curtains by pulling on the rope. All that was left was a small matter of hooking up ethernet to its toggle button, right?

Well, it wasn't that simple. The way you trigger this device to open or close the curtain is by turning the power off and then back on again -- but the power has to be off for more than a second to have an effect. Not quite as simple as simulating a momentary switch. (It's not a stand-alone device, it expects to be used as an end-component of some other complicated automation system that I'm not interested in.)

Here's the part where I think, "How hard could this be?"

So, I enlisted my friend John's help, since he's done more hardware nonsense than I have. First we tried to figure out if we could get rid of that one second delay. We did this by tracking down the patent ((US4958112) and trying to make sense of it, which was difficult, but apparently they were using some kind of crazy relays that had state in them, and implemented some halfassed digital logic using a tiny analog circuit. Or something. Anyway, at that point we decided to ditch the controller's board and just drive the motor directly on our own. Still, that saved us from having to build the gearbox from scratch.

Step one! Buy an Arduino Ethernet, a couple of relays, and wire up something that will let us turn power on and off, and switch the polarity of the motor.

While waiting for that to arrive, I whipped up some code to run the thing: it listens for connections on an Ethernet port, and reacts to commands like OPEN, CLOSE and TOGGLE by turning on and off various digital pins, which then drive the relays.

I also had it react to a push-button on the side of the device that does the same thing as the TOGGLE command, since there will surely be times when I want to open or close the curtains without using the computer to do it.

The code is pretty straightforward, but if you're writing your own command-line-driven server for an Arduino Ethernet, this might be a good starting point.

Arduino source: curtain.ino

And here's a Perl script for talking to that server from the command-line, so you can type things like "curtain open":

Cmdline interface:

Finally the parts arrived, and we started building it.

Needless to say, that went poorly.

Here's the part where I remember why I rarely do hardware crap.

As we iterated on the design and ran into problems we hadn't anticipated, it turned out to be a a much more complicated circuit than we expected. We spent a week or two on it, off and on, working on a design and then realizing that we needed more components that we didn't have. More ordering, more days go by waiting. Then at some some point while trying to debug it, John accidentally touched the multimeter's leads to something he shouldn't have, and suddenly my keyboard didn't work any more. Yup, we fried my USB hub, at 3am.

So the next day I bought a new hub, and discovered that I still couldn't talk to the Arduino. Maybe we also fried the FTDI cable. Time to order another one. Days pass.

Nope, that didn't help. I guess we fried the Arduino too. Great. At this point, I was so frustrated that I tossed it all in a box and said, "Fuck it, I don't care enough."

This is why I hate dealing with hardware: since there's no "undo" and no backups, you end up frying things all the time, and then it's just gone. So something that seems like it should be a simple hack made mostly of a handful of $1 components turns into a huge and expensive clown-car mess unless you already have a fully stocked workshop. People who tell you how easy this crap is are invariably people who already have a drawer full of every resistor, capacitor and relay known to man, instead of having to spend days waiting for the turnaround on ordering the components they need. So yeah, projects like this probably are simple and only a couple of bucks if you've already spent twenty grand building out your electronics workshop!

Hardware hacking is extremely hostile to the casual beginner. Without spending a small fortune up front, you never have the right components or tools, and without the right tools, everything is ten times harder than it should be.

Give me the iterative simplicity and low barrier to entry of software any day over this nonsense. Also, software rarely makes you bleed. Very rarely.

Another part of my frustration was that, at the time, there was no way to do DHCP on the Arduino Ethernet. That's right, to get the thing actually on the net, you were expected to hardcode an IP address into your source code. Need to change the IP address? Edit the source code, recompile, and re-upload it via the FTDI cable.

I mean, DHCP is only twenty years old, so let's not jump the gun here or anything!

I was so offended by the halfassery inherent in shipping something that calls itself an "Ethernet" board that doesn't do DHCP that I wanted to throw it away on that basis alone.

Here's the part where I can't leave it alone.

Months went by, and finally I got over my anger and frustration enough to think it was a good idea to try again. This time, we discovered the Seeed Relay Shield! This is fantastic, because it's pretty much the exact board we were trying to build ourselves, except higher quality, and built by someone who knew what they were doing.

So I ordered one of those, and threw away all of the work we had done so far.

After quite a bit more futzing around, I managed to get it wired up properly. this took some time, since no Arduino shields fit correctly on top of an Arduino Ethernet (the ethernet jack makes the board taller than they expect), and I didn't have (and didn't want to wait around for shipping on) pin extensions. A lot of the problems I was trying to debug were because it looked like it was seated right but it wasn't.

Zip ties. Second only to duct tape in holding the universe together.

Finally, the plan comes together.

The wiring diagram for the relays is this:


+ V

+ V


Relays 1 and 2 control the polarity of the voltage sent to the motor, by being wired to power oppositely. Relays 3 and 4 control whether the motor is connected to power at all. They operate in pairs: it's important that the on/off state of 1 and 2 always be the same, and that 3 and 4 always be the same.

As a pleasant surprise, in the intervening months between when I gave up and then un-gave-up, they finally added DHCP to the Arduino Ethernet library, so I got to stop hating on them for that. You still have to hardcode the MAC address into the source code, though, which is just idiotic. Instead of the MAC being burned into the hardware, the board has a sticker on it with the address printed on it, and you have to type those numbers into the source. So if you or someone else wants to use this same source code on a different device, you have to edit the source first.

This, my friends, is some grade-fucking-A brain damage.

Anyway, it works now.

Would you like to come up and see my automata?

At this point there's a fair amount of home-brewed automation in my apartment. My receiver (a Denon AVR-2805) has a serial port on the back, so years ago, I stuck a Lantronix UDS-10 serial-to-ethernet adapter on it and wrote a Perl script to speak the AVR/AVC control protocol. This means I can change the volume and input sources from the computer without getting out of my chair: sweet! (Some people might have used an IR remote control for this. How pedestrian.)

It also turns out that my video projector (a Panasonic PT-D5500U) has a web server in it, which lets you power it on and off from the web. Sweet.

So, combine the two of these with a properly-configured Griffin PowerMate, and I've got a big button sitting on my desk that adjusts the volume when I turn it, and toggles the projector on and off when I smack it. Turning the projector on also pauses iTunes and switches to the proper input on the tuner; and turning it off does the reverse.

This is especially handy for those times when I fall asleep watching TV, because when I wake up and stumble toward the bedroom, I can hit the big button to turn off the projector without having to wake up enough to focus my eyes on a remote!

Now that the curtain automation works, turning on the projector also closes the curtains -- and, I have a cron job that opens the curtains in the morning to remind me that daylight exists.

© 2012 Jamie Zawinski <>