Angela ChangHoward EglowsteinBettinaBrad KoernerYolita Wildman Nugent
Published © MIT

Reactive Safety Vest

A solar-powered safety vest that senses sudden changes in light and sound, using nLiteN LEDs and haptics to respond to the environment.

AdvancedWork in progress6 hours1,430

Things used in this project

Hardware components

ASCA | Free Form module
ASCA | Free Form module
×4
nLITEn Stretchy Cable
nLITEn Tech nLITEn Stretchy Cable
×3
nLITEn Power Injector
nLITEn Tech nLITEn Power Injector
×1
WS2812 Addressable LED Strip
Digilent WS2812 Addressable LED Strip
×2
nLITEn Power Injector
nLITEn Tech nLITEn Power Injector
×1
nLiten Forward-Emitting 30 LED strip
nLITEn Tech nLiten Forward-Emitting 30 LED strip
×2
MSP-EXP430G2 MSP430 LaunchPad
Texas Instruments MSP-EXP430G2 MSP430 LaunchPad
×1
Linear Regulator (7805)
Linear Regulator (7805)
×1
420 ohm resistors
×2
light sensor
×1
pager motor
×1
small Li-Ion battery 1300 mAh
×1
mesh vest (storebought or homemade)
×1
Single Yarn power mesh for liner
×1
reflective tape
×1
#5 Molded plastic teeth zipper with webbing reinforcement for durability
×1
Recycled polyester thread
×1
Recycled bias tape for edge and seam finishing
×1

Software apps and online services

bekonix
Code Composer Studio
Texas Instruments Code Composer Studio

Hand tools and fabrication machines

Standard industrial straight stitch sewing machine with ball point needles
Scissors, Free Fall
Scissors, Free Fall

Story

Read more

Custom parts and enclosures

CLO3D pattern first pass

layout diagram

CLO3D Turntable Video

top layer

inner layer

CLO3D pattern

Front and Back View of Vest

Schematics

Schematic

Code

Light Sensing Light Up Circuit Code

C/C++
MSP430 code for sudden ambient light to trigger safety display on LED light strips
#include <msp430.h>
#include "ws2812.h"

#define ANALOG_LIGHT 1

int i = 0;
int room_brightness = 0;
int next_effect = 1;

void gradualFill(u_int n, u_char r, u_char g, u_char b);
int light_read(void);
void effect1(void);
void effect2(void);
void effect3(void);

