William SteversTaumer AnabtawiTiffany Tso
Published © GPL3+

The Wingman

When it comes to bicycle safety and theft-prevention, The Wingman has your back.

AdvancedFull instructions provided5,010

Things used in this project

Hardware components

MSP-EXP432P401R SimpleLink MSP432 LaunchPad
Texas Instruments MSP-EXP432P401R SimpleLink MSP432 LaunchPad
The Wingman MCU
×1
CC110L RF BoosterPack
Wireless Communication to Shirt (2 modules per kit)
×1
MPU6050
3-axis accelerometer/gyro, Motion Sensing and Crash Detection
×1
Adafruit FONA 808
GSM and GPS module
×1
GSM 2G SIM Card (Ting)
SIM for communicating with the Wingman
×1
Passive GPS Antenna uFL
FONA 808 GPS antenna
×1
Slim Sticker-type GSM/Cellular Antenna
FONA 808 GSM antenna
×1
Lithium Ion Polymer Battery - 3.7v 2500mAh
Main power supply (solar charged)
×1
USB / DC / Solar Lithium Ion/Polymer charger - v2
Solar charge regulator
×1
6V 2W Solar Panel
Solar panel
×1
2N3906 PNP Transistor
MPU6050 hard-reset
×1
Resistor 10k ohm
Resistor 10k ohm
MPU6050 hard-reset
×1
20-pin DIP Socket
CC110L RF BoosterPack stand-alone operation (SafeT)
×1
47K Ohm Resistor SMD
CC110L RF BoosterPack stand-alone operation (SafeT)
×1
1nF Capacitor SMD
CC110L RF BoosterPack stand-alone operation (SafeT)
×1
150 Ohm Resistor SMD
CC110L RF BoosterPack stand-alone operation (SafeT)
×1
Blue LED SMD
CC110L RF BoosterPack stand-alone operation (SafeT)
×1
0.1uF Capacitor SMD
CC110L RF BoosterPack stand-alone operation (SafeT) and 3.5 V regulation from Solar Panel Circuitry
×2
SMD Breakout Protoyping Board
3.5 V regulation from Solar Panel Circuitry
×1
TPS76801QD
3.5 V regulation from Solar Panel Circuitry
×1
250K Ohm Resistor SMD
3.5 V regulation from Solar Panel Circuitry
×1
100uF Capacitor SMD
3.5 V regulation from Solar Panel Circuitry
×1
60K Ohm Resistor
3.5 V regulation from Solar Panel Circuitry (voltage divider)
×1
30K Ohm Resistor
3.5 V regulation from Solar Panel Circuitry (voltage divider)
×1
MSP-EXP430G2 MSP430 LaunchPad
Texas Instruments MSP-EXP430G2 MSP430 LaunchPad
SafeT MCU (only use the actual IC, use the Launchpad to program)
×1
CSD18534KCS
NexFET MOSFET transistors, NPN (SafeT LED Driving)
×1
Fuel Tank BoosterPack
SafeT battery charging (not physically attached to the SafeT)
×1
LilyPad LED Yellow (5pcs each)
SafeT Amber LEDs
×7
LilyPad LED Red (5pcs each)
SafeT Red LEDs
×2
Proto Board
The Wingman base
×1
Female Headers
The Wingman base
×1
Male Headers
The Wingman base
×1
Jumper Cables
The Wingman base
×1
18 Gauge Speaker Wire
Shirt connections (strip wire, use as thread)
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
At least 40W recommended, use a conical or fine tip, May need a specialized setup for SMD components.
Hot-glue Gun
Useful for preventing shorts on the protoboard/SafT
Dremmel Multi-tool
Miscellaneous sanding/cutting (protoboard and female headers)
Needle Set
Sewing the SafeT

Story

Read more

Custom parts and enclosures

Wingman Baseboard

Our version. Designed to fit inside the bicycle bag seen in the videos.
Worked

Schematics

The Wingman Base Board

the Wingman is a modular system. A dual-sided protoboard acts as the base board, allowing for easy assembly and debugging. This schematic outlines which connections need to be made available for the appropriate hardware.

The Wingman 3.5 V Regulator

This is The Wingman's power source. Based on the TI TPS76801QD, this circuitry protects The Wingman from the solar charge controller. This is necessary because in direct sunlight, the solar panel can generate up to 6 V. This circuit produces a constant 3.5 V, perfect for our use.

The Wingman SafeT

This is the SafeT circuitry, built directly onto the Wireless Air Boosterpack prototyping area. It utilizes three TI N-channel MOSFETs to control the 44 LEDs via wireless communication from The Wingman.

Code

The Wingman Main Program

C/C++
This is the main program used to run the Wingman in its completed form. All libraries found in the embedded Git Repository are required for this code to work properly.
/*** FINAL UPDATE 7/23/15 ***/
/***   Taumer Anabtawi    ***/


