Introduction: Bicycle Turn Indicator From Backpack Cover

About: My mind races 24-7. Wherever I go I’m constantly observing and questing, pondering how to innovate the smallest details to improve the user experience. This questioning and curiosity is what drove to me the …

This project was created during the CCA Wheel Well Design Sprint  which was aimed at making bikers more visible to vehicles on the road. I used a material that I already had which was a backpack rain cover. The full post on the project can be found on my blog. To do this we took a back pack cover and water proof LEDs to create a pattern which could be used to indicate when the biker is turning right or left. Then the plan was to make a breaking signal and a general signal for riding.

You will need the following items or equivalents:

Material

  • Existing backpack cover
  • Thick canvas like material


Tools

  • Fabric scissors
  • Hot glue gun
  • Sharpie or pen
  • Computer


Hardware


Software

Step 1: Creating the Pattern

Start by creating a template that you can trace onto piece of fabric that will become you're backing for the LEDs. I ended up tracing my template onto both the backing fabric and the cover itself since the LEDs I was using waterproof. However it is only necessary to go to the backing material. Do this I found a large table and trace the shape onto the backing material with a sharpie and used a sharpie to estimate the size of the hole to create for the head of the LEDs.


After cutting out all of the circles that I marked on the backing fabric I popped the heads of LEDs through the holes and sod a X pattern across the back of each LED to be sure they were anchored to the backing prior to using the hot glue gun to fully fasten the LED and backing fabric together.

Something to keep in mind is that these are programmable RGB LEDs and therefore our most easily programmed when in a consistent sequence. For example I made sure that LEDs one through 12 minute at the left hand of the arrow and 13 through 24 minute the right-hand of the Arrow. Long-term this is simply easier to code for and ends up creating A nice pulsing effect when the signal becomes active.

Step 2: Assembling

Addressing the LEDS

The RGB LED are individually addressable (see what I did there) which means that each LED can be controlled independently of the others in the strip. Because of this we have a total of four connection to make instead of the usual two or three. Independently address for the LEDs require both a data connection and clock connection as well as the usual power and ground for total of four contact point per strip of 25.

[Side thought]
One feature I had added was a Data mail connector pins that the LEDs could be unplugged and plugged into the FLORA instead of being soldered directly to the FLORA. On the super helpful later when the future step the floor could be soon into the backpack along the switches for signaling left and right. But you would still be able to disconnect the less.


Soldering Components

Start by connecting the male of the connector for the LEDs. Solder the ground to ground and connect the power to vBatt. Then solder the data pin to D10 and the clock pin to D9 on the FLORA. Then solder one switch to D12 and the other to D6. Be sure to connect them each to ground (middle pin on switches) as well, then connect them to 3.3v on the FLORA.

Step 3: Coding




After I connected LEDs to the FLORA for the first time I wanted to test this entire strip too ensure I had a full range of color and all the LEDs were working properly. To do so I ran the following code which was included as an example sketch when you downloaded the LED library from Adafruit.




#include "SPI.h"<br>#include "Adafruit_WS2801.h"


/*****************************************************************************
Example sketch for driving Adafruit WS2801 pixels!




  Designed specifically to work with the Adafruit RGB Pixels!
  12mm Bullet shape ----> <a href="https://www.adafruit.com/products/322"> <a href="https://www.adafruit.com/products/322"> <a href="https://www.adafruit.com/products/322"> https://www.adafruit.com/products/322
</a>
</a>
</a>
  12mm Flat shape   ----> <a href="https://www.adafruit.com/products/738"> <a href="https://www.adafruit.com/products/322"> <a href="https://www.adafruit.com/products/322"> https://www.adafruit.com/products/322
</a>
</a>
</a>
  36mm Square shape ----> <a href="https://www.adafruit.com/products/683"> <a href="https://www.adafruit.com/products/322"> <a href="https://www.adafruit.com/products/322"> https://www.adafruit.com/products/322
</a>
</a>
</a>


  These pixels use SPI to transmit the color data, and have built in
  high speed PWM drivers for 24 bit color per pixel
  2 pins are required to interface


  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!


  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution


*****************************************************************************/


// Choose which 2 pins you will use for output.
// Can be any valid output pins.
// The colors of the wires may be totally different so
// BE SURE TO CHECK YOUR PIXELS TO SEE WHICH WIRES TO USE!
uint8_t dataPin  = 2;    // Yellow wire on Adafruit Pixels
uint8_t clockPin = 3;    // Green wire on Adafruit Pixels


// Don't forget to connect the ground wire to Arduino ground,
// and the +5V wire to a +5V supply


// Set the first variable to the NUMBER of pixels. 25 = 25 pixels in a row
Adafruit_WS2801 strip = Adafruit_WS2801(25, dataPin, clockPin);


// Optional: leave off pin numbers to use hardware SPI
// (pinout is then specific to each board and can't be changed)
//Adafruit_WS2801 strip = Adafruit_WS2801(25);


// For 36mm LED pixels: these pixels internally represent color in a
// different format.  Either of the above constructors can accept an
// optional extra parameter: WS2801_RGB is 'conventional' RGB order
// WS2801_GRB is the GRB order required by the 36mm pixels.  Other
// than this parameter, your code does not need to do anything different;
// the library will handle the format change.  Examples:
//Adafruit_WS2801 strip = Adafruit_WS2801(25, dataPin, clockPin, WS2801_GRB);
//Adafruit_WS2801 strip = Adafruit_WS2801(25, WS2801_GRB);


