LED bike light
Last summer I took up bicycle commuting. Besides the exercise benefits, it's fun, and a welcome relief from the stress of driving. (See Does Anyone in Seattle Know How to Drive?) As the days became shorter, I knew I needed a front light, and like any self-respecting EE, I was sure I could build one as least as good as the big-name brands. Here were my design parameters:
3.7-volt lithium-ion battery power, not a hub dynamo. Pedal power has a certain appeal, and it would be fun to play with max-power-point tracking (MPPT) on a dynamo, but IMO this is outweighed by the weight savings and freedom from drag offered by battery power.
Cree XM-L emitter, for the highest lumens per watt of a single-LED solution.
High-efficiency buck converter (switching power supply), to maximize battery life. Linear current regulators, used by many DIYers, are far simpler, but throw away 10-20% of the available power.
AVR microcontroller based, making it easy to experiment with different flash patterns, user interfaces, and battery management.
Intelligent (or at least different) lens design, as the narrow-beam spot pattern of most commercial offerings is not ideal for city riding.
I wasn't sure where to find hobbyist-friendly Li-ion batteries, so I purchased one intended for radio-control planes, assuming this would be the lightest possible solution. Actually, these batteries are optimized for large peak currents (not needed for a bike light), and, because a battery fire is preferable to a crash of your RC aircraft, they are supplied without the “protection PCB” normally used to limit current and protect cells from over-discharge. Oops. I recommend a battery pack with the protection circuit built-in. Use a 3.7V pack, as packs with cells in series are more difficult to charge correctly.
My battery started life as a 7.4V 2200mAH pack, which I rewired as 3.7V 4400mAH by connecting the two cells in parallel instead of series--another move I would not recommend, because of the potential for cells to explode in your face if you accidentally switch wires. I also added an off-the-shelf protection circuit and wrapped the whole thing in weatherstripping foam for cushioning. This fit snugly into a LowePro neoprene camera pouch, which I mounted to my bicycle's head tube with Velcro and zipties. I used an EC2 connector from the RC hobby world to connect the battery to the light. Definitely choose a polarized connector for this job, and one that can comfortably handle a few amps.
I am using a Li-ion charger from Adafruit Industries. (They also sell battery packs with the protection circuitry included.) Charging current is quite low, which I don't mind, as it probably increases the safety margin. Even so, I only charge when I am in the house and awake.
Power LEDs like the Cree XM-L are quite efficient, but they still dissipate an astonishing amount of power through a very small die surface. For this reason, they must be soldered to special metal-core PCBs, which are then bonded to the heat sink with a good thermal paste or epoxy. You can find many good ideas for thermal management in the Candlepower Forums, which has a forum dedicated to DIY bike lights.
Most people will buy an LED pre-mounted to a metal-core PCB “star,” which is what I did. You get to choose color temperature, spectral bin, and efficiency grade. The MCPCB must then be mated to a good heat sink.
Based on the beam shots provided here, I decided to use the Ledil CRS oval optic. While not designed for the XM-L emitter, it gives a decent horizontal beam spread with limited vertical extent. I can aim this low enough to give a comfortable view of the road without blinding far-away oncoming traffic. I have no scientific proof that this is better than a round spotlight, but I like it. Note: The lens needs a little trimming with a dremel tool to fit cleanly over the XM-L emitter.
Wikipedia has a nice article on buck converters, a standard topology for step-down switching power supplies. I chose the LM21212-2, a synchronous buck converter with built-in switches from National Semiconductor (now Texas Instruments), for the following reasons:
Synchronous switching eliminates the catch diode and the loss caused by its forward voltage drop. With a chunky inductor and a low switching frequency (300 kHz), the efficiency can approach 98%!
The TSSOP-20 package is easier to solder than smaller QFN-packaged devices. (Soldering the ground pad on the underside is still tricky though.)
The "SS/TRK" input can be used to drive the voltage feedback reference to tens of millivolts, instead of the usual 0.6V. More on this below.
Any voltage regulator with an adjustable output requires an external feedback network, typically a resistive divider that outputs a special “feedback voltage” to the regulator's internal error amplifier (FB, pin 19) when the regulated voltage is at its set point. (Oftentimes this network also provides “loop compensation”—a frequency-dependent gain and phase shift to prevent undesired oscillations of the voltage control loop.)
Power LEDs require constant current control. One obvious way to achieve this is with a sense resistor (R10) between the LED cathode and ground; the resistor value is chosen to produce the correct feedback voltage at the desired LED current. The problem with this approach is that it wastes a lot of power: The LM21212-2 feedback voltage is a typical 0.6V; at an LED current of 2A, R10 would have to be 0.3Ω and the I2R loss would be more than a watt!
Fortunately, many switching regulators (like the LM21212) offer a pin called SS/TRK (pin 2) or its equivalent, which stands for “soft start and tracking.” When it is less than 0.6V, the voltage on this pin overrides the internal feedback reference voltage. The intended use case is a capacitor to ground; the pin is designed to source about two microamps, which, as it charges the capacitor, causes the regulator's output voltage to ramp up gradually at power on. The bike light circuit uses a PWM DAC in the AVR microcontroller to drive SS/TRK to an adjustable, but very low, voltage (tens of millivolts). This both permits a tiny sense resistor of 0.02Ω, and provides brightness control from the microcontroller. Spiffy!
Note that this approach might not be suitable for a mass-produced circuit, because the error amplifier inside the LM21212 has a small offset voltage which can vary from part to part by up to 20 mV. For a one-off hobby design this isn't a big problem, because we can calibrate the current regulation by trial and error with different PWM values in our code. Even so, it's not possible to turn the LED all the way off with SS/TRK; we use the separate EN (enable, pin 3) digital input for that.
The LM21212 requires an external compensation network (C3 and R9). I am using a dominant pole loop compensation, sometimes known as “type 1.” (I found this app note helpful.) This basically says “I don't care if the regulator is a bit slow in response to transient changes in the load; I just want it stable.”
Coilcraft has a nice selection of very-low-series-resistance power inductors, using a sort of disc-shaped wire. The SER2915L-103 that I used is probably overkill, with a series resistance of 1.5mΩ and weighing about as much as the rest of the circuit and emitter assembly combined. It should be possible to substitute a smaller inductor of the same value, at the cost of slightly reduced efficiency, as long as it can handle several amps.
The rest of the switching-regulator components and layout follow the guidelines in the data sheet.
The ATtiny24A microcontroller uses two momentary switches for input. The firmware distinguishes between short and long presses. A short press of button one cycles through the pre-programmed blink (or steady) patterns. A short press of button two interrupts whatever pattern is in progress and immediately performs a special “emergency” blink pattern. Long presses of either button turn off the light and put the circuit to sleep. (Another long press wakes up.)
The status LED (D1) is not really necessary, but handy for debugging. It's blue because when the port pin is low, at rated current its voltage will rise high enough that a series resistor is (barely) not necessary.
OC0A (pin 5) is an 8-bit PWM output used as a DAC to control the LM21212 feedback reference voltage, and thus the output brightness. R3, R6, and C1 are compromise choices that trade off (a) smoothing of the PWM waveform, (b) a reasonable voltage range on the SS/TRK pin, and (c) minimizing the voltage offset caused by the two-microamp current source inside SS/TRK. As there are several unknowns here (component variation, LM21212 input offset voltage, etc.), use caution when integrating the parts and powering up the emitter for the first time; start dim! Also keep in mind that the safe limit for emitter current is lower in your workshop than on the bike, as the air blowing past the heat sink helps considerably when moving.
ADC2 (pin 11) provides an independent monitor of the voltage on the current-sense resistor R10. This is presently unused. ADC3 (pin 10) is used, to monitor the battery voltage and warn the user when it is dangerously low, by flashing the main emitter with the “emergency pattern.” It does this every 60 seconds as long as the low-battery condition persists. (Li-ion voltage vs discharge curves depend quite strongly on temperature as well as discharge current relative to battery capacity, so it would be wise to re-evaluate the threshold voltage for your particular circumstances.)
I used a standard six-pin programming header (J1) on my board out of habit. Now that standard parallel and serial ports are becoming rare, I've switched my AVR programming device to a USB-connected Bus Pirate with micro-clip leads. A much better board layout would thus leave the six programming contacts as a single row of plated holes, very close to the board edge.
I haven't measured the efficiency exactly, but none of the components are more than slightly warm to the touch, and everything works fine. It's a lot of fun riding with a custom-designed light, where I can go back to the C code and tweak the behavior at will.
- gEDA design (gschem schematic and pcb layout): bikelight_hardware.tar.gz
- AVR Eclipse C project: bikelight_code.tar.gz
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.