Bike helmet turn signal

It is dangerous to take your hands off of the handlebars when signaling a turn, so I designed a helmet-mounted turn signal than can be triggered by a small switch. The switch can be mounted on the handlebars or clipped to your wrist so that it dangles within easy reach of your fingers. The signal clips to the strap at the back of the helmet. Since there is not much distance between the left and right sides of the helmet, I used a strip of 6 LEDs that chase from left to right or vice-versa; this is similar to the system that some ambulances use.


Arduino board (center) wired to 3-way switch (top) and strip of 6 LEDs (left)

Arduino board (center) wired to 3-way switch (top) and strip of 6 LEDs (left)

Input is from a 3-way toggle switch; center position is “off” and makes no contact with any of the four pins, left and right position are used for left/right turn signal, and those positions make contact with the left and right pairs of contacts, respectively. Each pair of contacts is wired to the +5v rail of the breadboard and to a digital input pin, and those pins are also connected to ground through >1k ohm resistors. There is also a small potentiometer wired to an analog input pin from the middle (variable output) pin, while the other two pins on the pot are wired to ground and +5v, allowing the output pin to range from 0-5v.

The output to the 6 LEDs is through 6 digital pins, wired through 6 ~1k ohm resistors to the cathodes, while the anodes are wired to ground (would it be possible to use a single 1k ohm resistor between the junction of all the anodes and ground?) Also note that we extend the conductors to the LEDs using an 8-conductor CAT-5 cable with RJ-45 connectors. The jacks are wired to the breadboard at one end using 26-gauge solid-core jumpers which can be press-fit to the jack (no stripping required) and at the other end the LEDs cathodes are directly connected to the RJ-45 jack using the same press-fit connections. This does not give them much stability until they are pressed through the cardboard mounting strip (a more waterproof material would be a better long-term choice). The anodes are twisted together with a jumper which is attached to another pin on the RJ-45 jack; this connection should be strengthened with solder.


connections between LEDs, 3-way switch, and potentiometer and the Arduino's connectors

connections between LEDs, 3-way switch, and potentiometer and the Arduino

Arduino code

/* turn signal
ripple through a row of LEDs in one of two directions
speed (aka 1/slowness) is controlled by an analog input
boolean debug = false; // show debug messages on serial output
int leftButtonPin = 2; // connect to left side of 3-way switch
int rightButtonPin = 3; // connect to right side of 3-way switch
int rowWidth = 6; // number of LEDs
int firstLedPin = 4; // lowest pin number of LEDs - connect to adjacent pins in ascending order
int knobPin = 4; // connected to variable pin of potentiometer knob

int rippleDirection = 1; // can be set to +/- 1 for left-to-right or right-to-left rippling, respectively
int currentRipplePos = -1; // can be set from 0-(rowWidth-1) to indicate currently "active" LED, or set to -1 to indicate no active LED
int leftButton; // value read from left button pin; should be LOW or HIGH
int rightButton; // value read from right button pin; should be LOW or HIGH
boolean lightState[6]; // zero-indexed array of booleans indicating whether LED at that index should be off (false) or on (true)
int slowness; // delay per cycle, in milliseconds; set by knob position, scaled between min and max
int minSlowness = 5; // min delay
int maxSlowness = 500; // max delay
boolean justSwitched = false; // flag for the reset actions at the beginning of a left- or right-moving cycle; reset when switch is set to "off"
unsigned long lastMoveTime = millis(); // reset each time LED position changes
int rawKnobPos; // analog value of knob pin

void setup(){
// set all the LED pins to LOW (off) and digital output mode
int i;
for (i = 0; i < rowWidth; i = i + 1) {
lightState[i] = false;
pinMode(firstLedPin + i, OUTPUT);
// for debugging output

void loop(){
// read value of knob pin and set slowness to that value, scaled between min and max
rawKnobPos = analogRead(knobPin);
slowness = map(rawKnobPos, 0, 1024, minSlowness, maxSlowness);

// only show debug code when needed, as it adds a delay and limits the min slowness
if (debug == true){
Serial.print("current pos: ");
Serial.print(" direction: ");
Serial.print(" rawKnobPos: ");
Serial.print(" slowness: ");

// read button pins and make LEDs ripple if switch is not "off"
leftButton = digitalRead(leftButtonPin);
rightButton = digitalRead(rightButtonPin);
if ((rightButton == HIGH || leftButton == HIGH)){

if (leftButton ==HIGH){
if (debug == true){Serial.println(" left button on");}
rippleDirection = 1; // ripple from left to right
if (justSwitched == true){ // setup steps for the first cycle after switch moves from off to left
currentRipplePos = 0; // start with the left-most LED
justSwitched = false; // don't run setup steps again
lastMoveTime = millis(); // reset delay timer
} else {
if (debug == true){Serial.println(" right button on");}
rippleDirection = -1; // ripple from left to right
if (justSwitched == true){ // setup steps for the first cycle after switch moves from off to right
currentRipplePos = rowWidth - 1; // start with the right-most LED
justSwitched = false; // don't run setup steps again
lastMoveTime = millis(); // reset delay timer
// if switch is in "off" position
} else {
currentRipplePos = -1; // no active LED
justSwitched = true; // ready to run setup steps nect time switched on
// set all LEDs to LOW (off)
int j;
for (j = 0; j lastMoveTime + slowness){
// reset timer
lastMoveTime = millis();
// only make LEDs ripple if they are not set to off (position = -1)
if (currentRipplePos != -1){
// toggle the led at the current position; on->off or off->on
if (lightState[currentRipplePos] == false){
lightState[currentRipplePos] = true;
} else {
lightState[currentRipplePos] = false;

// if the position is at the end of the row, go to other end
if (currentRipplePos == (rowWidth - 1) && rippleDirection == 1){
currentRipplePos = 0;
} else if (currentRipplePos == 0 && rippleDirection == -1){
currentRipplePos = rowWidth - 1;
} else {
currentRipplePos = (currentRipplePos + rippleDirection);

// update the LED pins with the new values so the lights go blinky-blinky
int k;
for (k = 0; k < rowWidth; k = k + 1) {
if (lightState[k] == true){
digitalWrite(firstLedPin + k, HIGH);
} else {
digitalWrite(firstLedPin + k, LOW);