Lightning strikes. It struck near me, and fried a component of my old X10 home-control system.
X10 is a power-line-based communications network. Data is sent (slowly) over the house power lines by injecting a 120 kHz signal into the 60 Hz AC signal just after the zero-crossing of that signal. One bit per cycle is sent by either adding or withholding a short pulse of the 120 kHz.
X10 devices are either plugged or wired into the house power lines. Each device has an address, not necessarily unique, which consists of a house code A-P and a unit code 1-16. The original design intent was to have each house in a neighborhood choose a unique house code, to prevent signals from the neighbors from controlling one’s own devices.
The data sent over the power lines corresponds to commands like “A03 AON”, which says to turn on any device with house code A and unit code 3.
I had been using a TW523 interface which provides:
- a logic-level zero-crossing synchronization signal
- a logic-level output which indicates when a 120 kHz carrier is present on the power line
- a logic-level input which causes the generation of the 120 kHz carrier.
It was controlled by an old Arduino which passed commands between the TW523 and a UDP socket using an Ethernet shield.
A Perl script on another computer provided the intelligence – receiving messages from the X10 system and an auxiliary RF control box, from my MQTT message broker, and from a Perl scheduler.
A recent thunderstorm provided my next-door neighbor some excitement when a bolt hit his chimney. It provide me with something to do, too…
It fried my TW523.
I subsequently found that the devices aren’t manufactured anymore. Fortunately, Jeff Volp produces a plug-compatible replacement, the XTB-523. I’m not yet using its extended capabilities, but am enjoying the higher reliability produced by its higher-power signals.
However, being a geek, I had to make other improvements to my system.
I didn’t like the power consumption of the old Arduino and its Ethernet shield – the Arduino’s voltage regulator was always quite hot, and I was afraid it would cook itself. I also didn’t like the solderless breadboard I had cobbled together 20 years ago as an electronics newbie – it was a mess.
So I grabbed a spare Adafruit Huzzah ESP8266 breakout board and went to work on the software. [ I will upload that to my Github account once I figure out why it’s telling me hundreds of my files have changed and I should do a pull but it won’t let me anyways and … wah, wah, wah ]
I also needed to create a better hardware setup – I wanted to plug the Huzzah into a board with its own voltage regulation, level shifting, and an RJ11 jack for the phone wire to connect it to the XTB-523. I entered the schematic into Eagle and laid out the components as if I were going to produce a PCB. I do this even when I’m going to hand-wire a circuit board, just to the point of laying out the components but not laying out the traces. I generally also create and record a color code for the wires, which will help me in future debugging.
This time around I also remembered to add some test points onto the board. I have a 4-pin header for the power (Vcc, 5V, 3.3V, and GND) and one for the 4 connections to the XTB-523.
After some major troubles with the software, I got it all to work. The main software trouble was a bug in the X10 library. I was getting an ESP8266 fatal exception when I enabled receiving. As I tried to create bread crumbs ( Serial.print statements ) and follow them back, I found that the problem arose in an object method that was called from an interrupt service routine (ISR). Now, it’s a really bad idea to do anything in an ISR that takes any significant time at all, because other interrupts want to be serviced, too, and they can’t while one ISR is in control. Print statements take a really long time ( from the perspective of a computer ), so trying to put them in confounded my search for enlightenment. Eventually I got frustrated enough to put some print statements outside the ISR and learned that the object’s .cpp file had to define an object pointer ( so the ISR could call an object method ), but that it wasn’t initialized to point to anything. When you try to dereference a null pointer, bad things happen. Once I found that, I was past the hump.
I almost said, “Once I found that, I was home free.” But I wasn’t. I still had (gasp!) bugs in my own code. They were, however, readily found and fixed.
Now everything works. <contented smile>