The second of these goals is easily achieved with a few ultra-bright lights in the front of the bicycle, but the first goal (and realistically more important of the two) needs a little more help. To solve this problem a complete lighting system consisting of front, rear, and side lights was conceived. The overall style of the lights resembles that of a vintage cruiser motorcycle, sleek and appealing. The side lights will be more reminiscent of a big rig to enable someone viewing the bike perpendicularly to easily see it. Any other features can be added as the design is under way.
To control the lights, there are a variety of different types of switches to be used. Aside from the main power switch which will be a standard 12V rocker, two momentary-on push buttons are used for the dims and brights, a slide switch will turn the dash lights on or off, a push-on/push-off button is used for the hazards, and an on-off-on momentary toggle switch controls the left and right blinkers. For the brakes, a normally on, momentary-off switch is embedded into the plastic under each of the brake levers such that when the brakes are pulled, the buttons are depressed, closing the switches. When the brakes are released, the brake cable tension will pull the levers back against the buttons which opens the switches.
Another trick I have learned when working with large LED arrays is to use a sheet of craft foam to hold the LEDs as opposed to soldering them to a large and expensive board. The foam is usually one or two bucks for a square yard as opposed to five bucks for one perf-board. The only downside to doing this is that you have to manually poke each lead hole with a sharp pick. Trying to push the LEDs through without a guide hole will destroy the leads. Once they are in place, the leads can be twisted together and soldered on the reverse of the foam. As long as you don't need a lot of heat dissipation, this is an ideal material to use.
The 1st generation headlight was created pretty quickly and was not without flaws, but these were addressed in the next generation headlight which is currently used in the system. Deciding where and how to mount the lights posed yet another problem. My first thought was to fasten the headlight to the plastic piece holding the front reflector just above the fender. This would still allow a front basket or bag to be used on the handlebars, but the plastic piece could not support the weight of the headlight and didn't look right anyway. The headlight was remounted at the top of the front fork, just under the handlebar.
The taillight was a bit easier to deal with thanks to the book rack I installed over the rear fender. At the end of the rack is a removable plastic piece which must have been intended for a small license plate. I was able to drill two small holes into one of the metal headlamps and bolt this plastic piece to it. Then, the taillight was inserted back into the rear of the rack. The taillight housing was eventually painted black to match it's surroundings.
CycleLux Version 1
It's time to turn to microcontrollers. I chose the Atmel ATtiny25 MCU because I am familiar with AVR chips and because I had a few of this model laying around. Although this MCU does not have many I/O pins, more can be added by use of a data bus. This chip has a built in universal serial interface (USI) which can act as a few different types of buses. I chose to use the serial peripheral interface (SPI) bus to communicate with an MCP23S17 I/O expander from Microchip, again, primarily because I had a few of those chips laying around.
The result was a much cleaner circuit with a lot fewer parts and more control possibilities. The I/O expander reads in data from switches and drives the MOSFET gates to turn the LED strings on or off. For power, any regulator will do as long as it is within the voltage range of all of the chips. For the MOSFETs I was using, I needed a logic level of 5 volts.
CycleLux Version 3
Rather than try to get the USI module on the MCU working, I wrote a simple "bit bang" algorithm to communicate with the MCP23S17. In this code example, the CLEAR_XX and SET_XX macros, as well as the user defined pins DO (data out), DI (data in), and SCK (serial clock), are defined in a header file.
One major concern I had was switch bounce. If the switches "bounce" when being pressed, the MCU will think they are being pressed and depressed multiple times in a row and will set the output states to some random value. To remedy this, whenever the MCU recognizes that a switch has been pressed, it delays for so many milliseconds before checking the switch state again and deciding what to do.
The next challenge to overcome was creating the interrupt routines that flash the left, right, and side lights, but this was handled using simple counters and delays. The program would check the current state of each blinker output and simply toggle that state when the appropriate counter was up.
Finally, a routine to rapidly flash the brakes was added. This was a bit more complicated then the simple blinker flashing because the brakes will only flash a few times before remaining constantly on instead of continuously flashing. For this to work, a second counter was incremented with each flash of the brakes until a set number was reached. At that time, the brake flashing routine would be skipped, and they would remain on as long as the brake lever(s) were held in.
With the entire system installed and working perfectly, the only thing left to do is plan for future versions. The only known major problem is a crack on the back side of the headlight housing which has been generously coated in multiple layers of epoxy. A metal housing would be more durable and potentially lighter than the solid glass housing currently in use. Another little quirk which I decided not to work out in the software was an unexpected flashing ability of the head/taillights. Whenever the dim switch is held in indefinitely, the software will run through it's normal de-bounce routine and toggle the lights accordingly. That means that while the button is held in, the lights will continuously turn on and off each time the software recycles. Similarly, when the bright switch is held in, the bright and dim lights will toggle back and forth each time the software recycles. This could be a useful feature if flashing the headlights would ever be more useful than turning on the hazards. I may write the ability to select this mode without having to hold in the button into a future version of the code.
Also, I would eventually like to replace the bulky circuit with a surface mount board housing all of the parts and switches, but I have plenty enough else to keep me busy then to try and upgrade things that are working fine as is.
We really enjoy the look and feel of these bikes. We also get a lot of compliments on them.
Not much progress was made trying to cut off the lamp face.
The back of the first generation headlight...what a mess!
It's a mess of wires after the switches and indicators are soldered to the first generation control board.
If you are considering a similar project, check out the attached zip file containing all of the source files for the MCU as well as the latest schematic for use in Eagle PCB layout designer!