int main(void) {
    WDTCTL = WDTPW + WDTHOLD;  // Stop WDT
    if (CALBC1_16MHZ==0xFF)    // If calibration constant erased
    {
        while(1);              // do not load, trap CPU!!
    }

    // configure clock to 16 MHz
    BCSCTL1 = CALBC1_16MHZ;    // DCO = 16 MHz
    DCOCTL = CALDCO_16MHZ;

#if ANALOG_LIGHT
    // Our light sensor is an analog input on P1.4. Set up that and P1.3 and P1.5 (pushbutton) as digital inputs
    P1DIR &= ~(BIT3+BIT5);     // make sure theyre inputs
    P1REN |= (BIT3+BIT5);           // select internal resistor for P1.3 and P1.5
    P1OUT |= (BIT3+BIT5);          // and make it a pullup

    //; A little setup for the ADC. We're reading on P1.5 and the max voltage we can distiguish is 1.65 volts
    ADC10CTL1 = INCH_4+ADC10DIV_3;          // mov.w   #INCH_4+ADC10DIV_3, &ADC10CTL1  ; Temp sensor ADC10CLK/4
                                            // and input channel 5
//    ADC10CTL0 = SREF_0+ADC10SHT_3+ADC10IE+ADC10ON+REFON;  // mov.w   #SREF_0+ADC10SHT_3+ADC10IE+ADC10ON+REFON, &ADC10CTL0
    ADC10CTL0 = SREF_0+ADC10SHT_3+ADC10ON+REFON;  // mov.w   #SREF_0+ADC10SHT_3+ADC10IE+ADC10ON+REFON, &ADC10CTL0
    P1SEL |= BIT5;                          // bis.b   #BIT5, &P1SEL       ; enable P1.5 to be analog input 5

#else
    // Our light sensor is a digital input on P1.4. Set up that and P1.3 and P1.5 (pushbutton) as inputs
    P1DIR &= ~(BIT3+BIT4+BIT5);     // make sure theyre inputs
    P1REN |= (BIT3+BIT5);           // select internal resistor for P1.3 and P1.5
    P1OUT |= (BIT3+BIT5);          // and make it a pullup
#endif

    // initialize LED strip
    initStrip();  // ***** HAVE YOU SET YOUR NUM_LEDS DEFINE IN WS2812.H? ******

    // set strip color red
    fillStrip(0xFF, 0x00, 0x00);

    // show the strip
    showStrip();

#if 0
    // gradually fill for ever and ever
    while (1) {
        gradualFill(NUM_LEDS, 0x00, 0xFF, 0x00);  // green
        gradualFill(NUM_LEDS, 0x00, 0x00, 0xFF);  // blue
        gradualFill(NUM_LEDS, 0xFF, 0x00, 0xFF);  // magenta
        gradualFill(NUM_LEDS, 0xFF, 0xFF, 0x00);  // yellow
        gradualFill(NUM_LEDS, 0x00, 0xFF, 0xFF);  // cyan
        gradualFill(NUM_LEDS, 0xFF, 0x00, 0x00);  // red
    }
#elif 1
#if ANALOG_LIGHT
    room_brightness = light_read();
#endif
    gradualFill(NUM_LEDS, 0x00, 0xFF, 0x00);  // green
#if ANALOG_LIGHT
    room_brightness += light_read();
#endif
    gradualFill(NUM_LEDS, 0x00, 0x00, 0xFF);  // blue
#if ANALOG_LIGHT
    room_brightness += light_read();
#endif
    gradualFill(NUM_LEDS, 0xFF, 0x00, 0xFF);  // magenta
#if ANALOG_LIGHT
    room_brightness += light_read();
#endif
    gradualFill(NUM_LEDS, 0xFF, 0xFF, 0x00);  // yellow
#if ANALOG_LIGHT
    room_brightness += light_read();
#endif
    gradualFill(NUM_LEDS, 0x00, 0xFF, 0xFF);  // cyan
#if ANALOG_LIGHT
    room_brightness += light_read();
#endif
    gradualFill(NUM_LEDS, 0xFF, 0x00, 0x00);  // red
#if ANALOG_LIGHT
    room_brightness += light_read();
#endif
    gradualFill(NUM_LEDS, 0x00, 0x00, 0x00);  // black
#if ANALOG_LIGHT
    room_brightness += light_read();
    room_brightness = room_brightness / 8;  // we took 8 readings. Divide by 8

    // we'll set the threshold to 95% of what we measured as the average
    room_brightness = room_brightness - (room_brightness / 20);  // subtract 5%
#endif

    while (1) { // main loop - do this forever
#if ANALOG_LIGHT
        while(light_read() > (room_brightness >> 1));
#else
        // wait for a light sensor trip
        while (BIT4 == (BIT4 & P1IN));
            //i = (BIT4 & P1IN);
#endif
        if (1 == next_effect)
            effect1();
        if (2 == next_effect)
            effect2();
        next_effect = next_effect + 1;
        if (next_effect > 2)
            next_effect = 1;
    }
#endif

}

void gradualFill(u_int n, u_char r, u_char g, u_char b){
    int i;
    for (i = 0; i < n; i++){        // n is number of LEDs
        setLEDColor(i, r, g, b);
        showStrip();
//        _delay_cycles(1000000);       // lazy delay
        _delay_cycles(250000);       // lazy delay
    }
}

// lower values mean more light
int light_read(void)
{
    int retval = 0;
    ADC10CTL0 |= 0x03;          // bis.w   #0x03, &ADC10CTL0       ; sampling and conversion start
    //; wait until the ADC is done
    //ML_2
    while (ADC10CTL1 & ADC10BUSY);      // bit.b   #ADC10BUSY, &ADC10CTL1
    retval = ADC10MEM;

    return retval;
}

