The job of this part is to gather information about the user's desires, and communicate them to the other end. We decided to build a circuit board that had eight buttons, since that's the size of a data byte, and give it a simple interface. Everything else is just there to support those buttons. We also wanted to make the battery last as long as possible, so we attempted to chose parts that use little quiescent current, and minimize the current draw while active. We also wanted to make the boards easy to build, so we attempted to minimize components when possible. For example, using the internal pull up resistors in the MCU.
We started out with an ATMega16L, because it was cheaper than the Mega32. We didn't really need the extra memory of the 32, and using an L part meant we could run at a lower Vcc. It also forced us down to 8MHz, but that's fine -- it uses less power and we don't need the extra cycles. We have the buttons hooked up to PortC, so we can read them in a single operation.
We added an 74HCT30 NAND gate, to generate an edge triggered interrupt whenever a button is pushed. Because the buttons are active low, the NAND normally has 8 high inputs, and outputs low. Whenever a button is pressed, one input goes to zero, and the microcontroller sees a rising edge on INT2. This serves to wake up the microcontroller from power down sleep. In that mode, it uses a few microamps, but takes a while to wake up. Basically, all clocks are halted and only external interrupts can wake it up. This wasn't necessary for basic operation, but dramatically increases battery life. We chose the HCT family because it is level compatible with our circuitry, and consumes a few microamps as well. CMOS technology has less leakage current than bipolar or schottky families, and thus is better for us. We hooked an LED up to the output, to verify that the gate was operating. This was in case we pushed a button and nothing happened -- we'd know if the NAND was busted, or if there were a more serious MCU issue.
Initially, we were using an LM340 voltage regulator to drop the 9V from the battery down to 5V for all the CMOS circuitry. It can handle a lot of current, and is rather robust. It is simple to use, and doesn't require much external circuitry (capacitors on input and output, if you choose). However, it has 5mA of quiescent current, which will deplete our battery in less than a week, even if the microcontroller is in power down sleep. We ordered better parts from Analog Devices, but they didn't arrive by the time of the demonstration. We did put it on afterwards though, because then the battery will last for nearly a year. We also tried to build a simple one ourselves from a Zener diode, bipolar transistor, and resistor, but decided it wasn't worth the effort after playing around with it on a breadboard.
To determine the battery level, we use a large resistive voltage divider between the 9V terminal of the battery and ground. It consists of a 1MΩ resistor and 330kΩ resistor. The output is hooked to an analog input, and is compared to the internal bandgap voltage reference. That reference is very constant, barely changing over wide ranges of temperature and Vcc. The output is 0.24182 times the input, for a max of 2.109V when the battery is at 9V. This is well below the 2.60V reference, just in case the battery starts out at 9.5V or something. When the battery is nearly completely depleted, at 7V, the output is 1.7368V. The battery status is indicated by two LEDs -- a yellow one for almost dead, and a red one for dead. The divider uses 6.7 µA, and will basically function as long as the battery has enough juice to wake up the MCU.
Another way we save power is by physically disconnecting the power from the voltage regulator when not in use. We put a jumper on the input wire of the battery, which allows easy access. In addition, it allows us to measure supply current rather simply. We remove the jumper and hook an ammeter between the pins.
The transmitter itself is a very small surface mount component, which is designed for handheld battery powered applications. It has no error correction, and uses OOK modulation to transmit the data. A 0 is the lack of carrier signal, while a 1 is the presence of it. This causes some software headaches, but is good for power - when it's "transmitting" a 0, it's using about 100µA. We were considering powering it from an op-amp, which we could turn off with a port pin, to eliminate that power also. But we decided that this power pinching was getting excessive.
We tried lots of ways to increase the range of the RF transmission, since it was not very good to begin with. One thing that helped was running the transmitter at 9V (or whatever the battery was putting out). Running at a higher voltage puts more power into the transmission, which increases the range. However, the input of the transmitter needed to go up to 9V as well. To that end, we used an LMC7111 op-amp with 20kΩ resistors to create a gain of 2. The UART signal would rail out, and we'd get our 9V. However, the 7111 has a very low slew rate, and the signal coming out was not a square wave by any stretch of the imagination. We considered using a Schmitt trigger buffer to clean it up, but couldn't find one in the lab that would operate up to 9V. Luckily, the transmitter seemed to work alright at 1200bps without it. Other op-amps used more quiescent current to get better amplification, and not all were rail-to-rail. The 7111 was easily available and good enough. We tried various antenna designs, straight wires of varying lengths, helical wires, with and without ground planes, etc. The best result was hooking up an alligator clip and wire to the existing antenna and forming a circle with it, and then touching an exposed part to use our body as a tuned element. Needless to say we gave up and just used a 17cm (1/4 wavelength) straight wire, like was recommended.
This part is twofold -- it consists of the circuit board with the MCU and RF receiver, as well as the relays inside the outlet strip housing. They're connected with Cat5 twisted cable, each wire pair consisting of a signal wire, and a ground wire. This minimizes crosstalk and signal losses. However, our signal isn't high enough frequency or traveling over long enough distances for this to matter.
Within the housing, we hooked up four Omron G3MB-202P relays to control each outlet individually. All the neutral wires were hooked together, and the hot wires individually went to the relays. The relays were in turn hooked up to the 15A circuit breaker, which then connected to the outside world. We selected those relays due to a few factors. First off, they're really small. They are solid state devices, with no mechanical parts to break. Their housings act as heat sinks, and we push them against the metal housing as an even bigger heat sink. They can handle up to 2A at 240VAC, which is plenty for most home lighting applications. They have an internal input resistor, so they can be hooked directly to the MCU port pins. In addition, they have zero-cross circuitry, which prevents them from switching when the AC signal is not at zero. Because of this, we don't have to worry about inductive spikes from cutting the power at the wrong time. We tried to get samples of them, since they were relatively expensive in small quantities, but did not have any luck with that.
We attempted to put a small 5V switching power supply also within the housing, since we'll need the power for the circuitry outside the box. It worked well for about 30 seconds, and then blew itself up. We're still not quite sure how it happened, but decided to just wire up a connector, and have the actual power supply outside the box. That way, if we blow another one up (which we hoped we wouldn't), the box could remain closed.
To connect the outlets to the microcontroller board, we soldered the Cat5 cable to a pin header, and hot-glued it to prevent it from breaking. We keyed the connector so it could only be inserted one way. Basically, we filled in one of the pin holes, and removed that pin from the header. It was important to do that, since reversing the polarity on the relays for even a moment can destroy them. It would be very bad if our project would cook itself from inadvertently inserting the connector backwards.
The board itself consists of a few components. First off, there's a full wave bridge rectifier from the input of the power supply before the voltage regulator. This will allow us to use various power supplies with our circuit -- it won't matter if the center is (+) or (-) polarity. We use the same Mega16L chip as in the transmitter, for code consistency and price. We also have an array of LEDs to mirror the state of the relays. They are powered from the upper half of PortC, the same port the relays are controlled from. This made the software simpler to write. We were considering running them off the same pin as the relay, but weren't sure if putting the resistance to power or ground would affect the relay. We tested it briefly, and it still worked, but weren't sure if it was detrimental to the life of the device.
Finally, there's the receiver itself. This was a
prefabricated component, designed to work together with the transmitter.
It has auto-gain control, which will turn random noise into a signal if the
transmitter hasn't sent data in about 5-10 seconds. One problem we noticed
was that the rising edge of the signal was delayed from the transmitter to the
receiver by a significant amount. We considered using a retriggerable
one-shot to fix the pulse width ourselves, but decided that the hardware wasn't
worth the effort. Instead, we slowed down the baud rate of the transmitter
to 1200bps, so the receiver's level detection would have a better chance of
sampling the correct part of the waveform. We have an LED to indicate
successful data reception, which only comes on if the complete data packet
arrives without errors.