Seven LED Rear Blinker
d. bodnar  10-28-13

The seven LED bike light is designed to mount on the back of a saddle bag either with an existing strap on the bag or with a cable tie looped through two small holes in the bag.

The unit was designed to use seven LEDs in conjunction with the ULN2003A Darlington array that can power them all with one chip.  The array also has internal resistors on the base of each driver that eliminates the need for seven additional resistors between the output of the processor and the drivers.

A P-Channel Mosfet is used to brighten or dim the LEDs by controlling the PWM frequency on the common positive connection.

A single push button switch is used to turn the unit on and off and to change the blinking mode for the 7 LEDs.  This was done with a magnetic reed switch in an earlier revision but this proved to be problematic when trying to change modes.

Operating Modes
The software allows for six different operating modes. 
  • PWMBrightdim - all seven LEDs on - their brightness varies from full bright to dim and back to full bright
  • StarBurst - all off then LED4 on, then LED3 and LED5 on then all on - repeat
  • TopToBottomToTopFast - all off then LED1 & LED2 on, then LED3 then LED4 then LED5 then LED6 & LED7 - repeat
  • All - all on - pause - all off - pause - repeat
  • Corners  - all off - top two on - top two off/bottom two on - bottom two off/top two on - repeat
  • CornersCenter - Corners on/center 3 off - pause - corners off / center 3 on - repeat

 

The case was designed with Sketchup.  It is made up of a top with seven 10mm holes for the LEDs and a bottom with a mounting hook and a round block that can support a post that is used to level the unit on a saddle bag.  Click here for file.

This photo shows the case "printed" in black ABS using an Afinia 3D printer.  Click here for STL files  TOP and BOTTOM

The LEDs that are used are red, 1/2 watt, 10mm devices that put out between 15 and 20 lumens at 100 mA current.   They were purchased from eBay - see:  http://www.ebay.com/itm/151026675228?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649

 

Schematic

A custom circuit  board was designed using FreePCB software.  Gerber files were created and sent off for manufacture.  The PCB file is here.

Building the Circuit

The populated circuit board is shown here.   Power from the battery goes to one pair of the pins labeled "power" and the charging plug goes to the other.  The four pins labeled "i c s p" are for In Circuit Serial Programming which allows you to program the PIC chip after it has been soldered to  the board.


The components that attach to the circuit board are mostly surface mount devices.  Using SMT keeps the board profile as small as possible.

The two black integrated circuits are the PIC 16F683 microprocessor (lower left) and the ULN2003A Darlington array (bottom center).  The seven pairs of large holes are where the LEDs attach to the board.  These holes are quite large for two reasons.  One is to simplify alignment if the printout of the case is a bit off.  In addition the board is designed to fit to the very bottom of the LED leads which are quite large.

The small black device labeled "mosfet" is a P-Channel Mosfet the is used to vary the brightness of all seven LEDs as it controls the power on the common positive connection to each LED.

A jumper goes between the two pins labeled "10".  This area was originally designated for installation of a 10 ohm resistor to limit the power to the LEDs.  A jumper is used in place of the resistor since the Mosfet is now used to limit power.

There are two pairs of pins labeled reed 1a & 1b and reed 2a & 2b are are for two reed or pushbutton switches.  The software has been written to only use one switch (1a & 1b) and the other reed pins are not used.

The only component that is not SMT is the small capacitor to the left of the PIC chip.  It is a 0.1 uf bypass capacitor that was needed for testing.  It does not seem to be needed for normal operation of the blinker.

The five holes at the top of the board are for an accelerometer that may be added in the future.  My thought is that it could be used to brighten the light when you hit the brakes to decelerate.

Program for PIC 16F684 using PIC Basic Pro
'10-27-13 - IOC appears to be working --- needs more testing for ma draw
'10-16-13  PWN to P-Channel Mosfet connected to pin 5

include "modedefs.bas"
ansel=0                 'use pins as digital rather than analog
define OSC 8            'use 8 mhz oscillator
OSCCON = $70            'set clock speed 

cmcon0=7                'allows you to use pins as digital rather than analog
ansel=0 

