Introduction: Bicycle Automatic Brake Lights

Welcome to our guide on Instructables.com, where we address a critical safety concern: the frequent collisions or near-misses between pedestrians and cyclists, particularly prevalent on university campuses during the darker months of fall and spring. With decreased visibility at night, it's vital for cyclists to be seen by both motorists and pedestrians. This is where lights on bicycles play a crucial role in signaling the cyclist's presence and intended movements, such as under braking. These measures are essential not only on college campuses but also in urban settings, enhancing overall cyclist safety. We've also observed a concerning trend among campus cyclists – many forego proper protective gear, making collision avoidance even more crucial to prevent serious injuries. Join us in this project to make our campuses and cities safer for everyone. Cars and motorcycles have brake lights, so why not bicycles? In this project, we develop a system of automatic brake lights, triggered by an accelerometer that detects when bike is slowing down - that can be retrofitted to any existing bike.

Supplies

Electrical supplies:

*note that components such as resistors, capacitors, jumpers, PCBs, etc. are often available in bulk/assorted packs and from a variety of suppliers. Use what is most easily available or best fits your circumstances.

  • 1x Microcontroller: Arduino Micro
  • https://www.amazon.com/Arduino-Micro-Headers-A000053-Controller/dp/B00AFY2S56/ref=sr_1_3?crid=169KCVVCNAR3Q&keywords=arduino%2Bmicro&qid=1702328052&sprefix=arduino%2Bmicro%2Caps%2C93&sr=8-3&th=1
  • 1x Accelerometer (GY-521 module)
  • https://www.amazon.com/HiLetgo-MPU-6050-Accelerometer-Gyroscope-Converter/dp/B01DK83ZYQ?th=1
  • 1x WS2812B Addressable LED strip
  • https://www.amazon.com/WESIRI-Programmable-Individual-Addressable-Non-Waterproof/dp/B07C1VJ1WS/ref=sr_1_9?crid=COLY8P3LZLEZ&keywords=WS2812B%2BAddressable%2BLEDs&qid=1702328595&sprefix=ws2812b%2Baddressable%2Bleds%2Caps%2C104&sr=8-9&th=1
  • 1x 330 ohm resistor
  • https://www.amazon.com/EDGELEC-Resistor-Tolerance-Multiple-Resistance/dp/B07QH5PFG3/ref=sr_1_1_sspa?crid=32THW14E8Z1SR&keywords=330+ohm+resistor&qid=1702328785&sprefix=330+ohm+resistor%2Caps%2C83&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1
  • 1x 100uF capacitor
  • https://www.amazon.com/Projects-Radial-Electrolytic-Capacitor-100uF/dp/B07YN6NX4H/ref=sr_1_3?crid=2MO06X7KIENU8&keywords=100+uf+capacitor&qid=1702328799&sprefix=100+uf+capa%2Caps%2C90&sr=8-3
  • 1x Solderable prototype PCB
  • https://www.amazon.com/ELEGOO-Prototype-Soldering-Compatible-Arduino/dp/B072Z7Y19F/ref=sr_1_3?crid=VPAAI3WS5UM3&keywords=prototype+PCB&qid=1702328841&sprefix=prototype+pcb%2Caps%2C152&sr=8-3
  • Assorted breadboard jumpers:
  • https://www.amazon.com/Elegoo-EL-CP-004-Multicolored-Breadboard-arduino/dp/B01EV70C78/ref=sr_1_2_sspa?crid=295HZ6L4WDMYT&keywords=breadboard+jumpers&qid=1702328966&sprefix=breadboard+jumpers%2Caps%2C95&sr=8-2-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1
  • https://www.amazon.com/AUSTOR-Lengths-Assorted-Preformed-Breadboard/dp/B07CJYSL2T/ref=sr_1_3?crid=295HZ6L4WDMYT&keywords=breadboard+jumpers&qid=1702328978&sprefix=breadboard+jumpers%2Caps%2C95&sr=8-3
  • Assorted breadboard headers:
  • https://www.amazon.com/Glarks-Connector-Assortment-Stackable-Breakaway/dp/B07CWSXY7P/ref=sr_1_3?crid=2YH2X1T5523C1&keywords=breadboard+headers&qid=1702329148&sprefix=breadboard+headers%2Caps%2C94&sr=8-3
  • 1x Battery bank
  • You can use whatever battery bank you have. Larger capacities mean longer batter life but are more expensive.
  • The battery bank used in this project: https://www.amazon.com/Anker-PowerCore-Portable-Charger-Compatible/dp/B09VPHVT2Z/ref=sr_1_5?crid=1S7CDHKPVYNII&keywords=anker+battery+bank&qid=1702329737&sprefix=anker+battery+bank%2Caps%2C115&sr=8-5
  • More affordable/smaller battery bank: https://www.amazon.com/SIXTHGU-Portable-Capacity-External-Indicator/dp/B08QHG7BTB/ref=sr_1_5?crid=RKKIDR2G0635&keywords=mini%2Busb%2Bbattery%2Bbank&qid=1702329800&sprefix=mini%2Busb%2Bbattery%2Bbank%2Caps%2C155&sr=8-5&th=1
  • 2x USB-A to Micro-USB cable
  • https://www.amazon.com/Amazon-Basics-Charging-Transfer-Gold-Plated/dp/B0711PVX6Z/ref=sr_1_1_ffob_sspa?crid=5HL929OI3YIL&keywords=micro%2Busb%2Bcable&qid=1702330010&sprefix=micro%2Busb%2Bcable%2Caps%2C146&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&th=1

