motorcycle turn signal flasher and hazard lights

This is a turn light signal flasher for motorbikes with 3 modes of flashing

Based on PIC16F628A its a complete flasher system adding turn signals , hazard lights and a short flashing mode for better visibility in traffic.

This was the first automotive project i`ve ever made so i had no idea what could go wrong.My main concern was electric noise going to the microcontroller and cause random resets , lagging or other strange behaviour.
Also another thing i had to take in concern was how to drive the lamps since i knew that the building size would be limited if you consider the amount of cables there.

I had already reserved some space behind the main headlight of the KLR250 i had back then , so i already had an idea how big i should make. Driving the six lamps could not be done using transistors since the take up a lot of space (also i didnt have any to make my tests) so i decided to use a ULN2003A

This did have the capacity to drive the lamps (4 flash lights and two on the dashboard) and the loud buzzer without any problem. I used this system for years until i gave the bike away and it was still working without problem!

The whole system is made on two seperate metal boxes , one that has the microcontroller and the ULN2003 and one that contains the PSU.

After everything was working on the breadboard i made the boards , put everything in the boxes , made some tests , i had to find an ergonomic way to use it.

There are 4 buttons to place on the handle bar , one left – right signal , one for the hazard lights and the visibility flasher. Luckily ebay had the solution! Someone was selling this magnificent multiswitch specialy made for motorcycle handlebars but it had one button less.

No problem with that, I`ve just added a small board with two buttons i had in the bin and that was it!. Yes yeaah i know they’re not waterprooved and blahblah blah..Didnt care at all..4 years or rain and some times just spraying them with contact cleaner , zero problems

The PSU is very simple , just outputs 2 different voltages , one 12V for the ULN2003A and one 5V for the PIC16F628A.

The mainboard is nothing special actualy.Just the microcontroler and the driver chip , notice though the ICSP port.The pinout is not correctly placed (according to PICKIT) because the cheap chinese programmer i used back the had its own pinout.Well…

Heres a short (and very bad) video of the flasher in action

Again the program was written in PICC and consists of a main file and an include file. This was the way i was doing it back then , just copying the same schematic with some changes and adding or deleting library files

You can find the .hex file for direct burn here
Also the source file is available here

There are also the designs for the boards on pdf
The main board can be found here
And the PSU can be found here

flasherSystem1.c

#include "16F628A.h"
#use delay(clock=4000000)
#FUSES INTRC_IO
#FUSES NOWDT
#FUSES NOPUT
#FUSES NOPROTECT
#FUSES NOBROWNOUT
#FUSES NOMCLR
#FUSES NOLVP
#FUSES NOCPD

#include "includes/flex_KBD.C"

unsigned int16 count=0;
char k;
int8 action=0,cc,subcnt=0;
int1 state=0,substate=0;

//Flasher speed parameters and option========
#define FLASH_COUNT 5000
#define STROBE_COUNT_LOW 40000
#define STROBE_COUNT_HIGH 2000
#define BUZZER 1
//===========================================


//==================== FLASHING ACTIONS===============
void led_proc(){
   if(action==1 || action ==2){ //LEFT, RIGHT and ALARM SIGNAL      
      while(TRUE){
         k=kbd_getc();
         //flasher state
         if(state==0){//xronos led svismena
            if(count<FLASH_COUNT){ state=0; count++; } if(count==FLASH_COUNT) state=1; } if(state==1){//xronos led anamena if(count>0){
               state=1;
               count--;
            }
            if(count==0) state=0;
         }
         
         //light status
         if(state==1){
            if(action ==1) output_high(PIN_A2);
            if(action ==2) output_high(PIN_A3);
            if(action ==3) {//an einai alarm
               output_high(PIN_A2);
               output_high(PIN_A3);
            }
            if(BUZZER==1) output_high(PIN_A0);
         } else {
            if(action ==1) output_low(PIN_A2);
            if(action ==2) output_low(PIN_A3);
          /*  if(action ==3){// an einai alarm
               output_low(PIN_A2);
               output_low(PIN_A3);
            }*/
            if(BUZZER==1) output_low(PIN_A0);
         }
         
         //escape routine
         if(k) {
            k="";count=0;action=0;
            output_low(PIN_A2);
            output_low(PIN_A3);
            if(BUZZER==1) output_low(PIN_A0);
            break;
         }
      }
    } // end of action
    
      if(action==3){ //LEFT, RIGHT and ALARM SIGNAL      
      while(TRUE){
         k=kbd_getc();
         //flasher state
         if(state==0){//xronos led svismena
            if(count<FLASH_COUNT){ state=0; count++; } if(count==FLASH_COUNT) state=1; } if(state==1){//xronos led anamena if(count>0){
               state=1;
               count--;
            }
            if(count==0) state=0;
         }
         
         //light status
         if(state==1){
            output_high(PIN_A2);
            output_high(PIN_A3);   
            if(BUZZER==1) output_high(PIN_A0);
         } else {
            output_low(PIN_A2);
            output_low(PIN_A3);   
            if(BUZZER==1) output_low(PIN_A0);
         }
         
         //escape routine
         if(k) {
            if(k=='A'){
               action=4;
            } else {
               action=0;
            }
            k="";count=0;action=4;
            output_low(PIN_A2);
            output_low(PIN_A3);
            if(BUZZER==1) output_low(PIN_A0);
            break;
         }
      }
    } // end of action
      
    
   if(action==4){ //STROBE
      while(TRUE){
         k=kbd_getc();
         //flasher state
         if(state==0){//xronos leds svismena
            if(count<STROBE_COUNT_LOW){ state=0; count++; } if(count==STROBE_COUNT_LOW) state=1; } if(state==1){//xronos leds anamena if(count>0){
               state=1; 
               count=count-STROBE_COUNT_HIGH;//xronos anamatos
            }
            if(count==0) state=0;
            
         }
         
         //light status
         if(state==1){
            output_toggle(PIN_A2);
            output_toggle(PIN_A3);
            delay_ms(70);
         } else {
            output_low(PIN_A2);
            output_low(PIN_A3);          
         }
         
         //escape routine
         if(k) {
            k="";action=0;state=0;count=0;
            output_low(PIN_A2);
            output_low(PIN_A3);
            break;
         }
         
         //delay_us(50);
      }
    } // end of action    
    
}

