Make: Projects
X10 Macro Module
One of the most powerful additions to an X10 system is macro capability, where a computer continuously monitors the powerline for trigger signals, and responds by executing a timed sequence of additional X10 commands.
As a home automation buff, I’ve used X10 powerline control products for over 30 years. And although the technology has some shortcomings, I still believe X10 is the cheapest and fastest way to automate a home.
One of the most powerful additions to an X10 system is macro capability, where a computer continuously monitors the powerline for trigger signals, and responds by executing a timed sequence of additional X10 commands. This capability can be implemented with canned automation software as offered by X10.com and others, but often only with serious limitations. These macros are usually developed with a graphical user interface that limits construction, nesting and conditional logic, and the capability often only works if a resident pc is on and running the software. X10’s Activehome code will download to a CM11a or CM15a interface for stand-alone macro operation, but I’ve found these interfaces to be unreliable and prone to frequent lock-ups.
This project uses the X10 powerline carrier home automation protocol, developed in the late 1970’s by Pico Electronics for British Sound Recording (BSR), and subsequently marketed through a Pico/BSR partnership known as X10 Ltd. With this technology, automation commands are transmitted and received using existing house wiring, so that appliances can be turned on and off and lamps can be dimmed or brightened remotely, with no need for dedicated control wires. X10 commands are injected onto the powerline in a binary format, where a binary 1 is represented by a 1ms burst of a 120KHz signal, and a binary 0 is the lack thereof.
Now because home power wiring is noisy, the signals are injected only at certain opportune times, to maximize signal integrity. Our homes are powered with alternating current, where the voltage polarity changes regularly from positive to negative with a sinusoidal frequency (in the USA) of 60 cycles per second, or 60 Hertz (Hz). Because of this sinusoidal polarity change, the voltage on our wiring actually crosses through zero volts 120 times each second. It is at these zero crossing moments that X10 bits are transmitted, as shown in Figure 2. To accommodate the 3-phase power in a typical house wiring system, each bit is actually transmitted 3 times, once for each phase.
Downloads
- Creatrope’s X10 send/receive library
- X10 Macro Module code zip file
Steps
Step #1: Wire the Arduino to the phone jack.
Next



- Begin creating the wiring arrangement by connecting the Arduino board to the phone jack receptacle.
- Remove the cover from the receptacle, and you’ll see four (4) color coded screw terminals. Attach a 3” length of 20-gauge wire to each of these.
- Then attach the wire from the Yellow screw terminal to Arduino digital pin 2, inserting the free end of the wire into the digital pin header on top of the board. Connect the wire from the Red screw terminal to Arduino digital pin 4, from the Black terminal to Arduino digital pin 5, and from the Green screw terminal to the Arduino GND pin.
Conclusion
Maximize Your Macros
Extending your use of macros is easy. First, realize that if you copy the Appendix A example into the Arduino IDE and use it as a template, you need only change that portion of code following the conditional phrase
if (SX10.received()){.
Parse the received X10 data using the library functions SX10.houseCode(), SX10.unitCode() and SX10.cmdCode(). In the example of Figure 24, we search for X10 trigger “A1 ON” like this:
if (SX10.houseCode() =='A')
if (SX10.unitCode() == 1)
if (SX10.cmndCode() == ON)
If the parsing functions return a desired macro trigger address, we take further actions in the form of commands or delays. To send X10 commands, use the function SX10.write(). The write function must be invoked twice for every command, with the first call defining the X10 house and unit code, and the 2nd defining the X10 action. So to send an “ON” command to a module with address B1, we use the following:
SX10.write(HOUSE_B, UNIT_1, RPT_SEND);
SX10.write(HOUSE_B, ON, RPT_SEND);
Note that calls to this function must end with a semicolon.
Finally, invoke wait periods using the function delay(time), where time is an integer number of milliseconds. To program a 5 minute wait (which is 30000 milliseconds) we use the following:
delay(30000);
Again, don’t forget the semicolon.
That’s about it. With a little creativity, you can do some amazing things around the house. Place a motion detector in your mailbox, and have it turn on a light and sound a chime whenever the box is opened. Add a contact sensor and an X10 PowerFlash module to your garage door, to sound a chime if the door is left open for 5 minutes or more. Put a motion detector in your teenager’s car, so that when they drive up and get out, the porch light comes on and interior lights illuminate a path to their room. Or to the refrigerator. The possibilities for automation are limited only by your imagination.
The macro example waits for a signal from the outdoor motion detector, and then responds by turning on a lamp, sounding a chime, and activating sprinklers. After 30 seconds, the sprinklers and the lamp are turned off.
Even if you are not a C++ programmer, you can easily understand the logic used in our example, and alter the macro code to suit your needs. For instance, you can have the macro module sniff the powerline for an indoor motion detector signal, and then turn on a series of lights that illuminate a path to the bathroom. This example is included in the macro code listing of Appendix A, to show how multiple macros can coexist in the same Arduino file.




































