Difference between revisions of "Concussion Coach"

From ESE205 Wiki
Jump to navigation Jump to search
Line 78: Line 78:
  
 
<br />
 
<br />
<br /><br />
+
<br /><br /><br />
  
 +
===== Code =====
 +
/*
 +
RF ASK Tx and Rx Example
 +
Created in 2011 by NPoole @ SparkFun Electronics
 +
 +
modified 5 Feb 2015
 +
by Bobby Chan @ SparkFun Electronics
 +
*/
 +
// the rf code used here came from this
 +
 +
(#include <VirtualWire.h>)<br />
 +
 +
(#include <Wire.h>)<br />
 +
 +
 +
const int xInput = A0;<br />
 +
 +
const int yInput = A1;<br />
 +
 +
const int zInput = A2;<br />
 +
 +
int xRawMin = 509;<br />
 +
 +
int xRawMax = 514;<br />
 +
 +
int yRawMin = 509;<br />
 +
 +
int yRawMax = 514;<br />
 +
 +
int zRawMin = 507;<br />
 +
 +
int zRawMax = 513;<br />
 +
 +
float magnitude = 0;<br />
 +
 +
const int sampleSize = 10;<br />
 +
 +
const int sampleArraySize = 200;<br />
 +
 +
double sampleArray[sampleArraySize];<br />
 +
 +
 +
 +
 +
void setup()
 +
{
 +
  analogReference(EXTERNAL);
 +
  Serial.begin(9600);    // Debugging only
 +
  Serial.println("Initialize RF Link Tx Code");
 +
 +
  // Initialise the IO and ISR
 +
  vw_set_ptt_inverted(true); // Required for DR3100
 +
  vw_setup(2000);    // Bits per sec
 +
  vw_set_tx_pin(3);        //Pin 3 is connected to "Digital Output" of transmitter
 +
 +
  //Set pin for LED as status indicator
 +
  pinMode (13, OUTPUT);
 +
}
 +
 +
void loop()
 +
{
 +
  char *msg;
 +
  int xRaw = ReadAxis(xInput);
 +
  int yRaw = ReadAxis(yInput);
 +
  int zRaw = ReadAxis(zInput);
 +
  long xScaled = map(xRaw, xRawMin, xRawMax, -1000, 1000);
 +
  long yScaled = map(yRaw, yRawMin, yRawMax, -1000, 1000);
 +
  long zScaled = map(zRaw, zRawMin, zRawMax, -1000, 1000);
 +
  float xAccel = xScaled / 1000.0;
 +
  float yAccel = yScaled / 1000.0;
 +
  float zAccel = zScaled / 1000.0;
 +
 +
 +
 +
  magnitude = sqrt(sq(xAccel) + sq(yAccel) + sq(zAccel)); //calculates the force from accelerometer
 +
    char result[6];
 +
  if (magnitude > 25.0){  //force threshold
 +
    for(int i = 0; i < sampleArraySize; i++){                //fills up array with values of magnitude
 +
      magnitude = sqrt(sq(xAccel) + sq(yAccel) + sq(zAccel)); //right after detection above threshold
 +
      sampleArray[i] = magnitude;
 +
    }
 +
    for(int j = 0; j < sampleArraySize; j++){                //so that we can get a more accurate
 +
      if(sampleArray[j] < sampleArray[j-1]){                  //number for our force
 +
        magnitude = sampleArray[j-1];
 +
      }
 +
    }
 +
    magnitude=9000+magnitude;
 +
    dtostrf(magnitude, 6, 2, result);  //method for turning our double into a char
 +
    Serial.println("movement detected");
 +
    Serial.println(magnitude);
 +
    digitalWrite(13, true);  //Flash status LED to show transmitting
 +
    char *msg = result; //message to send
 +
    tx_debug(msg); //output message to serial monitor for debugging.
 +
    for (int i = 0; i < 3; i++){ // send 3 times to ensure message was sent
 +
    vw_send((uint8_t *)msg, strlen(msg));//send message
 +
    vw_wait_tx(); // Wait until the whole message is gone
 +
    }
 +
    digitalWrite(13, false); //Turn off status LED
 +
  }
 +
 +
 +
}
 +
 +
void tx_debug(char *temp_msg){
 +
  //output to serial monitor to indicate which button pressed
 +
  Serial.print("Movement detected");
 +
  Serial.println(temp_msg);
 +
}
 +
int ReadAxis(int axisPin) // method for accelerometer data
 +
{
 +
  long reading = 0;
 +
  analogRead(axisPin);
 +
  delay(1);
 +
  for (int i = 0; i < sampleSize; i++)
 +
  {
 +
    reading += analogRead(axisPin);
 +
  }
 +
  return reading/sampleSize;
 +
}
  
 
==== Coach's Pad ====
 
==== Coach's Pad ====

Revision as of 20:29, 5 December 2017

Link to weekly log

Overview

Concussions can have a severe and lasting impact on individual, and while coaches and athletes alike are aware of this danger, many concussions continue to go unrecognized. In football especially, concussions occur regularly due to the contact nature of the sport. While better protection and more careful playing an be used to prevent players from getting concussions, it is just as important to diagnose and treat concussions that do occur. Most concussions deliver ~95 g's to the body, so by measuring the amount of force applied to a player's head, the likelihood of a concussion could be monitored and the player could be checked when enough force was applied to cause a concussion.


Team Members

Colton Farley
Darby Hakken
Emma Zastrow
Nathan Schmetter (TA)

Objectives

A successful project will require:

1. Accelerometers be installed in a football helmet in a way that force can be detected in all directions

2. The encapsulation of the Arduino and any necessary battery packs and circuitry in the football helmet by creating a 3-D printed shell

3. Use an Arduino mini to detect forces capable of causing a concussion and transmitting the signal to an Arduino uno

4. Implementation of an LCD interface to transmit Arduino data from all players to coaches

Challenges

1. Being able to sense force equally throughout the helmet instead of distinct points where the accelerometer is located
2. Learning how to program an arduino and using it effectively
3. Learning how to use CAD and 3D print
4. Coding an interface to show an up to date status of the players helmets
5. Understanding radio frequencies and learning how to implement them
5. Communication between arduinos

Gantt Chart

ConcussionCoachGantt3.png

Budget


Shipping:

  • adafruit (LCD screen, aruino pro mini, and accelerometer) - $7.17
  • Sparkfun (RF module transmitter and receiver) - $5.74


Total:
$82.29

Design and Solutions

Circuitry and Code

Football Helmet

The football helmet is designed to detect any force applied to the payer's head. An initial concern was being able to detect force in all directions and in all locations of the helmet. However, we realized that our accelerometer was three dimensional so it is able to pick up force in any direction, and since the helmet is a solid body, it should not matter where the hit is with respect to the accelerometer. The technology for the football helmet consists of an arduino uno, triple axis accelerometer, and RF 434 MHz transmitter.

  • We downloaded the virtualwire library ([1]). We then set up the circuit using the diagrams that are located under the product page under documents and product page.
  • We used the example for the virtualwire library to make sure that our RF transmitter was working with our RF receiver.
  • COLTON TALK ABOUT SETTING UP THE ACCELEROMETER
  • We attached the accelerometer and RF transmitter to the same arduino to send the magnitue of the force detected by the accelerometer to the coach's pad arduino.
  • We set a threshold to be adjusted that will determine when a force will be transmitted, i.e., only a force above the threshold will be transmitted.
  • We played around with the sampling rate until we felt that the accelerometer was accurately detecting the force applied.
  • When everything was working, we attached a 9V battery to the arduino so that it could be powered without being attached to a computer.
Helmet Circuit
















Code

/*

RF ASK Tx and Rx Example
Created in 2011 by NPoole @ SparkFun Electronics 

modified 5 Feb 2015
by Bobby Chan @ SparkFun Electronics 
*/
// the rf code used here came from this

(#include <VirtualWire.h>)

(#include <Wire.h>)


const int xInput = A0;

const int yInput = A1;

const int zInput = A2;

int xRawMin = 509;

int xRawMax = 514;

int yRawMin = 509;

int yRawMax = 514;

int zRawMin = 507;

int zRawMax = 513;

float magnitude = 0;

const int sampleSize = 10;

const int sampleArraySize = 200;

double sampleArray[sampleArraySize];



void setup() {

 analogReference(EXTERNAL);
 Serial.begin(9600);    // Debugging only
 Serial.println("Initialize RF Link Tx Code");
 // Initialise the IO and ISR
 vw_set_ptt_inverted(true); // Required for DR3100
 vw_setup(2000);     // Bits per sec
 vw_set_tx_pin(3);         //Pin 3 is connected to "Digital Output" of transmitter
 //Set pin for LED as status indicator
 pinMode (13, OUTPUT);

}

void loop() {

 char *msg;
 int xRaw = ReadAxis(xInput);
 int yRaw = ReadAxis(yInput);
 int zRaw = ReadAxis(zInput);
 long xScaled = map(xRaw, xRawMin, xRawMax, -1000, 1000);
 long yScaled = map(yRaw, yRawMin, yRawMax, -1000, 1000);
 long zScaled = map(zRaw, zRawMin, zRawMax, -1000, 1000);
 float xAccel = xScaled / 1000.0;
 float yAccel = yScaled / 1000.0;
 float zAccel = zScaled / 1000.0;


 magnitude = sqrt(sq(xAccel) + sq(yAccel) + sq(zAccel)); //calculates the force from accelerometer
   char result[6];
 if (magnitude > 25.0){  //force threshold
   for(int i = 0; i < sampleArraySize; i++){                 //fills up array with values of magnitude
     magnitude = sqrt(sq(xAccel) + sq(yAccel) + sq(zAccel)); //right after detection above threshold
     sampleArray[i] = magnitude; 
   }
   for(int j = 0; j < sampleArraySize; j++){                 //so that we can get a more accurate
     if(sampleArray[j] < sampleArray[j-1]){                  //number for our force
       magnitude = sampleArray[j-1];
     }
   }
   magnitude=9000+magnitude;
   dtostrf(magnitude, 6, 2, result);  //method for turning our double into a char
   Serial.println("movement detected");
   Serial.println(magnitude);
   digitalWrite(13, true);  //Flash status LED to show transmitting
   char *msg = result; //message to send
   tx_debug(msg); //output message to serial monitor for debugging.
   for (int i = 0; i < 3; i++){ // send 3 times to ensure message was sent
   vw_send((uint8_t *)msg, strlen(msg));//send message
   vw_wait_tx(); // Wait until the whole message is gone
   }
   digitalWrite(13, false); //Turn off status LED
 }


}

void tx_debug(char *temp_msg){

 //output to serial monitor to indicate which button pressed
 Serial.print("Movement detected");
 Serial.println(temp_msg);

} int ReadAxis(int axisPin) // method for accelerometer data {

 long reading = 0;
 analogRead(axisPin);
 delay(1);
 for (int i = 0; i < sampleSize; i++)
 {
   reading += analogRead(axisPin);
 }
 return reading/sampleSize;

}

Coach's Pad

The Coach's pad is meant to be kept on the sidelines so that the coach can see the force inflicted on a player. The will allow the coach to determine when a player should be pulled out of the game instead of it being up to the player to know when it is serious. This information will hopefully decrease the number of concussions that go unreported, The coach's pad consists of a 20x4 LCD screen, arduino uno and 434 MHz RF receiver.

  • We used the liquid crystal library ([2]) for the lcd and the basic set up for the LCD was found at [3].
  • At one point in the project we had problems with the text on the LCD being clear, and the potentiometer was not really helping with the clarity of the screen. We found that using a stronger resistor yielded the results that we wanted. Since the resistors in the lab were not labeled, it was trial and error to find a resistor that worked well.
  • We used the hello world example to get used to the LCD screen and the liquid crystal library.
  • The RF receiver was set up using the diagram from [4].
  • We initially just printed the message received, which was simply the force. We then added in a message to make it more user friendly. The message was added on the receiver end for simplicity since there was only one player in our set up. However, for a whole team, the message would be added onto the transmitter side to distinguish the player number. This would not be difficult since the message can be sent as a string with the whole message including the player number and force magnitude.
  • When everything was working, we attached a 9V battery to the arduino so that it could be powered without being attached to a computer.
Coach's Pad Circuit











Code

(#include <LiquidCrystal.h>)

(#include <VirtualWire.h>)

//initialize the library with the numbers of the interface pins

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int receive_pin = 8;


void setup() {

 // set up the LCD's number of columns and rows: 
 lcd.begin(20, 4);
 // Print a message to the LCD.
 Serial.begin(9600);
 Serial.print("start");
 lcd.print("ready");
 vw_set_rx_pin(receive_pin);
 vw_set_ptt_inverted(true);
 vw_setup(2000);   // Bits per sec
 vw_rx_start();
 

}

void loop() {

 delay(100);
 uint8_t buf[VW_MAX_MESSAGE_LEN];
 uint8_t buflen = VW_MAX_MESSAGE_LEN;

if(buf[0]=9){

  if (vw_get_message(buf, &buflen)) {
   lcd.clear();
   lcd.print("Player 84 was hit");
   lcd.setCursor(0,1);
   lcd.print("force: ");
   int i;
   for (i = 1; i < buflen; i++){
     lcd.print((char)buf[i]);
  }
  lcd.print(" g's");
  }}

}

3D Designs

Coach's Pad Shell Design

First Design

  • Our first design for the shell for the coach was designed to hold the Arduino Uno and a 20x4 LCD screen, as well as a perfboard. We planned to keep it closed by using a snap close with four poles going through the four corner holes of the LCD screen. The poles are designed to then fit into the larger cylinders attached to the bottom of the enclosure.

Second Design

  • The second design accounted for the space needed for the 9V battery that would be needed to power the Arduino on demo day. Therefore, there was space added to the shell to account for this. The four pole snap system is still used. We realized that the poles that would slide through the LCD screen were the weakest part of the design, so we made them a lot shorter and the cylinders that they snapped into were extended to be much taller. There were also supports added to the cylinder supports to make it more stable.

Third Design

  • After soldering everything to the perfboard, we realized that we needed to change our shell design. Because of the way that the perfboard was attached to the LCD screen, the design was extended a lot below the LCD screen. The four pole snap system was no longer able to be used, so instead we made four holes in each corner of the shell for metal rods to go through and then screws to be fastened on to keep the box closed. This was our final design that we printed and used for our demo.

Helmet Shell Design

First Design

  • The first design was modeled to hold an Arduino Mini, a perfboard, and a 9V battery. There are four holes at each corner of the shell for metal rods to go through and then screws to be fastened to keep the box closed.

Second Design

  • Our second and final design was enlarged because we were no longer using the Arduino Mini, but rather using the Arduino Uno. The four hole pole system for closure was still being used. We also added a hole in one of the sides for the wires to go from the Arduino to the accelerometer in the helmet. This was our final design that we printed and used for our demo.


Results and Improvements

Overall our project was very successful and most of our objectives were achieved. Those that were not completely achieved were do to changes in our design, that we made while working on the project.
(1) We were able to install the accelerometer to detect forces in all directions because we used an accelerometer with three dimensions.
(2) The arduino and everything for the helmet fit into a shell, however it was not inside of the helmet because we realized that with the helmet we had we could not fit it inside of the helmet. This was do to the fact that we couldn't modify the actual shape of the helmet, so we were working with the helmet that we had and not designing a helmet to fit the materials. Instead, the shell was attached to the helmet and could easily be placed in shoulder pads.
(3) We used an arduino uno instead of a mini because we did not have as much of a size constriction since we decided to keep the parts outside of the helmet, therefore we used the arduino uno to simplify the process since the arduino mini was being finicky and we didn't want to risk anything on demo day. However, the arduino uno was successful at determining the force and transmitting it above a set threshold.
(4) The LCD effectively displayed the force a player was hit with.

Alterations and Improvements

Some critical decisions that we had to make were based upon time, design, and lack of equipment. We originally set out to use an Arduino Mini so that the casing could be smaller to better replicate what our project would really use, but due to the Arduino Mini not functioning properly and timing, we ultimately had to switch to a more familiar Arduino Uno for demo day. For future renditions of our project, we would like to use the smallest microcontroller we could get to further minimize the casing. Because we only had one helmet and no shoulder pads, we couldn’t show our full project. With more helmets, we would be able to show which player was hit, but because we had one helmet, we could only demonstrate our project working on a singular helmet. With no shoulder pads, we couldn’t demonstrate where the Arduino sending the signal to the coach’s pad would fit. It would be in a small casing that fit in the back side of the pads where it would be unnoticeable to the player. But because we didn’t have shoulder pads, we decided to cover the wires and let the casing hang freely from the helmet. The many different 3D prints that we went through changed due to how we soldered the components of our project. Our final casing had a hole that would have the wiring fit through it in a nice compact way, but because we soldered the wires on before setting it inside the casing, we had to poke the wires out of the side of the case rather than through the hole that we made.

Demo Day

Detecting the magnitude of the force and sending it via radio frequency worked wonderfully. However, on demo day, another group was using the same radio frequency as us and our Arduino was picking up on it. Ourr initial solution was to remove the antenna we had on our receiver to limit the range of our receiver and prevent it from picking up the other group's signal. However, our LCD was still displaying the other group's information, so we asked Nathan for help. He made changes in our code so that once a signal was received that message would remain on the screen until the arduino was reset. This worked as long as the helmet was hit quickly after being hit, making it more difficult to demo but showing our signal. In a normal setting the arduino would not need to be reset in between hits, but the importance of having the function available led us to believe that adding a reset button would be a good addition to our project. However, on most football fields there aren't other projects demoing, so demo day provided a unique problem that would not exist the typical setting.

Poster

Ccposter.png












Important Links

3D Printed Designs
Find our different versions of our designs here