Soldering equipment:

  • Any basic soldering iron will work. Use whatever soldering iron/solder/flux you are most comfortable with. Useful accessories such as solder pump and third hand are recommended but not required.
  • Complete entry-level soldering starterkit: https://www.amazon.com/YIHUA-Soldering-194%C2%BAF-896%C2%BAF-Adjustable-Calibration/dp/B082F1WKP9/ref=sr_1_10?crid=2M5SY5IS6KUMS&keywords=soldering%2Bkit&qid=1702328275&sprefix=soldering%2Bkit%2Caps%2C94&sr=8-10&th=1

Other equipment:

  • Assorted Zipties
  • https://www.amazon.com/HAVE-ME-TD-Cable-Ties/dp/B08TVLYB3Q/ref=sr_1_3?crid=2L567SSSGJS3V&keywords=zipties&qid=1702328507&sprefix=zipties%2Caps%2C94&sr=8-3&th=1
  • Wire strippers
  • https://www.amazon.com/ETAPCO-Wire-Stripper-ETWS-04-Strippers/dp/B0B4S6JT48/ref=sr_1_1_sspa?crid=2M1YD11MIJH9Y&keywords=wire+strippers&qid=1702329867&sprefix=wire+strippers%2Caps%2C113&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1
  • Flush cutters
  • https://www.amazon.com/IGAN-170-Precision-Electronic-Strongest-Ultra-fine/dp/B07GR7QF63/ref=sr_1_1_sspa?crid=38O9NINWL12I6&keywords=flush+cutters&qid=1702329906&sprefix=flush+cutters%2Caps%2C121&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1

Step 1: Mount Microcontroller and Accelerometer to PCB

  1. Using Male to Female headers, cut to the lengths of the accelerometer and the Arduino Micro
  2. As shown in the second and third photos above, place the header pins through the PCB and solder in place
  3. Locate digital output pin 6 from the Arduino Micro
  4. To the respective adjacent point on the PCB, solder the 330 ohm resistor
  5. On the downstream end of this resistor, on the edge of the PCB, solder a 3 pin male-to-male header
  6. Align the middle pin of the header to the resistor you just installed
  7. Connect the two outside pins of the 3 pin male-to-male header just soldered to the board (as shown in figures 4 and 5) with the 100 uF capacitor
  8. The capacitor helps to protect the LED strip from spikes or drops in voltage by attenuating noise
  9. Using breadboard jumper cables, route the following header pins from the accelerometer to the Arduino-Micro
  10. Vcc (accelerometer) to +5V (Arduino)
  11. GND (accelerometer) to GND (Arduino)
  12. SDA (accelerometer) to SDA (Arduino)
  13. SCL (accelerometer) to SCL (Arduino)
  14. Figure 7 highlights the pinout of the Arduino Micro that is utilized in the steps above

