You know, the Jews got 1 day's worth of oil to last 8 days. That's what I call engineering!
A very good friend of mine is Jewish, and I thought it would be fun to make her something for the holidays. I've had an idea for a while to make a birthday card that sings and lights up printed on a single PCB with the copper as the text as well as the circuit. Somehow, that idea evolved into this project, which is certainly cooler and more practical than a birthday card, and it actually called for some pretty cool design constraints.
- It had to look good. Something you might sit on your desk or even use as your ceremonial menorah if your living arrangements have a "no open fires" policy.
- It must use as few components as possible. This goal sort of evolved into me getting rid of the need for a power switch and interface button by using what I call "poor-man's cap sense". It didn't work super well, but more on that later.
- It must actually last eight days of operation. This would require some cool tricks to extend the battery life.
When laying this board out, I had to throw all PCB layout rules out the window. There are a lot of right-angle traces, but given how simple the application is, it's hardly a problem (still, don't get into the habit of using right-angle traces!).
The circuit is a single-layer PCB with the battery mounted on the back. The battery enclosure is actually a surface mount part, but by looping some wire through to the back of the board, I was able to provide enough "surface" to solder to. Note that there is no power switch. This means that I had to be careful while building the circuit to take the battery out before making any modifications.
I didn't want a programming header muddling up my design, so while I was working on the firmware, I made a temporary programming header and soldered it lightly to the relevant lines.
Power is provided by the copper plane surrounding the candles. This helps maintain the illusion that the candles have tips rather than being part of a circuit. Also, I soldered the current-limiting resistors on upside down because I think their white bottom looks more like a candle than their black tops.
The flickering was achieved using PWM with a random value lookup table. There are seven different brightness values (eight if you include "off" which I didn't), and each byte on the lookup table provides data for two LEDs at a time (I just threw away half of the 5th byte). By making my lookup table non divisible by 5 and looping it, I greatly extended the time it takes before the pattern repeats, simulating the flickering of a real candle.
Poor Man's Cap Sense
Some of you probably know a lot about capacitive touch sensing electronics. Everything from the classic iPod click wheel to the touch pad in your laptop use this technology. Capacitive touch sensing technology uses oscillators that charge and discharge a capacitor. When you touch or get near that capacitor, you alter its capacitance slightly and change the time it takes to charge or discharge. Measuring this frequency can determine whether or not you are touching the device.
Poor Man's Cap Sense does not do this at all. It does use a capacitor though!
I discovered PMCS while I was working on the LED sensor a while back. I noticed that often touching the LED had the same effect as shining a bright light at it. This is because the LED was at the time acting like a capacitor, and my finger was acting like a very high impedance resistor (but less high than air). By replacing the LED with a very very small capacitor, I was able to harness this effect and use it to my advantage.
Here's the basic rundown of how my implementation worked.
- Charge the capacitor using the micro controller.
- Disconnect the internal voltage rail from the output pin (i.e. turn it into a high-impedance input).
- Read the voltage on the capacitor pin and wait for it to drop (which would mean that a finger has shorted it to ground).
The only flaw with this plan is that the capacitor will discharge on its own given enough time. Usually within 5-10 seconds, the charge leaks out either through the air or through the not-quite-infinite impedance of the micro controller input pin. To cope with this, I treated it just like the LED sensor and timed how long it took to discharge. If it discharged quickly, that would mean that a finger was touching it. If it took something like 5 seconds, that means that it's discharging freely through air.
Now, my implementation was incredibly simple. I just had two thresholds (determined empirically) that set up a hysteresis for the time readings. Here's a graphic explaining it.
Every time the capacitor's voltage reaches the low input voltage for the micro controller (and it therefore reads the pin as being low), it takes a time measurement, charges the cap, and starts the timer again. This time measurement is compared against the threshold values (in green) to determine if anything needs to be done. If the measurement is below the lower threshold, it registers as a touch. The second measurement in this region is ignored. The values must first rise above the upper threshold before a second touch can be registered. This prevents the device from going nuts with repeated touches if you hold your finger down for an extended period of time (where "extended" = more than a few milliseconds).
Now, when this method works, it works beautifully (see video below). The only problem is that it doesn't work in all conditions. I found that there is a lot that can mess with the measurements and needs to be taken into account. If your fingers are particularly moist, they will leave a residue on the surface of the button that will provide a conduit for the charge and prevent the time measurements from rising above the upper threshold like they might in the presence of a better insulator. Also, after taking a shower, I noticed that the humidity in the room was enough to register a touch.
Long story short, if you plan on making this thing in any sort of serious application, be prepared to spend a lot of time coming up with a clever algorithm that has self-calibrating thresholds that can adapt to different conditions. I didn't post a video of my algorithm failing, but let's just say that the success rate is about 75%. I consider this acceptable mostly because it typically misses hits rather than registering false-positives. I expect the user to leave the menorah alone after it is set to the correct day, and I'd rather the user have to touch the pad a few extra times than having it skip ahead in the calendar when unprovoked.
Eight Days of Efficiency
Not having a power switch requires a few neat tricks if you want to make your battery last more than a few days. The cap sense actually helped me achieve this.
AVR micro controllers have a low-power shutdown mode that you can place them into wherein they draw a minimal amount of current (2 microamps) while still holding all of your values in ram. They also have a few options for how to wake them from this state. You can either have them wake on a timer interrupt (if you have an external oscillator) or on a pin change interrupt. I opted for the latter option and made sure to have my capacitor pin tied to INT0.
When my device is "off", it's actually sleeping until the capacitor discharges. As I said before, it will discharge in about 5 seconds or so when left alone. At this point, it wakes up, charges the cap, waits a few milliseconds for it to discharge, gives up, tops it off again, then goes back to sleep. The idea is that if the cap takes longer than a few milliseconds to discharge, it's probably not being touched, and the micro can better spend its time sleeping than waiting for the cap to discharge all the way.
This means that it's only operating at full power for a few ms out of every 5000 greatly extending the battery life.
As a last note, I did use fairly efficient LEDs (these are the same ones from the low battery indicator of the bullet counter), so I can afford to crank the LED current down pretty low. The current limiting resistors I used were 470 ohm. It also helps that it's meant to emulate candles, so the LEDs shouldn't be super bright.
All in all, I'm very satisfied with the final product. I probably spent way more time than I should have trying to think up a better algorithm for handling the cap-sense, but I had to give up due to time constraints (I'm not much of a CS guy anyway). I leave it as a challenge to the reader to come up with a cleverer solution. If I really needed it to work 100% of the time, I would just replace the cap sense with a cheap tactile switch. The code would barely even have to change.
I'll be packing this thing up soon and mailing it off. I hope she likes it! Happy Hanukkah everyone!
Edit: A reader pointed out to me that menorahs are supposed to be lit from right to left. Whoops... Good think I didn't mail it off yet!
Project files can be found here: Menorah package v1.0