SerialOut       var porta.0      'pin 13
LED7            var portc.0      'pin 10  ok 5   17
LED4            var portc.4      'pin 6   ok 3   44
LED3            var	porta.4      'pin 3   ok 2   23
LED2            var porta.5      'pin 2   ok 1   32
LED1            var portc.3      'pin 7   ok 7   51
LED6            var portc.2      'pin 8   ok 6   66
LED5            var porta.1      'pin 12  ok 4  75
Trigger         var porta.2      'pin 11
AllPWM          var portc.5      'pin 5 PWM
SleepCounter    var byte        'count times mode shown before sleep
MinMaxReptFlag  var byte        '0=temp, 1=min, 2=max- order of minmaxreport
y               var word
Temp            var byte
Temp2           var byte
ModeCount       var byte
TPause          con 300
BetweenPause    con 300
PWMMax          con 80
trisc = %00000000       
trisa = %00000100
data @0,1           ' start /w brightdim
read 0, ModeCount   'read mode 

serout SerialOut,n9600,[12,10,13,"Ver 16f684_v8-0-PWM-1SW-7-leds.bas ",10,13]
serout SerialOut,n9600,["(c) d. bodnar 10-27-13 - one switch- like helmet light",10,13]
gosub AllOff:
hpwm 1, PWMMax,0 'turn PWM full on - looks like it shoudl be off but NO

NewTop:
hpwm 1, PWMMax,0 'turn PWM full on - looks like it shoudl be off but NO
branch  ModeCount, [PWMBrightdim, StarBurst, toptobottomtotopfast, all, corners, cornerscenter]
goto NewTop:

Changemode:
gosub AllOff
SleepCounter=0
serout SerialOut,n9600,["CMd",10,13]
low LED3
ModeCount=ModeCount+1:if ModeCount>5 then ModeCount=0
StayHere:
    SleepCounter=SleepCounter+1    'count number of times reported
    if SleepCounter >=6 then GoToSleep 'if held for 5 repeats goes to sleep
    for y=1 to ModeCount+1     'flash mode
        high LED3:pause 100:low LED3:pause 100
    next y