void effect1(void)
{
    // Walk a red LED back and forth
    for (i=0; i<NUM_LEDS; i++)  // this is forth
    {
        if (i > 1)
            setLEDColor(i-2, 0x00, 0x00, 0x00);  // Go back two and turn off the lED
        if (i > 0)
            setLEDColor(i-1, 0x20, 0x00, 0x00);  // Go back one light half intensity
        setLEDColor(i, 0xFF, 0xFF, 0x00);  // Light our LED full intensity yellow
        if ((i+1) < NUM_LEDS)
            setLEDColor(i+1, 0x20, 0x00, 0x00);  // The one after our is half brightness
        showStrip();
        _delay_cycles(1000000);       // lazy delay
    }
    for (i=NUM_LEDS-1; i>=0; i--)  // this is back
    {
        if ((i+2) < NUM_LEDS)
            setLEDColor(i+2, 0x00, 0x00, 0x00);  // the one two behind us needs to go off
        if ((i+1) < NUM_LEDS)
            setLEDColor(i+1, 0x20, 0x00, 0x00);  // tthe one behind us needs to go to half brightness
        setLEDColor(i, 0xFF, 0xFF, 0x00);  // Light our LED full intensity yellow
        if (i > 0)
            setLEDColor(i-1, 0x20, 0x00, 0x00);  // The next one is half
        if (i > 1)
            setLEDColor(i-2, 0x00, 0x00, 0x00);  // go forward two and make sure it's off
        showStrip();
        _delay_cycles(1000000);       // lazy delay
    }
    // clear the strip
    fillStrip(0x00, 0x00, 0x00);
    // show the strip
    showStrip();
}

void effect2(void)
{
    int i;

    for (i=0; i<5; i++)
    {
        // set strip color yellow
        fillStrip(0xFF, 0xFF, 0x00);
        showStrip();
        _delay_cycles(1000000);       // lazy delay
        // set strip color black
        fillStrip(0x00, 0x00, 0x00);
        showStrip();
        _delay_cycles(1000000);       // lazy delay
        // set strip color red
        fillStrip(0xFF, 0x00, 0x00);
        showStrip();
        _delay_cycles(1000000);       // lazy delay
        // set strip color black
        fillStrip(0x00, 0x00, 0x00);
        showStrip();
        _delay_cycles(1000000);       // lazy delay
    }
}

Light Sensing Header File

C Header File
Setup and specifying the number of LEDs in the WS2812 light strips
// Configuration - SET THESE!
#define OUTPUT_PIN  (0x80)  // Set to whatever UCB0SIMO is on your processor (Px.7 here)
#define NUM_LEDS    (32)    // NUMBER OF LEDS IN YOUR STRIP

// Useful typedefs
typedef unsigned char u_char;	// 8 bit
typedef unsigned int u_int;     // 16 bit

// Transmit codes
#define HIGH_CODE   (0xF0)      // b11110000
#define LOW_CODE    (0xC0)      // b11000000

// Configure processor to output to data strip
void initStrip(void);

// Send colors to the strip and show them. Disables interrupts while processing.
void showStrip(void);

// Set the color of a certain LED
void setLEDColor(u_int p, u_char r, u_char g, u_char b);

// Clear the color of all LEDs (make them black/off)
void clearStrip(void);

// Fill the strip with a solid color. This will update the strip.
void fillStrip(u_char r, u_char g, u_char b);

Credits

Angela Chang

Angela Chang

1 project • 14 followers
Angela plays with electronic textiles. She previously designed a Luminous Firefly Dress. Homeschooling mom x creative technologist.
Howard Eglowstein

Howard Eglowstein

1 project • 3 followers
I am a recovering toy designer, and survived the home computer wars of the 1980s. I've been soldering and writing code for 40+ years.
Bettina

Bettina

1 project • 5 followers
Brad Koerner

Brad Koerner

0 projects • 3 followers
Brad Koerner is a creative director in lighting product development and immersive digital experiences for architectural environments.
Yolita Wildman Nugent

Yolita Wildman Nugent

0 projects • 4 followers
Passionate interdisciplinary leader merging R&D, and wearable technology with scaled production for over twenty years.
Thanks to Brooks and Beth Ahern.

Comments