Print Shortlink

Adding auto-shutoff turn signals to a motorcycle

I always use my blinkers when I drive. Always. If I won a billion dollar powerball jackpot, I would use 900 million to form death-squads to hunt down meandering jerks who casually change lanes without even a hint of their actions to their fellow travelers. Bikers get a pass, though. Many motorcycle riders opt to use hand signals for several reasons; one of the more common being that motorcycle turn signals do not automatically cancel after a turn. It is easy to ride for miles, blissfully unaware that your blinker is on. Full face helmet riders are particularly prone to this riding faux pas as the lower portion of the helmet often obscures the dash display.

I commute on my sportsbike nearly every day that the weather permits. I have noticed that bright blinkers are better observed by drivers than hand signals, particularly for right-hand turns, so I opt to use my indicators on the freeway. After a commute home from work on a particularly heavy traffic day, I complained to my wife that I missed the “quick-blinker” feature in her BMW; that is, the half press you can do on the indicator lever (think autofocus on a SLR camera) that causes the blinkers to fire off several times then stop automatically. She said, “can’t you make your bike do that?” and it dawned on me that yeah, I could do that!

The first step was to take a look at the switching mechanism. The whole thing is mechanical. A little box with terminals slides back and forth to contact a center pin with either the left blinker output or the right blinker output. A complicated little mechanism moves the box back to center when the signal lever is depressed in the center position. This detaches the center pin from either of the other two pins and turns the blinkers off. My intent was to time how long the indicator lever was active in either the left or right position and, based on a short or long press, activate the blinkers for five blinks or keep them on indefinitely. What I needed were momentary switchs on the left, right and center positions. This box connector thingy represented a latching switch and was not going to work for my needs.

I removed the guts of the switch and starting running through my options to get the signal I needed. The obvious answer was to add momentary switches that would trigger in the positions I needed. I tried to dry fit some really tiny switches inside the casing to no avail. There just was not enough room to fit them in on the left and right positions. I decided to go with hall sensors, which are essentially tiny, solid-state magnetic switches. I opted to use Honeywell SS451A’s as they are cheap, readily available, non-latching and will only trigger with a strong magnetic field. A couple of permanent magnets on the lever are used to trigger the sensors. Some soldering and a lot of hot glue later and everything is in position. A bench test showed that the switches closed only when the indicator lever is in the appropriate left, right or center position.

The rest of the project was straightforward. I soldered up a board with a couple of relays, a 5V power supply and attached everything to an arduino mini I had laying around. I also added a reset switch on my dash, just in case something went amiss. The left and right blinkers were wired to the arduinos two hardware interrupt pins and the main loop used to evaluate how long a switch was held. Anything over a couple of seconds would trigger  a blinker to remain on while anything under that causes the blinker to stay on shortly then turn off. Other triggers were added to turn off the opposing blinker when indicating and cancelling both blinkers after the center button is pushed.

Below is my final code. I had a few stability issues the first go around, but the bugs are worked out in this rev and everything has been working rock solid for weeks.

// initialize input pins
unsigned int cancel_pin = 7;
unsigned int left_relay_pin = 9; // choose the input pin (for a pushbutton)
unsigned int right_relay_pin = 8;
unsigned int sensor_pwr = 10;

// initialize variables

volatile boolean left_change = false; //State variables controlled by interrupts
volatile boolean right_change = false;

boolean left_active = false; //Variables changed in loop to signal switches are on
boolean right_active = false;
boolean cancel = false;
unsigned int switch_count = 0; //counter used to determine length of time a switch is active
unsigned int switch_timeout = 10; //switch hold time to keep blinker on
unsigned int blink_time = 0; //counter used to keep track of how long the blinker has been on
unsigned int auto_blink_time_max = 33; //time blinkers will stay on in auto shutoff mode (33 = 5 blinks)
boolean left_relay_active = false;
boolean right_relay_active = false;
void setup() {

//assign input/output pins
pinMode(cancel_pin, INPUT);
pinMode(left_relay_pin, OUTPUT); left_relay(false); //set relay pins and make sure relays are off
pinMode(right_relay_pin, OUTPUT); right_relay(false);
pinMode(sensor_pwr, OUTPUT); digitalWrite(sensor_pwr,LOW);
delay(2500);
digitalWrite(sensor_pwr, HIGH);

// attach interrupts
attachInterrupt(0, left_switch, CHANGE);
attachInterrupt(1, right_switch, CHANGE);
}

void loop() {

switch_checks(); // set variables based on the states of the left, right and center switches

if (left_active || right_active) switch_count++; //increment counters to determine the length of time each switch is held and how long either the left or right relays have been active
if (left_relay_active || right_relay_active) blink_time++;

if (blink_time > auto_blink_time_max && switch_timeout > switch_count) //if the total blink time exceeds the autoblinker time and either switch timer is less than the delay time, turn off both relays
{
right_relay(false);
left_relay(false);
blink_time = 0; //reset the blinker and switch timers
switch_count = 0;
}

delay(100); // 100 ms delay to slow loop down
}

void switch_checks()
{
if (!digitalRead(cancel_pin)) //read state of cancel button, turn off blinkers and reset counters
{
switch_count=0; // turn everything off and reset all counters
blink_time = 0;
left_change = false;
right_change = false;
left_active = false;
right_active = false;
left_relay(false);
right_relay(false);
}

if (left_change && !left_active) // check to see if an interrupt for the left switch was triggered and if it was on during the previous loop
{
left_change = false; // reset trigger from interrupt
left_active = true; // set variable active, used to signal that the switch is on
if (right_relay_active) right_relay(false); // turn off right relay if on
left_relay(true);
}
else if (left_change && left_active) // triggered if switch has swapped states to off position
{
left_change = false; // reset trigger from interrupt
left_active = false; // reset active variable, used to signal that the switch is off
}

if (right_change && !right_active) // check to see if an interrupt for the right switch was triggered and if it was on during the previous loop
{
right_change = false; // reset trigger from interrupt
right_active = true; // set variable active, used to signal that the switch is on
if (left_relay_active) left_relay(false);
right_relay(true);
}
else if (right_change && right_active) // triggered if switch has swapped states to off position
{
right_change = false; // reset trigger from interrupt
right_active = false; // reset active variable, used to signal that the switch is off
}

//left_active=false;
//right_active = false;
}

void right_relay(boolean power)
{
if (power)
{
right_relay_active = true; // set relay state variable to on
digitalWrite(right_relay_pin, HIGH); // turn on relay
}
else
{
digitalWrite(right_relay_pin, LOW); // turn off right relay if already on
right_relay_active = false; // set right relay state variable to off
}
}

void left_relay(boolean power)
{
if (power)
{
left_relay_active = true; // set relay state variable to on
digitalWrite(left_relay_pin, HIGH); // turn on relay
}
else
{
digitalWrite(left_relay_pin, LOW); // turn off right relay if already on
left_relay_active = false; // set right relay state variable to off
}
}

void left_switch()
{
left_change=true;
}

void right_switch()
{
right_change=true;
}

 

Leave a Reply

You must be logged in to post a comment.