Final Program for Cycle Fit Project, Program is able to collect, process and output via bluetooth values for: Pedal Speed (RPM) Heart Rate (BPM) and incline (degrees)

Dependencies:   FXAS21000 FXOS8700Q mbed

Committer:
roberthill04
Date:
Sun Apr 10 20:53:46 2016 +0000
Revision:
0:30fa229c34d6
Final Cycle Fit Program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
roberthill04 0:30fa229c34d6 1 #include "mbed.h"
roberthill04 0:30fa229c34d6 2 #include "FXOS8700Q.h" //Needed for Accelerometer
roberthill04 0:30fa229c34d6 3 #define PI 3.14159265
roberthill04 0:30fa229c34d6 4 #include "PulseSensor.h"
roberthill04 0:30fa229c34d6 5 #include "FXAS21000.h" //Needed for Gyroscope (If I add it)
roberthill04 0:30fa229c34d6 6
roberthill04 0:30fa229c34d6 7 DigitalOut gpo(D0);
roberthill04 0:30fa229c34d6 8 DigitalOut led_red(LED_RED);
roberthill04 0:30fa229c34d6 9 DigitalOut led_green(LED_GREEN);
roberthill04 0:30fa229c34d6 10 DigitalOut led_blue(LED_BLUE);
roberthill04 0:30fa229c34d6 11 Serial pc(USBTX, USBRX);
roberthill04 0:30fa229c34d6 12 Serial blue(PTC17,PTC16);
roberthill04 0:30fa229c34d6 13
roberthill04 0:30fa229c34d6 14 int longTimer = 10;
roberthill04 0:30fa229c34d6 15 double shortTimer = 0.5;
roberthill04 0:30fa229c34d6 16
roberthill04 0:30fa229c34d6 17 //instantiating timers
roberthill04 0:30fa229c34d6 18 Timer time01;
roberthill04 0:30fa229c34d6 19 Timer time02;
roberthill04 0:30fa229c34d6 20
roberthill04 0:30fa229c34d6 21 //instantiating summation and counter variables
roberthill04 0:30fa229c34d6 22 int HR_Sum;
roberthill04 0:30fa229c34d6 23 int RPM_Sum;
roberthill04 0:30fa229c34d6 24 int Acc_Sum;
roberthill04 0:30fa229c34d6 25 int Acc_Count;
roberthill04 0:30fa229c34d6 26
roberthill04 0:30fa229c34d6 27 //instantiating averaging variables
roberthill04 0:30fa229c34d6 28 int avgRPM;
roberthill04 0:30fa229c34d6 29 int avgAcc;
roberthill04 0:30fa229c34d6 30 int avgHR;
roberthill04 0:30fa229c34d6 31
roberthill04 0:30fa229c34d6 32 //variables needed for processing
roberthill04 0:30fa229c34d6 33 ////////////////////////////////////////Heart Rate////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 34 AnalogIn Pulse_Signal(A0); //Initialize analog input for pulse signal(Heart Rate sensor)
roberthill04 0:30fa229c34d6 35 int Pulse_Count=0;
roberthill04 0:30fa229c34d6 36 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 37
roberthill04 0:30fa229c34d6 38 ///////////////////////////////////////Pedal Speed///////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 39 DigitalIn HallEffect(D2); //Intializes Digital input into pin D2 (Hall Effect sensor)
roberthill04 0:30fa229c34d6 40 int Hall_Counter = 0; //Initialize Counter for Hall Effect
roberthill04 0:30fa229c34d6 41 bool Low_Hall = true; //Initialize Flag for Hall Effect sensor
roberthill04 0:30fa229c34d6 42 bool Button_Pressed = true; //Initialize flag for output on terminal
roberthill04 0:30fa229c34d6 43 Timer Hall_Timer; //Initialize timer for pedal speed calc
roberthill04 0:30fa229c34d6 44 int Pedal_Time; //Intialize int for Time Passed
roberthill04 0:30fa229c34d6 45 int Pedal_Speed; //Initialize int for Pedal Speed
roberthill04 0:30fa229c34d6 46 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 47
roberthill04 0:30fa229c34d6 48 ///////////////////////////////////////Incline////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 49 I2C i2c(PTE25, PTE24); //Initialize I2C connection for sensor
roberthill04 0:30fa229c34d6 50 FXOS8700QAccelerometer acc(i2c, FXOS8700CQ_SLAVE_ADDR1); // Configured for the FRDM-K64F with onboard sensors
roberthill04 0:30fa229c34d6 51 FXAS21000 gyro(D14, D15);
roberthill04 0:30fa229c34d6 52 double angleX, denomX_T, denomX_A, denomX_B, denomX_C; //intializing variable to hold the angle calculation
roberthill04 0:30fa229c34d6 53 double angleY, denomY_T, denomY_A, denomY_B, denomY_C; //and denominator pieces of algorithm for both X&Y axis
roberthill04 0:30fa229c34d6 54 float faX, faY, faZ; //intialize float variables for incoming raw sensor values
roberthill04 0:30fa229c34d6 55 double Start_Angle; //Used for intial calibration to find an offset
roberthill04 0:30fa229c34d6 56 double Acc_Angle; //Eq: Angle Experienced - Start_Angle = Actual Angle seen by bike
roberthill04 0:30fa229c34d6 57
roberthill04 0:30fa229c34d6 58 int drift_counter=0;
roberthill04 0:30fa229c34d6 59 double gyro_reset=0;
roberthill04 0:30fa229c34d6 60 double gyro_drift_degree = 0;
roberthill04 0:30fa229c34d6 61 double gyro_drift_angle = 0;
roberthill04 0:30fa229c34d6 62 double gyro_data[3];
roberthill04 0:30fa229c34d6 63 double gyro_angle = 0; //always intilize
roberthill04 0:30fa229c34d6 64 double gyro_degree = 0;
roberthill04 0:30fa229c34d6 65 double gyro_drift =0;
roberthill04 0:30fa229c34d6 66 int gyro_read_time;
roberthill04 0:30fa229c34d6 67
roberthill04 0:30fa229c34d6 68 double Filter_Angle=0;
roberthill04 0:30fa229c34d6 69 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 70
roberthill04 0:30fa229c34d6 71 //////////////////////////////////////////Sensor Processing////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 72
roberthill04 0:30fa229c34d6 73 //////////////////////////////////////Heart Rate Processing/////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 74 PulseSensor::PulseSensor(PinName analogPin, void (*printDataCallback)(char,int), int callbackRateMs)
roberthill04 0:30fa229c34d6 75 {
roberthill04 0:30fa229c34d6 76 _started = false;
roberthill04 0:30fa229c34d6 77
roberthill04 0:30fa229c34d6 78 _pAin = new AnalogIn(analogPin);
roberthill04 0:30fa229c34d6 79
roberthill04 0:30fa229c34d6 80 _callbackRateMs = callbackRateMs;
roberthill04 0:30fa229c34d6 81
roberthill04 0:30fa229c34d6 82 _printDataCallback = printDataCallback;
roberthill04 0:30fa229c34d6 83 }
roberthill04 0:30fa229c34d6 84
roberthill04 0:30fa229c34d6 85
roberthill04 0:30fa229c34d6 86 PulseSensor::~PulseSensor()
roberthill04 0:30fa229c34d6 87 {
roberthill04 0:30fa229c34d6 88 delete _pAin;
roberthill04 0:30fa229c34d6 89 }
roberthill04 0:30fa229c34d6 90
roberthill04 0:30fa229c34d6 91
roberthill04 0:30fa229c34d6 92 void PulseSensor::process_data_ticker_callback(void)
roberthill04 0:30fa229c34d6 93 {
roberthill04 0:30fa229c34d6 94 // _printDataCallback('S', Signal); // send Processing the raw Pulse Sensor data ** Commented out so it doens't stream data
roberthill04 0:30fa229c34d6 95 if (QS == true) { // Quantified Self flag is true when a heartbeat is found
roberthill04 0:30fa229c34d6 96
roberthill04 0:30fa229c34d6 97 //_printDataCallback('B',BPM); // send heart rate with a 'B' prefix **Commented out so it doens't stream data
roberthill04 0:30fa229c34d6 98 //_printDataCallback('Q',IBI); // send time between beats with a 'Q' prefix **Commented out so it doens't stream data
roberthill04 0:30fa229c34d6 99 QS = false; // reset the Quantified Self flag for next time
roberthill04 0:30fa229c34d6 100 }
roberthill04 0:30fa229c34d6 101 }
roberthill04 0:30fa229c34d6 102
roberthill04 0:30fa229c34d6 103
roberthill04 0:30fa229c34d6 104 void PulseSensor::sensor_ticker_callback(void)
roberthill04 0:30fa229c34d6 105 {
roberthill04 0:30fa229c34d6 106 Signal = 1023 * _pAin->read(); // read the Pulse Sensor
roberthill04 0:30fa229c34d6 107
roberthill04 0:30fa229c34d6 108
roberthill04 0:30fa229c34d6 109 sampleCounter += 2; // keep track of the time in mS with this variable
roberthill04 0:30fa229c34d6 110 int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise
roberthill04 0:30fa229c34d6 111
roberthill04 0:30fa229c34d6 112 // find the peak and trough of the pulse wave
roberthill04 0:30fa229c34d6 113 if(Signal < thresh && N > (IBI/5)*3) { // avoid dichrotic noise by waiting 3/5 of last IBI
roberthill04 0:30fa229c34d6 114 if (Signal < T) { // T is the trough
roberthill04 0:30fa229c34d6 115 T = Signal; // keep track of lowest point in pulse wave
roberthill04 0:30fa229c34d6 116 }
roberthill04 0:30fa229c34d6 117 }
roberthill04 0:30fa229c34d6 118
roberthill04 0:30fa229c34d6 119 if(Signal > thresh && Signal > P) { // thresh condition helps avoid noise
roberthill04 0:30fa229c34d6 120 P = Signal; // P is the peak
roberthill04 0:30fa229c34d6 121 } // keep track of highest point in pulse wave
roberthill04 0:30fa229c34d6 122
roberthill04 0:30fa229c34d6 123 // NOW IT'S TIME TO LOOK FOR THE HEART BEAT
roberthill04 0:30fa229c34d6 124 // signal surges up in value every time there is a pulse
roberthill04 0:30fa229c34d6 125 if (N > 250) { // avoid high frequency noise by waiting
roberthill04 0:30fa229c34d6 126 //this also sets limit to HR sensor to max =240 BPMs
roberthill04 0:30fa229c34d6 127
roberthill04 0:30fa229c34d6 128 if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) {
roberthill04 0:30fa229c34d6 129 Pulse = true; // set the Pulse flag when we think there is a pulse
roberthill04 0:30fa229c34d6 130 Pulse_Count++; //This should count every time there is a pulse ** value needed for loops below
roberthill04 0:30fa229c34d6 131 IBI = sampleCounter - lastBeatTime; // measure time between beats in mS
roberthill04 0:30fa229c34d6 132 lastBeatTime = sampleCounter; // keep track of time for next pulse
roberthill04 0:30fa229c34d6 133
roberthill04 0:30fa229c34d6 134 if(firstBeat) { // if it's the first time we found a beat, if firstBeat == TRUE
roberthill04 0:30fa229c34d6 135 firstBeat = false; // clear firstBeat flag
roberthill04 0:30fa229c34d6 136 return; // IBI value is unreliable so discard it
roberthill04 0:30fa229c34d6 137 }
roberthill04 0:30fa229c34d6 138 if(secondBeat) { // if this is the second beat, if secondBeat == TRUE
roberthill04 0:30fa229c34d6 139 secondBeat = false; // clear secondBeat flag
roberthill04 0:30fa229c34d6 140 for(int i=0; i<=9; i++) { // seed the running total to get a realisitic BPM at startup
roberthill04 0:30fa229c34d6 141 rate[i] = IBI;
roberthill04 0:30fa229c34d6 142 }
roberthill04 0:30fa229c34d6 143 }
roberthill04 0:30fa229c34d6 144
roberthill04 0:30fa229c34d6 145 // keep a running total of the last 10 IBI values
roberthill04 0:30fa229c34d6 146 long runningTotal = 0; // clear the runningTotal variable
roberthill04 0:30fa229c34d6 147
roberthill04 0:30fa229c34d6 148 for(int i=0; i<=8; i++) { // shift data in the rate array
roberthill04 0:30fa229c34d6 149 rate[i] = rate[i+1]; // and drop the oldest IBI value
roberthill04 0:30fa229c34d6 150 runningTotal += rate[i]; // add up the 9 oldest IBI values
roberthill04 0:30fa229c34d6 151 }
roberthill04 0:30fa229c34d6 152
roberthill04 0:30fa229c34d6 153 rate[9] = IBI; // add the latest IBI to the rate array
roberthill04 0:30fa229c34d6 154 runningTotal += rate[9]; // add the latest IBI to runningTotal
roberthill04 0:30fa229c34d6 155 runningTotal /= 10; // average the last 10 IBI values
roberthill04 0:30fa229c34d6 156 BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM!
roberthill04 0:30fa229c34d6 157 QS = true; // set Quantified Self flag
roberthill04 0:30fa229c34d6 158 // QS FLAG IS NOT CLEARED INSIDE THIS ISR
roberthill04 0:30fa229c34d6 159 }
roberthill04 0:30fa229c34d6 160 }
roberthill04 0:30fa229c34d6 161
roberthill04 0:30fa229c34d6 162 if (Signal < thresh && Pulse == true) { // when the values are going down, the beat is over
roberthill04 0:30fa229c34d6 163 Pulse = false; // reset the Pulse flag so we can do it again
roberthill04 0:30fa229c34d6 164 amp = P - T; // get amplitude of the pulse wave
roberthill04 0:30fa229c34d6 165 thresh = amp/2 + T; // set thresh at 50% of the amplitude
roberthill04 0:30fa229c34d6 166 P = thresh; // reset these for next time
roberthill04 0:30fa229c34d6 167 T = thresh;
roberthill04 0:30fa229c34d6 168 }
roberthill04 0:30fa229c34d6 169
roberthill04 0:30fa229c34d6 170 if (N > 2500) { // if 2.5 seconds go by without a beat
roberthill04 0:30fa229c34d6 171 thresh = 512; // set thresh default
roberthill04 0:30fa229c34d6 172 P = 512; // set P default
roberthill04 0:30fa229c34d6 173 T = 512; // set T default
roberthill04 0:30fa229c34d6 174 lastBeatTime = sampleCounter; // bring the lastBeatTime up to date
roberthill04 0:30fa229c34d6 175 firstBeat = true; // set these to avoid noise
roberthill04 0:30fa229c34d6 176 secondBeat = true; // when we get the heartbeat back
roberthill04 0:30fa229c34d6 177 }
roberthill04 0:30fa229c34d6 178 }
roberthill04 0:30fa229c34d6 179
roberthill04 0:30fa229c34d6 180 void sendDataToProcessing(char symbol, int data)
roberthill04 0:30fa229c34d6 181 {
roberthill04 0:30fa229c34d6 182 pc.printf("%c%d\t\r\n", symbol, data);
roberthill04 0:30fa229c34d6 183 }
roberthill04 0:30fa229c34d6 184
roberthill04 0:30fa229c34d6 185 bool PulseSensor::start()
roberthill04 0:30fa229c34d6 186 {
roberthill04 0:30fa229c34d6 187 if (_started == false)
roberthill04 0:30fa229c34d6 188 {
roberthill04 0:30fa229c34d6 189 sampleCounter = 0;
roberthill04 0:30fa229c34d6 190 lastBeatTime = 0;
roberthill04 0:30fa229c34d6 191 P =512;
roberthill04 0:30fa229c34d6 192 T = 512;
roberthill04 0:30fa229c34d6 193 thresh = 512;
roberthill04 0:30fa229c34d6 194 amp = 100;
roberthill04 0:30fa229c34d6 195 firstBeat = true;
roberthill04 0:30fa229c34d6 196 secondBeat = true;
roberthill04 0:30fa229c34d6 197
roberthill04 0:30fa229c34d6 198 BPM=0;
roberthill04 0:30fa229c34d6 199 Signal=0;
roberthill04 0:30fa229c34d6 200 IBI = 600;
roberthill04 0:30fa229c34d6 201 Pulse = false;
roberthill04 0:30fa229c34d6 202 QS = false;
roberthill04 0:30fa229c34d6 203
roberthill04 0:30fa229c34d6 204 _pulseSensorTicker.attach(this, &PulseSensor::sensor_ticker_callback, ((float)_sensorTickRateMs/1000));
roberthill04 0:30fa229c34d6 205 _processDataTicker.attach(this, &PulseSensor::process_data_ticker_callback, ((float)_callbackRateMs/1000));
roberthill04 0:30fa229c34d6 206 _started = true;
roberthill04 0:30fa229c34d6 207 return true;
roberthill04 0:30fa229c34d6 208 }
roberthill04 0:30fa229c34d6 209 else
roberthill04 0:30fa229c34d6 210 {
roberthill04 0:30fa229c34d6 211 return false;
roberthill04 0:30fa229c34d6 212 }
roberthill04 0:30fa229c34d6 213 }
roberthill04 0:30fa229c34d6 214
roberthill04 0:30fa229c34d6 215 bool PulseSensor::stop()
roberthill04 0:30fa229c34d6 216 {
roberthill04 0:30fa229c34d6 217 if(_started == true)
roberthill04 0:30fa229c34d6 218 {
roberthill04 0:30fa229c34d6 219 _pulseSensorTicker.detach();
roberthill04 0:30fa229c34d6 220 _processDataTicker.detach();
roberthill04 0:30fa229c34d6 221 _started = false;
roberthill04 0:30fa229c34d6 222 return true;
roberthill04 0:30fa229c34d6 223 }
roberthill04 0:30fa229c34d6 224 else
roberthill04 0:30fa229c34d6 225 {
roberthill04 0:30fa229c34d6 226 return false;
roberthill04 0:30fa229c34d6 227 }
roberthill04 0:30fa229c34d6 228 }
roberthill04 0:30fa229c34d6 229 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 230
roberthill04 0:30fa229c34d6 231
roberthill04 0:30fa229c34d6 232 ///////////////////////////////////Pedal Speed Processing//////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 233 void RPM (void)
roberthill04 0:30fa229c34d6 234 {
roberthill04 0:30fa229c34d6 235 Hall_Counter=0; //resets so it adds either a 0 or 1 for the RPM_Sum counter
roberthill04 0:30fa229c34d6 236 Button_Pressed = true;
roberthill04 0:30fa229c34d6 237
roberthill04 0:30fa229c34d6 238 if(HallEffect==0 && Low_Hall==true) { //If Hall Effect Digital Output is low
roberthill04 0:30fa229c34d6 239 Hall_Counter++; //Add one to counter for calc pedal speed
roberthill04 0:30fa229c34d6 240 led_green = 0; //Output Green on LED, simulates wheel rotation "sensed"
roberthill04 0:30fa229c34d6 241 led_red = 1;
roberthill04 0:30fa229c34d6 242 led_blue = 1;
roberthill04 0:30fa229c34d6 243 Low_Hall = false; //flag to avoid errors
roberthill04 0:30fa229c34d6 244 }
roberthill04 0:30fa229c34d6 245
roberthill04 0:30fa229c34d6 246 else if(HallEffect==1 && Low_Hall==true){ //Additional logic for accurate readings
roberthill04 0:30fa229c34d6 247 led_green = 1;
roberthill04 0:30fa229c34d6 248 led_red = 0; //Stays red while hall effect outputs digital high
roberthill04 0:30fa229c34d6 249 led_blue = 1;
roberthill04 0:30fa229c34d6 250 }
roberthill04 0:30fa229c34d6 251 else if(HallEffect==0 && Low_Hall==false){
roberthill04 0:30fa229c34d6 252 led_green = 0;
roberthill04 0:30fa229c34d6 253 led_red = 1;
roberthill04 0:30fa229c34d6 254 led_blue = 1;
roberthill04 0:30fa229c34d6 255
roberthill04 0:30fa229c34d6 256 }
roberthill04 0:30fa229c34d6 257 else if(HallEffect==1 && Low_Hall==false){
roberthill04 0:30fa229c34d6 258 led_green = 1;
roberthill04 0:30fa229c34d6 259 led_red = 0;
roberthill04 0:30fa229c34d6 260 led_blue = 1;
roberthill04 0:30fa229c34d6 261 Low_Hall = true;
roberthill04 0:30fa229c34d6 262 }
roberthill04 0:30fa229c34d6 263 // Hall_Active=0;
roberthill04 0:30fa229c34d6 264 wait(0.05);
roberthill04 0:30fa229c34d6 265 }
roberthill04 0:30fa229c34d6 266 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 267
roberthill04 0:30fa229c34d6 268 /////////////////////////////////////Incline Processing/////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 269 void Acc(void)
roberthill04 0:30fa229c34d6 270 {
roberthill04 0:30fa229c34d6 271 acc.getX(faX); //get raw accelerometer data in the X axis
roberthill04 0:30fa229c34d6 272 acc.getY(faY); //"" Y axis
roberthill04 0:30fa229c34d6 273 acc.getZ(faZ); //"" Z axis
roberthill04 0:30fa229c34d6 274 denomY_A = pow(faX, 2);
roberthill04 0:30fa229c34d6 275 denomY_B = pow(faZ, 2);
roberthill04 0:30fa229c34d6 276 denomY_C = denomY_A + denomY_B;
roberthill04 0:30fa229c34d6 277 denomY_T = pow(denomY_C, .5); //pow returns base raised to the power exponent
roberthill04 0:30fa229c34d6 278
roberthill04 0:30fa229c34d6 279 angleY = atan(faY/denomY_T) * 180/PI; //should calculate the angle on the Y axis in degrees based on raw data
roberthill04 0:30fa229c34d6 280 Acc_Angle= angleY - Start_Angle;
roberthill04 0:30fa229c34d6 281 }
roberthill04 0:30fa229c34d6 282
roberthill04 0:30fa229c34d6 283 void Offset_Calc(void) //Function for angle calc upon startup
roberthill04 0:30fa229c34d6 284 {
roberthill04 0:30fa229c34d6 285 acc.getX(faX); //get raw accelerometer data in the X axis
roberthill04 0:30fa229c34d6 286 acc.getY(faY); //"" Y axis
roberthill04 0:30fa229c34d6 287 acc.getZ(faZ);
roberthill04 0:30fa229c34d6 288 denomY_A = pow(faX, 2);
roberthill04 0:30fa229c34d6 289 denomY_B = pow(faZ, 2);
roberthill04 0:30fa229c34d6 290 denomY_C = denomY_A + denomY_B;
roberthill04 0:30fa229c34d6 291 denomY_T = pow(denomY_C, .5); //pow returns base raised to the power exponent
roberthill04 0:30fa229c34d6 292
roberthill04 0:30fa229c34d6 293 Start_Angle = atan(faY/denomY_T) * 180/PI; //Stores intial angle value for offset calculation
roberthill04 0:30fa229c34d6 294
roberthill04 0:30fa229c34d6 295 }
roberthill04 0:30fa229c34d6 296 void Gyro(void)
roberthill04 0:30fa229c34d6 297 {
roberthill04 0:30fa229c34d6 298 gyro.ReadXYZ(gyro_data); //Gyro output data
roberthill04 0:30fa229c34d6 299 gyro_degree= gyro_data[0] / 10; //take y value (dps) and conver it to just degrees
roberthill04 0:30fa229c34d6 300 gyro_angle += gyro_degree; //add new degree value to old value
roberthill04 0:30fa229c34d6 301 //pc.printf("Angle: %f \t\r\n",gyro_angle); //print angle seen by gyro
roberthill04 0:30fa229c34d6 302 wait_ms(10); //wait needed in order to know what to integrate by
roberthill04 0:30fa229c34d6 303
roberthill04 0:30fa229c34d6 304 /*
roberthill04 0:30fa229c34d6 305 while (drift_counter < 30)
roberthill04 0:30fa229c34d6 306 {
roberthill04 0:30fa229c34d6 307 gyro.ReadXYZ(gyro_data);
roberthill04 0:30fa229c34d6 308 gyro_degree= gyro_data[0];
roberthill04 0:30fa229c34d6 309 gyro_angle += (gyro_degree+gyro_drift_angle)/10;
roberthill04 0:30fa229c34d6 310 pc.printf("Angle: %f \t\r\n",gyro_angle);
roberthill04 0:30fa229c34d6 311 wait_ms(10);
roberthill04 0:30fa229c34d6 312 drift_counter++;
roberthill04 0:30fa229c34d6 313 gyro_reset=gyro_angle;
roberthill04 0:30fa229c34d6 314 }
roberthill04 0:30fa229c34d6 315 drift_counter=0;
roberthill04 0:30fa229c34d6 316 */
roberthill04 0:30fa229c34d6 317 }
roberthill04 0:30fa229c34d6 318 void filter(void)
roberthill04 0:30fa229c34d6 319 {
roberthill04 0:30fa229c34d6 320 //Angle = a*(Angle + gyroData *dt) + (1-a)*(accData) filter formula constants subject to change in order to tune filter (must add to 1)
roberthill04 0:30fa229c34d6 321 // a = tau / ( tau * dt)
roberthill04 0:30fa229c34d6 322 //tau = ?
roberthill04 0:30fa229c34d6 323 //dt = 10ms
roberthill04 0:30fa229c34d6 324 /*
roberthill04 0:30fa229c34d6 325 The time constant of a filter is the relative duration of signal it will act on.
roberthill04 0:30fa229c34d6 326 For a low-pass filter, signals much longer than the time constant pass through unaltered
roberthill04 0:30fa229c34d6 327 while signals shorter than the time constant are filtered out. The opposite is true for a highpass
roberthill04 0:30fa229c34d6 328 filter.
roberthill04 0:30fa229c34d6 329 */
roberthill04 0:30fa229c34d6 330
roberthill04 0:30fa229c34d6 331 Filter_Angle = 0.35 * (Filter_Angle + gyro_angle) + 0.65*(Acc_Angle);
roberthill04 0:30fa229c34d6 332 //pc.printf("The Angle after the values are filtered: %f \t\r\n", Filter_Angle);
roberthill04 0:30fa229c34d6 333
roberthill04 0:30fa229c34d6 334 }
roberthill04 0:30fa229c34d6 335 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
roberthill04 0:30fa229c34d6 336
roberthill04 0:30fa229c34d6 337 int main()
roberthill04 0:30fa229c34d6 338 {
roberthill04 0:30fa229c34d6 339 blue.baud(9600);
roberthill04 0:30fa229c34d6 340 acc.enable(); //Turn on Accelerometer
roberthill04 0:30fa229c34d6 341 Offset_Calc(); //Run intial calibration angle
roberthill04 0:30fa229c34d6 342 PulseSensor Pulse_Signal(A0, sendDataToProcessing); //intialize pulse sensor to pin A0 on board
roberthill04 0:30fa229c34d6 343 Pulse_Signal.start(); //Turn on pulse sensor
roberthill04 0:30fa229c34d6 344 //runs data collection continuously
roberthill04 0:30fa229c34d6 345 //blue.printf("Bluetooth Start\t\r");
roberthill04 0:30fa229c34d6 346
roberthill04 0:30fa229c34d6 347 while(1)
roberthill04 0:30fa229c34d6 348 {
roberthill04 0:30fa229c34d6 349
roberthill04 0:30fa229c34d6 350
roberthill04 0:30fa229c34d6 351 //reset HR count and RPM count
roberthill04 0:30fa229c34d6 352 HR_Sum = 0;
roberthill04 0:30fa229c34d6 353 RPM_Sum = 0;
roberthill04 0:30fa229c34d6 354
roberthill04 0:30fa229c34d6 355 //reset timer01 for HR and RPM
roberthill04 0:30fa229c34d6 356 time01.reset();
roberthill04 0:30fa229c34d6 357 time01.start();
roberthill04 0:30fa229c34d6 358
roberthill04 0:30fa229c34d6 359
roberthill04 0:30fa229c34d6 360
roberthill04 0:30fa229c34d6 361
roberthill04 0:30fa229c34d6 362 //Loop includes all four sensors(HR, RPM, & Acc+Gyro)
roberthill04 0:30fa229c34d6 363 while(time01.read() < longTimer) { //runs for 10 seconds
roberthill04 0:30fa229c34d6 364
roberthill04 0:30fa229c34d6 365
roberthill04 0:30fa229c34d6 366 //reset timer02 for Acc
roberthill04 0:30fa229c34d6 367 time02.reset();
roberthill04 0:30fa229c34d6 368 time02.start();
roberthill04 0:30fa229c34d6 369
roberthill04 0:30fa229c34d6 370 Acc(); //might need to move this into the half second loop so that the Acc value the gyro takes to avoid drift is more accuarte
roberthill04 0:30fa229c34d6 371
roberthill04 0:30fa229c34d6 372
roberthill04 0:30fa229c34d6 373 //loop does not includes acc sensor
roberthill04 0:30fa229c34d6 374 while(time02.read() < shortTimer) //half second loop
roberthill04 0:30fa229c34d6 375 {
roberthill04 0:30fa229c34d6 376 //call Hall sensor funtion to pull # of revolutions
roberthill04 0:30fa229c34d6 377
roberthill04 0:30fa229c34d6 378 RPM(); //Resets every time its run so it sends a 1 or a 0 to add to the RPM_Sum
roberthill04 0:30fa229c34d6 379
roberthill04 0:30fa229c34d6 380 Gyro();
roberthill04 0:30fa229c34d6 381 filter();
roberthill04 0:30fa229c34d6 382
roberthill04 0:30fa229c34d6 383 RPM_Sum = RPM_Sum + Hall_Counter; // + function value
roberthill04 0:30fa229c34d6 384
roberthill04 0:30fa229c34d6 385 }
roberthill04 0:30fa229c34d6 386
roberthill04 0:30fa229c34d6 387 //Every half second calculate angle
roberthill04 0:30fa229c34d6 388
roberthill04 0:30fa229c34d6 389 /*
roberthill04 0:30fa229c34d6 390 blue.printf("This is the current angle: %f in degrees\t\r\n\n", Actual_Angle); //this is here to check values being found before sending for debugging
roberthill04 0:30fa229c34d6 391 blue.printf("This is the current pedal count: %d \t\r\n\n",RPM_Sum);
roberthill04 0:30fa229c34d6 392 blue.printf("This is the current heart rate: %d in BPM \t\r\n\n",Pulse_Signal.BPM);
roberthill04 0:30fa229c34d6 393 */
roberthill04 0:30fa229c34d6 394
roberthill04 0:30fa229c34d6 395 blue.printf("%d,%d,%f\n",Pulse_Signal.BPM, RPM_Sum, Filter_Angle); //prints to bluetooth
roberthill04 0:30fa229c34d6 396 //pc.printf("%d,%d,%f\n",Pulse_Signal.BPM, RPM_Sum, Filter_Angle); //prints to terminal
roberthill04 0:30fa229c34d6 397
roberthill04 0:30fa229c34d6 398
roberthill04 0:30fa229c34d6 399
roberthill04 0:30fa229c34d6 400
roberthill04 0:30fa229c34d6 401 //send data avgAcc, avgHR/BPM variable, avgRPM
roberthill04 0:30fa229c34d6 402
roberthill04 0:30fa229c34d6 403 }
roberthill04 0:30fa229c34d6 404 //reseting average HR and RPM
roberthill04 0:30fa229c34d6 405 avgHR = 0;
roberthill04 0:30fa229c34d6 406 avgRPM = 0;
roberthill04 0:30fa229c34d6 407
roberthill04 0:30fa229c34d6 408
roberthill04 0:30fa229c34d6 409 //converts sum to beats per min
roberthill04 0:30fa229c34d6 410 avgHR = HR_Sum*60/longTimer;
roberthill04 0:30fa229c34d6 411
roberthill04 0:30fa229c34d6 412 //converts sum to revolutions per min
roberthill04 0:30fa229c34d6 413 avgRPM = RPM_Sum*60/longTimer;
roberthill04 0:30fa229c34d6 414
roberthill04 0:30fa229c34d6 415 }
roberthill04 0:30fa229c34d6 416
roberthill04 0:30fa229c34d6 417 }