#include <gsm.h>
#include "Motion.h"
#include <Wire.h>
#include <radio_sensor.h>

/***TRIGGER VARIABLES***/

boolean firstTimeTheft = true;
boolean firstTimeStop = true;
boolean LOCKED = true;
boolean crashed = false;

/***INFORMATION VARIABLES***/
int numberOfTexts = 0;

/***TIMER VARIABLES***/
long checkerForSMS = 10000; //check every 10 seconds for a text
long globalStartTime = 0;
long theftTime = 0;
long crashTime = 0;

/***DEVICE OBJECTS***/
Gsm gsm = Gsm();
motion accel = motion(); //MPU6050
Radio_Sensor radio = Radio_Sensor(); //C110L

void setup()
{
  accel.setupMPU6050();
  gsm.startGSM(9600);
  delay(5000);
  //Allow ample time for devices to startup
  
  //Start GSM text mode
  Serial.println("AT+CMGF=1");
  delay(1000);
  
  //Make initial read of stored text messages
  numberOfTexts = gsm.getNumSMS(); 
  
  theftTime = millis();
}


void loop()
{
  bool theft = false;
  if(LOCKED)
  {
    if(firstTimeTheft)
    {
      //Switch MPU modes to read for theft
      accel.runTheftSetup();
      firstTimeTheft = !firstTimeTheft;
      theftTime = millis();
     } 
     
   //Attempt to read a theft for 3 seconds every iteration  
   while(millis() - theftTime < 3000)
   {
     if(accel.motionDetected())
     {
       //A theft has occured if motion is sensed while the bike is LOCKED
       theft = true;
       break; 
     }
   }
   
   if(theft)
   {
      bool retrieved = false;
      digitalWrite(BLUE_LED,HIGH);
      gsm.startGPS();
      while(!retrieved)
      {
        gsm.pingGPSTheft(60000, masterPhoneNumber);
        digitalWrite(BLUE_LED,LOW);
      } 
    }
    else{
    
      //No theft detected at this time
      //digitalWrite(GREEN_LED,LOW);
      
      //Check for incoming text messages
      int numCheck = gsm.getNumSMS();
      if(numCheck > numberOfTexts)
      {
        //digitalWrite(BLUE_LED,HIGH);
        String ret = "";
        //If a text was received from the master phone number, unlock bike and initialize unlock mode
        ret = "LET'S RIDE";
        LOCKED = !LOCKED;
        firstTimeStop = true;
        
        //notify user
        gsm.sendSMS(ret,masterPhoneNumber);
        globalStartTime = millis(); 
      }
      //incase of non-unlocking text, allow for more theft reads
     theftTime = millis(); 
    }
  }
  
  if(!LOCKED)
  {  
    bool crashDetect = false;
    //digitalWrite(BLUE_LED,LOW);
    if(firstTimeStop)
    {
      firstTimeStop = !firstTimeStop; 
      
      //initialize for stop and go detection
      accel.runSafetySetup();
      
      crashTime = millis();
      globalStartTime = millis();

    }

    long stopTime = millis();
   
    //constantly poll for motion/stopping
    accel.checkForStop(); 

    //allow ample time for a crash reading
    crashTime = millis();
    while(millis() - crashTime < 1000)
    {
      if(accel.crashDetected())
      {
       crashDetect = true;
       break;
      }
      else
      {
        crashDetect = false;
      }  
    }

    if(crashDetect)
    {
       //when a crash occures, send out gps ping's to helper phone number
       digitalWrite(BLUE_LED,HIGH);
       gsm.startGPS();
       while(1)
       { 
            gsm.pingGPSCrash(60000,lovedOneNumber);
            digitalWrite(BLUE_LED,LOW);
            radio.sendMessage('H'); //send Hazard Light Signal
       } 
    }
    
    //grab a stop reading
    long stoppingTime = millis();
    bool stopGet = false;
    while(millis() - stoppingTime < 3000)
    {
       if(accel.stopDetected())
       {
         radio.sendMessage('B'); //send brake light message
         stopGet = true;
         break; 
       }
      
    }
    
    //ensure stop reading is a real stop reading by checking a stop for 15 seconds
    stoppingTime = millis();
    bool fullStop =false;
    while(stopGet && millis() - stoppingTime < 15000)
    {
       //can do because already stopped
       if(!accel.stopDetected())
       {
         fullStop = false; //false out 
         break;
       }
       else
       { 
         radio.sendMessage('B');
         fullStop = true;   
       }
         
     }
     
     //if a real stop (no more biking)
     if(fullStop)
     {
          //now check for an incoming LOCK text
          int numCheck = gsm.getNumSMS();
          if(numCheck > numberOfTexts)
          {
            String ret = "RIDE OVER";
            LOCKED = !LOCKED; 
            firstTimeTheft = true; //can now check for theft
            gsm.sendSMS(ret,masterPhoneNumber); 
           } 
    }
  }
}