Step 2: Route Connection to Power Bank

  1. Cut USB-A to Micro-USB cable about 3 inches from the Micro-USB end
  2. Strip about 1 inch of casing from both newly created ends to reveal 3 wires on each end
  3. Red (positive)
  4. Black (ground)
  5. White (data)
  6. Cut away and secure white data wire as it will not be utilized
  7. Strip away about 0.5 inches of the casing on the red and black wires from each segment
  8. Twist and tin all 4 wires (2 Red and 2 Black) to prepare them to be inserted into prototype PCB
  9. As illustrated by the arrows in the figure shown, solder the red wires to the designated positive rail and the black wires to the designated negative rail.
  10. Bridge all the traces as shown in the figure above
  11. Connections to be bridged on red (+5V) rail:
  12. Male header +
  13. Micro-USB +
  14. USB-A +
  15. One lead of 100 uF capacitor
  16. Connections to be bridged on black (ground) rail:
  17. Male header -
  18. Micro-USB -
  19. USB-A -
  20. Remaining lead of 100 uF capacitor
  21. Plug Micro-USB into Arduino Micro and USB-A into output of power bank.
  22. If all connections are secure and done correctly, the microcontroller and accelerometer board will illuminate their status LEDs.


Step 3: Programming

  1. Connect the Arduino Micro to your computer using a micro-USB cable
  2. Launch the Arduino IDE and create a new sketch with the following code:
#include <Adafruit_NeoPixel.h>  // This libarary allows you to communicate with the LED strip
#include "Wire.h" // This library allows you to communicate with I2C devices.


#ifdef __AVR__
#include <avr/power.h>


#endif
#define PIN 6 //set to the digitial output pin on the Arduino utilized
#define NUMPIXELS 40 //set to the number of LEDs on the LED strip you used


Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500

const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.


int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t accelermoter_buffer;
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data


char tmp_str[7]; // temporary variable used in convert function


char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
sprintf(tmp_str, "%6d", i);
return tmp_str;
}


void setup() {


#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif


Serial.begin(9600);


Wire.begin();
Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);


pixels.begin();


//sets all LEDs to red
for(int i=0; i<NUMPIXELS; i++)
{
pixels.setPixelColor(i, pixels.Color(255, 0, 0));
}
pixels.show();
}


void loop()
{
//creates a buffer to hold the previous acceleromter value
//previous acceleromater value is compared against current to filter out sudden spikes
accelermoter_buffer = accelerometer_z;

pixels.setBrightness(50); //sets LEDs to a dim brightness
pixels.show(); //updated LED strip

Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers

accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)


// print out data
Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
Serial.println();

// delay 50 milliseconds
delay(50);


//compares accelerometer value of previous loop cycle and current acceleromter value to acceleromter threshold
//if both variables fall outside the threshold set, this indicates that the acceleromter is experiencing severe enough braking
//to warrant illuminating the LEDs.
//The threshold value (default -5000) can be tuned/adjusted as necessary for smooth operation
if ((accelerometer_z <= -5000) && (accelermoter_buffer <= -5000))
{
pixels.setBrightness(255); //sets brightness of LEDs to full
pixels.show(); //updates the LED strip
delay(250); //paused code execution for 250 milliseconds
}

}


  • The code above utilizes the library 'Adafruit Neopixel' to communicate with the LED strip and 'Wire' for I2C communication to the accelerometer board
  • Variable NUMPIXELS should be updated once the system is mounted to the bike and the LED strip is cut the desired length. You will need to count the number of LEDs remaining on the LED strip and enter that number in the code.
  • The code illuminates the LEDs to a dim baseline level at all times to ensure that the rider is always visible to pedestrians and motorists. When braking is detected, the LEDs will increase to their maximum illumination.
  • Serial output is established so that you can see the raw data output of the accelerometer. You can use these values to adjust the braking threshold to your desired sensitivity.

Step 4: Mount to Bike

  1. Using Male-to-Female jumper cables, connect the LED strip to the output pins from the PCB as shown in figure 1
  2. As shown in Figure 2, ensure you connect +5V to the +5V pin, GND to the GND pin, and DI to the data pin.
  3. As shown in figure 1, secure the PCB to the battery bank using Zip-ties or rubber bands
  4. Secure the LED control module (battery bank + PCB) to the bike
  5. Ensure that the face of the accelerometer is oriented perpendicular to the axis of motion of the bike. In order words, the flat face of the accelerometer should be facing towards the front of the bike. This is the axis of which the accelerometer readings are taken
  6. Using Zip-ties, secure the LED strip to the frame of the bike
  7. Use as much LED length as you wish, ensuring neat cable management to prevent loose cables from being entangled in moving parts of the bike
  8. Cut the LED strip once the desired coverage has been reached
  9. Cut along the designated cutting lengths
  10. Count the number of LEDs remaining on the bike and update the variable NUMPIXELS (as described in Step 3) if necessary
  11. Recompile and re-upload code to the Arduino Micro as necessary