pause 500
if Trigger=0 then StayHere:     'stay put till button released
serout SerialOut,n9600,["MD=",#modecount,10,13]
pause 300

write 0,ModeCount    'save current mode
goto newtop:

StarBurst:
SBpause con 200
serout 0,n9600,[10,13,"@StarBurst:",10,13]
gosub AllOff:pause 500
 if Trigger = 0 then goto changemode
'for temp2 = 1 to 10
  high LED4:pause SBpause
 if Trigger = 0 then goto changemode
  high LED3:high LED5:pause SBpause
   if Trigger = 0 then goto changemode
  high LED6:high LED7:high LED2:high LED1:pause SBpause
   if Trigger = 0 then goto changemode
  pause 500
   if Trigger = 0 then goto changemode
   pause 500
    if Trigger = 0 then goto changemode
  gosub AllOff
'next temp2
goto newtop

PWMBrightDim:
serout 0,n9600,[10,13,"@PWMBrightDim:",10,13]
 high LED1:high LED2:high LED3:high LED4:high LED5:high LED6:high LED7
 if Trigger = 0 then goto changemode
'for temp2 = 1 to 10
  for Temp = PWMMax to 255 step  1
   if Trigger = 0 then goto changemode
    '   serout serialout, n9600,["TEMP=",#temp,13,10]
    hpwm 1, Temp , 2000
    pauseus 1000
  next Temp 
  for Temp = 255 to PWMMax step -1
   if Trigger = 0 then goto changemode
    '    serout serialout, n9600,["TEMP=",#temp,13,10]
    hpwm 1, Temp , 5500
    pauseus 500
  next Temp  
  if Trigger = 0 then goto changemode
  pause 200   
  if Trigger = 0 then goto changemode
'next temp2 
goto newtop

All:         '(4)
if Trigger = 0 then goto changemode
serout SerialOut,n9600,["all",10,13]
if Trigger = 0 then goto changemode
'gosub alloff:
'for temp = 1 to 10
if Trigger = 0 then goto changemode
  toggle LED1:toggle LED2:toggle LED3:toggle LED4:toggle LED5:toggle LED6:toggle LED7
  if Trigger = 0 then goto changemode
  pause 500
  if Trigger = 0 then goto changemode
'next temp
goto newtop

Corners:
if Trigger = 0 then goto changemode
serout SerialOut,n9600,["Corners",10,13]
if Trigger = 0 then goto changemode
'for temp = 1 to 10
if Trigger = 0 then goto changemode
  gosub AllOff:
  if Trigger = 0 then goto changemode
  high LED1:high LED2:
  pause 500
  if Trigger = 0 then goto changemode
  low LED1:low LED2:
  high LED6:high LED7:
  pause 500
  if Trigger = 0 then goto changemode
'next temp                  
goto newtop

TopToBottom:
if Trigger = 0 then goto changemode
serout SerialOut,n9600,["TopToBottom",10,13]
if Trigger = 0 then goto changemode
'for temp = 1 to 10
if Trigger = 0 then goto changemode
  gosub AllOff:
  if Trigger = 0 then goto changemode
  pause 500
  if Trigger = 0 then goto changemode
  high LED1:high LED2:
  pause 200
  if Trigger = 0 then goto changemode
  high LED3:
  pause 200
  if Trigger = 0 then goto changemode
  high LED4:
  pause 200
  if Trigger = 0 then goto changemode
  high LED5
  pause 200
  if Trigger = 0 then goto changemode
  high LED6:high LED7
  pause 500
  if Trigger = 0 then goto changemode
'next temp                  
goto newtop

TopToBottomToTopFast:
PPause con 50 
if Trigger = 0 then goto changemode
serout SerialOut,n9600,["TopToBottomToTopFast",10,13]
if Trigger = 0 then goto changemode
'for temp = 1 to 10
if Trigger = 0 then goto changemode
  gosub AllOff:
  if Trigger = 0 then goto changemode
  pause PPause
  if Trigger = 0 then goto changemode
  high LED1:high LED2:
  pause PPause
  if Trigger = 0 then goto changemode
  high LED3:
  pause PPause
  if Trigger = 0 then goto changemode
  high LED4:
  pause PPause
  if Trigger = 0 then goto changemode
  high LED5
  pause PPause
  if Trigger = 0 then goto changemode
  high LED6:high LED7
  pause PPause
  if Trigger = 0 then goto changemode
  
  if Trigger = 0 then goto changemode
  if Trigger = 0 then goto changemode
  pause PPause
  if Trigger = 0 then goto changemode
  low LED6:low LED7:
  pause PPause
  if Trigger = 0 then goto changemode
  low LED5:
  pause PPause
  if Trigger = 0 then goto changemode
  low LED4:
  pause PPause
  if Trigger = 0 then goto changemode
  low LED3
  pause PPause
  if Trigger = 0 then goto changemode
  low LED1:low LED2
  pause PPause
  if Trigger = 0 then goto changemode
'next temp  
goto newtop

CornersCenter:
if Trigger = 0 then goto changemode
serout SerialOut,n9600,["CornersCenter",10,13]
if Trigger = 0 then goto changemode
'for temp = 1 to 10
if Trigger = 0 then goto changemode
  gosub AllOff:
  high LED1:high LED2:high LED6:high LED7
  if Trigger = 0 then goto changemode
  pause 500
  if Trigger = 0 then goto changemode
  gosub AllOff:
  high LED3:high LED4:high LED5
  pause 500
  if Trigger = 0 then goto changemode  
'next temp
goto newtop

GoToSleep:
 gosub AllOff:
hpwm 1, 255, 5500 'turn PWM full off which turns LEDs on!
pause 50
 if Trigger = 1 then goto newtop    'have to hold it for a time - filters bounce
ModeCount=ModeCount-1
write 0, ModeCount      'save current mode 
'write 1, mode       'save current mode
serout 0,n9600,[10,13,"@Sleepzzzzzzzzzz",10,13]
hpwm 1, 0,0
for y= 100 to 0 step -7  'dim showing going to sleep
    high LED1:high LED2:high LED3:high LED4
    pause y
    low LED1:low LED2:low LED3:low LED4
    pause y
next y
hpwm 1, PWMMax, 0
low LED1:low LED2:low LED3:low LED4
INTCON = %00001100
'INTCON.0 = 0	'Reset the  Port change bit 
IOCA=0  'clear
IOCA.2=1      'set bit 2
LongSleep:
low LED1
serout 0, n9600, ["Z", 10,13]
pause 500
INTCON.0 = 0	'Reset the  Port change bit
porta.2=0        'reset switch pin    -was porta.3
IOCA = %00000100 'enable INTERRUPT ON CHANGE on a.2

sleep 65000
if intcon.0=0 then goto longsleep
hpwm 1, 0,0
high LED1
pause 100
INTCON.0 = 0	'Reset the  Port change bit   
'IOCA=0

if Trigger = 0 then longsleep 
for y= 0 to 100 step 3  'dim showing going to sleep
    high LED1:high LED2:high LED3:high LED4
    pause y
    low LED1:low LED2:low LED3:low LED4
    pause y
next y   
high LED1:high LED2:high LED3:high LED4
serout 0, n9600, ["xZ", 10,13] 
INTCON.0 = 0	'Reset the  Port change bit   
pause 1000
goto Newtop:
 
AllOff:
low LED1:low LED2:low LED3:low LED4:low LED5:low LED6:low LED7
return