The SafeT Main Program

C/C++
This is the main program used to run the SafeT. All libraries found in the embedded Git Repository are required for this code to work properly.
/*
 //    														  
 //	The Wingman SafeT 								      
 //													          
 // This code uses an MSP430 and 3 NexFET N-channel		      
 //	MOSFETs to drive 45 LEDs.  It recieves accelerometer      
 //	and GPS data from a MSP432 via the C110L wireless          
 //	boosterpack. 											  
 //															  
 //	From this data, the MCSP430 determines:					  
 //															  
 //	(1) When to activate the LEDs (time and location based).  
 //	(2) How fast they should strobe.						  
 //	(3) Which side should be brighter.						  
 //	(4) When to activate the brake lights.					  
 //														      
 //	Created by SpEcTrUm										  
 //  06/20/15											      
 
 CHANGE LOG:
 
 06/20/15 created file, began LED coding and layout -- Billy
 06/22/15 updated code, sampled "simultaneous" blinking of LEDs -- Billy
 06/25/15 improved readability
 
 */

#include <radio_receiver.h>


// Declerations

const int GATE_PIN_L = P1_2; // Yellow LEFT SIDE -- This port allows for PWM
const int GATE_PIN_R = P2_1; // Yellow RIGHT SIDE -- This port allows for PWM
const int GATE_PIN_RED = P1_4; // RED for Braking -- This port is DIGITAL ONLY

const int interval_strobe = 50; // "Short" strobes
const int interval_flash = 500; // "Long" flashes
const int burst_duration = 100; // How long LEDs are "ON"

const int buttonPin = PUSH2;

int strobe_state = LOW; // Used for state changes
int flash_state = LOW; // Used for state changes

int brightness = 100; // Sets normal brightness (100 out of 255)

unsigned long current_strobe = 0;
unsigned long previous_strobe = 0; // Allows for strobing without delay
unsigned long previous_flash = 0; // Allows for strobing without delay

int buttonState = LOW; // For DEBUGGING purposes only

Radio_Receiver radio = Radio_Receiver();

void setup()
{	
  pinMode(GATE_PIN_L, OUTPUT);
  pinMode(GATE_PIN_R, OUTPUT);
  pinMode(GATE_PIN_RED, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{	
  current_strobe = millis(); 
  SafeT_Flash();
  SafeT_Strobe();
  Let_There_Be_Light();
} 

void SafeT_Flash()
{
  if(flash_state == LOW)
  {
    if(current_strobe - previous_flash >= interval_flash)
    {
      flash_state = brightness;
      previous_flash += interval_flash;
    }
  }
  else {
    if(current_strobe - previous_flash >= burst_duration)
    {
      flash_state = LOW;
      previous_flash += burst_duration;
    }
  }
}

void SafeT_Strobe()
{
  if(strobe_state == LOW)
  {
    if(current_strobe - previous_strobe >= interval_strobe)
    {
      strobe_state = brightness;
      previous_strobe += interval_strobe;
    }
  }
  else {
    if(current_strobe - previous_strobe >= burst_duration)
    {
      strobe_state = LOW;
      previous_strobe += burst_duration;
    }
  }
}

void Let_There_Be_Light()
{
    //ensure this is always reset
    String switcher = "default";
    if(radio.ReceiveMessage(1000))
    {
      switcher = (char*)radio.messagePacket.message;
    }
  
    if(switcher == "B")
    {
      digitalWrite(GATE_PIN_RED, HIGH);
    }
    else if(switcher == "H")
    {
      digitalWrite(GATE_PIN_RED, LOW);
      analogWrite(GATE_PIN_L, strobe_state);
      analogWrite(GATE_PIN_R, strobe_state);
    }
    else
    {
      digitalWrite(GATE_PIN_RED, LOW);
      analogWrite(GATE_PIN_R, flash_state);
      analogWrite(GATE_PIN_R, flash_state);
    }
    
    //always have yellow lights doing some type of flash
    digitalWrite(GATE_PIN_R, HIGH);
    digitalWrite(GATE_PIN_L, HIGH);
}

Wingman Repo

Credits

William Stevers

William Stevers

1 project • 4 followers
Avid DIY Electronic Hobbyist, love creating Laser Harps. It's great to be a TIer!
Taumer Anabtawi

Taumer Anabtawi

1 project • 1 follower
Tiffany Tso

Tiffany Tso

1 project • 6 followers
- EE student at the University of Texas at Austin - Summer intern at Texas Instruments - Loves cats and memes

Comments