void startup(){
   delay_ms(500);
   output_high(PIN_A2);
   output_high(PIN_A3);
   if(BUZZER==1) output_high(PIN_A0);
   delay_ms(150);
   output_low(PIN_A2);
   output_low(PIN_A3);
   if(BUZZER==1) output_low(PIN_A0);
   delay_ms(180);
   output_high(PIN_A2);
   output_high(PIN_A3);
   if(BUZZER==1) output_high(PIN_A0);
   delay_ms(150);
   output_low(PIN_A2);
   output_low(PIN_A3);
   if(BUZZER==1) output_low(PIN_A0);
   
   kbd_init();
}
//====================================================================
void main(){
   startup();
  
   
   while(TRUE){
      k=kbd_getc();
      if(k=='L') action=1;
      if(k=='R') action=2;
      if(k=='A') action=3;
     
      //if(k=='S') action=4;
      led_proc();
   } 
}

/includes/flex_KBD.c (taken from the PICC forum)

/////////////////////////////////////////////////////////////////////////// 
////                             Flex_KBD.C                            //// 
////                  Generic keypad scan driver                       //// 
////                                                                   //// 
////  kbd_init()   Must be called before any other function.           //// 
////                                                                   //// 
////  c = kbd_getc(c)  Will return a key value if pressed or /0 if not //// 
////                   This function should be called frequently so as //// 
////                   not to miss a key press.                        //// 
////                                                                   //// 
/////////////////////////////////////////////////////////////////////////// 



//Keypad connection:  

#define col0 PIN_B1
#define col1 PIN_B2 
#define col2 PIN_B3 
#define row0 PIN_B4 
#define row1 PIN_B5 
#define row2 PIN_B0 
#define row3 PIN_B7 

// Keypad layout: 
char const KEYS[4][3] = {{'L','A','S'}, 
                         {'R','5','6'}, 
                         {'7','8','9'}, 
                         {'*','0','#'}};

#define KBD_DEBOUNCE_FACTOR 20    // Set this number to apx n/333 where 
                                  // n is the number of times you expect 
                                  // to call kbd_getc each second 



void kbd_init() { 
} 


short int ALL_ROWS (void) 
{ 
   if (input (row0) & input (row1) & input (row2) & input (row3)) 
      return (0); 
   else 
      return (1); 
} 



char kbd_getc( ) { 
   static byte kbd_call_count; 
   static short int kbd_down; 
   static char last_key; 
   static byte col; 

   byte kchar; 
   byte row; 

   kchar='\0'; 
   if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) { 
       switch (col) { 
         case 0   : output_low(col0); 
               output_high(col1); 
               output_high(col2); 
                    break; 
         case 1   : output_high(col0); 
               output_low(col1); 
               output_high(col2); 
                    break; 
         case 2   : output_high(col0); 
               output_high(col1); 
               output_low(col2); 
                    break; 
       } 

       if(kbd_down) { 
         if(!ALL_ROWS()) { 
           kbd_down=false; 
           kchar=last_key; 
           last_key='\0'; 
         } 
       } else { 
          if(ALL_ROWS()) { 
             if(!input (row0)) 
               row=0; 
             else if(!input (row1)) 
               row=1; 
             else if(!input (row2)) 
               row=2; 
             else if(!input (row3)) 
               row=3; 
             last_key =KEYS[row][col]; 
             kbd_down = true; 
          } else { 
             ++col; 
             if(col==3) 
               col=0; 
          } 
       } 
      kbd_call_count=0; 
   } 
  return(kchar); 
}