void setup() {
    
  strip.begin();


  // Update LED contents, to start they are all 'off'
  strip.show();
}




void loop() {
  // Some example procedures showing how to display to the pixels
  
  colorWipe(Color(255, 0, 0), 50);
  colorWipe(Color(0, 255, 0), 50);
  colorWipe(Color(0, 0, 255), 50);
  rainbow(20);
  rainbowCycle(20);
}


void rainbow(uint8_t wait) {
  int i, j;
   
  for (j=0; j < 256; j++) {     // 3 cycles of all 256 colors in the wheel
    for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel( (i + j) % 255));
    }  
    strip.show();   // write all the pixels out
    delay(wait);
  }
}


// Slightly different, this one makes the rainbow wheel equally distributed 
// along the chain
void rainbowCycle(uint8_t wait) {
  int i, j;
  
  for (j=0; j < 256 * 5; j++) {     // 5 cycles of all 25 colors in the wheel
    for (i=0; i < strip.numPixels(); i++) {
      // tricky math! we use each pixel as a fraction of the full 96-color wheel
      // (thats the i / strip.numPixels() part)
      // Then add in j which makes the colors go around per pixel
      // the % 96 is to make the wheel cycle around
      strip.setPixelColor(i, Wheel( ((i * 256 / strip.numPixels()) + j) % 256) );
    }  
    strip.show();   // write all the pixels out
    delay(wait);
  }
}


// fill the dots one after the other with said color
// good for testing purposes
void colorWipe(uint32_t c, uint8_t wait) {
  int i;
  
  for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}


/* Helper functions */


// Create a 24 bit color value from R,G,B
uint32_t Color(byte r, byte g, byte b)
{
  uint32_t c;
  c = r;
  c <<= 8;
  c |= g;
  c <<= 8;
  c |= b;
  return c;
}


//Input a value 0 to 255 to get a color value.
//The colours are a transition r - g -b - back to r
uint32_t Wheel(byte WheelPos)
{
  if (WheelPos < 85) {
   return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
   WheelPos -= 85;
   return Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170; 
   return Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}


Now that we know the LED strip is working we can upload the actual sketch that we want to use.
The sketch we created during the design jam to demonstrate the working concept.


/*
=================================================================
Coded for Wheel Well Design Jam at California College of the Arts
By 
William Felker @weftech [www.williamfelker.com] &
Analicia Barros @AnaliciaB_ [analiciab.tumblr.com]

Project inspired by: FLORA Backpack
<a href="http://learn.adafruit.com/flora-brakelight-backpack">http://learn.adafruit.com/flora-brakelight-backpac...</a>
=================================================================
*/
#include "SPI.h" //
#include "Adafruit_WS2801.h" // imports LED Library

uint8_t dataPin  = 10; //Green cable on WS2801
uint8_t clockPin = 9; //Yellow cable on WS2801

const int rightTurn = 12;     // the number of the right pushbutton pin
const int leftTurn = 6;     // the number of the left pushbutton pin

int buttonRight = 0;
int buttonLeft = 0;

Adafruit_WS2801 strip = Adafruit_WS2801((uint16_t)7, (uint16_t)7, dataPin, clockPin);

void setup() {
  strip.begin(); // Makes sure all LEDs start "off"
  strip.show();
}
void loop() {
buttonRight = digitalRead(rightTurn);
if (buttonRight == LOW ) {     // this could easily be made into a for loop
  //Right
  center(0,0,0,0);
  right(16,0,0,255);
  delay(100);
  center(0,0,0,0);
  } 
  else {
    // turn LED off:
  center(0,0,0,0);
  delay(5000);
  }
buttonLeft = digitalRead(leftTurn);
if (buttonLeft == LOW) {     // this could easily be made into a for loop  
  //LEFT
  left(1,0,0,255);
  delay(100);
  center(0,0,0,0);
  left(1,0,0,255);
  delay(100);
  center(0,0,0,0);
  } 
  else {
    // turn LED off:
  center(0,0,0,0);
  delay(5000);
  }
/*
buttonLeft = digitalRead(leftTurn);<br>if (__ == __) {     
  //Center
  center(0,0,0,0);
  center(0,255,255,0);
  delay(100);
  center(0,255,225,0);
  delay(100);
  center(0,0,0,0);
*/
}
void left(uint16_t n, uint8_t r, uint8_t g, uint8_t b){
  for (n=0; n<10; n++) { // Specifies LEDs Range 0-10
    strip.setPixelColor(n, r, g, b);
    strip.show();
  }
}
void right(uint16_t n, uint8_t r, uint8_t g, uint8_t b){
  for (n=16; n<25; n++) { // Specifies LEDs Range 16-25
    strip.setPixelColor(n, r, g, b);
    strip.show();
  }
}
void center(uint16_t n, uint8_t r, uint8_t g, uint8_t b){
  for (n=0; n<25; n++) { // Specifies LEDs Range 0-25
    strip.setPixelColor(n, r, g, b);
    strip.show();
  }
}


Step 4: Use



Is a quick little snippet it what it looks like in action. Keep in mind this was for a proof of concept so some cables and connections may be shorter then you may want to make them.

Step 5: What's Next?

One of the reasons I was so enthusiastic about this project is because of it's potential to grow. I created a conceptual model for the purpose of the wheel well competition. However I'm ultimately more interested in where others will push this project. So hopefully this provided you with a good base to go create something more awesome.

Never stop making cool stuff.

"To invent, you need a good imagination and a pile of junk."
-Thomas Alva Edison