Code to be run for the project Group Fitness

Dependencies:   FXOS8700 Hexi_KW40Z Hexi_OLED_SSD1351 MAX30101

Fork of final_project_ee119 by Wenfei Lu

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // Importing the necessary header files for mbed OS, KW40z, OLED screen and 
00002 // FXOS 8700
00003 #include "mbed.h"
00004 #include "mbed_events.h"
00005 #include "Hexi_KW40Z.h"
00006 #include "Hexi_OLED_SSD1351.h"
00007 #include "OLED_types.h"
00008 #include "OpenSans_Font.h"
00009 #include "string.h"
00010 #include "FXOS8700.h"
00011 
00012 
00013 // Utility functions defined below
00014 void StartHaptic(void);
00015 void StopHaptic(void const *n);
00016 float Filter(int s);
00017 void AlertReceived(uint8_t *data, uint8_t length);
00018 void clearScreen();
00019 
00020 void displayString();
00021 void UpdateSensorData(void);
00022 void BTTask(void);
00023 void dataTask(void);
00024 
00025 void ButtonLeft();
00026 void ButtonRight();
00027 void ButtonDown();
00028 void ButtonUp();
00029 void ButtonLeft(void);
00030 
00031 /* Instantiate the accelerometer */ 
00032 
00033 FXOS8700 accel(PTC11, PTC10);
00034 
00035 /* Instantiate the Hexi KW40Z Driver (UART TX, UART RX) */ 
00036 KW40Z kw40z_device(PTE24, PTE25);
00037 
00038 /* Instantiate the SSD1351 OLED Driver */ 
00039 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15);
00040 
00041 RtosTimer hapticTimer(StopHaptic, osTimerOnce);
00042 DigitalOut haptic(PTB9);
00043 
00044 /* Create a Thread to handle sending BLE Sensor Data */ 
00045 Thread bluetoothThread;
00046 Thread dataThread;
00047 
00048 /* Create a Thread to handle displaying */ 
00049 Thread displayThread;
00050 EventQueue displayEventQueue;
00051 
00052 char text[20]; 
00053 
00054 // Variables
00055 float accel_data[3]; // Storage for the data from the sensor
00056 float accel_rms=0.0; // RMS value from the sensor
00057 float ax, ay, az; // Integer value from the sensor to be displayed
00058 const uint8_t *image1; // Pointer for the image1 to be displayed
00059 char text1[20]; // Text Buffer for dynamic value displayed
00060 char text2[20]; // Text Buffer for dynamic value displayed
00061 char text3[20]; // Text Buffer for dynamic value displayed
00062 float dot;
00063 float old_acc=0;
00064 float new_acc=0;
00065 float old_accx, old_accy, old_accz, old_dot=0.0;
00066 uint8_t StepNum = 0, StepNumber = 0;
00067 
00068 // Buffer for averaging out the Pedometer data
00069 float filter_buf[75];
00070 
00071 uint8_t result[1]={0};
00072 
00073 
00074 // variable to assist with viewing the other users' data
00075 char user[2]; 
00076 char mean[4];
00077 char max[4];
00078 char min[4];
00079 char steps[6];
00080 // boolean flag that says whether or not we've processed new data from pi
00081 // default to true because not data from pi until we ask for it
00082 bool processedReceivedData = true;
00083 
00084 int flag = 0;
00085 int userChosen = flag;
00086 
00087 // main() runs in its own thread in the OS
00088 int main() {
00089     
00090     /* Attaching the different functions to the Haptic Buttons*/
00091     kw40z_device.attach_buttonLeft(&ButtonLeft);
00092     kw40z_device.attach_buttonRight(&ButtonRight);
00093     kw40z_device.attach_buttonDown(&ButtonDown);
00094     kw40z_device.attach_buttonUp(&ButtonUp);
00095     kw40z_device.attach_alert(&AlertReceived);
00096     
00097     /* Starting the accelerometer values*/
00098     accel.accel_config();
00099     
00100     // open up the display queue so that at any point in the program,
00101     // we can put things inside of it and they'll be executed eventually
00102     displayThread.start(callback(&displayEventQueue, &EventQueue::dispatch_forever));
00103     displayEventQueue.call(&clearScreen);
00104     
00105     /*Thread start the thread for Handling Bluetooth Events*/
00106     dataThread.start(BTTask);
00107     bluetoothThread.start(dataTask);
00108     
00109     wait(osWaitForever); 
00110 }
00111 
00112 // Function for handling Bluetooth toggling advertisement, send Alert flag and 
00113 // Step numbers
00114 void BTTask(void){
00115    
00116    while (true) 
00117    {
00118         if (kw40z_device.GetLinkState() == 0) {
00119             kw40z_device.ToggleAdvertisementMode();
00120          }
00121         
00122         /*Notify Hexiwear App that it is running Sensor Tag mode*/
00123         kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG);
00124         
00125         kw40z_device.SendAlert(result, 2);
00126         kw40z_device.SendBatteryLevel(StepNumber);
00127 
00128         Thread::wait(1000);                 
00129     }
00130 }
00131 
00132 // Function for setting up the flag to configure different users to different
00133 // buttons on the Hexiwear and also to compute Pedometer algorithm based on 
00134 // Hexiwear data
00135 void dataTask(void) {    
00136     while (true) {
00137         if(flag == 1) {
00138             result[1] = 1;
00139             flag = 0;
00140             userChosen = 1;
00141         }
00142         
00143         if(flag == 2) { 
00144             result[1] = 2;
00145             flag = 0;
00146             userChosen = 2;
00147         }
00148         
00149         if(flag == 3){ 
00150             result[1] = 3;
00151             flag = 0;
00152             userChosen = 3;
00153         }
00154         
00155         accel.acquire_accel_data_g(accel_data);
00156         ax = Filter(0);
00157         ay = Filter(1);
00158         az = Filter(2);  
00159         wait(0.02);           
00160         accel_rms = sqrt((ax*ax)+(ay*ay)+(az*az)/3);
00161         dot = (old_accx * ax)+(old_accy * ay)+(old_accz * az);
00162         old_acc = abs(sqrt(old_accx*old_accx+old_accy*old_accy+old_accz*old_accz));
00163         new_acc = abs(sqrt(ax*ax+ay*ay+az*az));
00164         dot /= (old_acc * new_acc);
00165         
00166         /* Display Legends */ 
00167         StepNum = StepNumber;
00168         if(abs(dot - old_dot) >= 0.05 && abs(dot - old_dot) <= 0.10) {
00169             StepNumber += 1;
00170         }
00171         
00172         old_accx = ax;
00173         old_accy = ay;
00174         old_accz = az;
00175         old_dot = dot;
00176         
00177         Thread::wait(250);
00178     }
00179 }
00180 
00181 void StartHaptic(void)  {
00182     hapticTimer.start(50);
00183     haptic = 1;
00184 }
00185 
00186 void StopHaptic(void const *n) {
00187     haptic = 0;
00188     hapticTimer.stop();
00189 }
00190 
00191 float Filter(int s) {
00192     accel.acquire_accel_data_g(accel_data);
00193     float filter_sum = 0.0;
00194     //printf("%d\n\r",s);
00195     for(int i = 0; i < 75; i++) 
00196     {
00197     filter_buf[i] = accel_data[s];
00198     //printf("%4.2f\n\r",filter_buf[i]);
00199     filter_sum += filter_buf[i];
00200     }
00201     return (float)(filter_sum / 75);
00202 }
00203 
00204 // Key modification: use the alert functionality enabled by the host-ble interface
00205 // to define our own command to display different user's data
00206 void AlertReceived(uint8_t *data, uint8_t length) {
00207     processedReceivedData = false;
00208     
00209     StartHaptic();
00210     data[19] = 0;
00211     
00212     user[0] = '0' + userChosen;
00213     
00214     mean[0] = data[0];
00215     mean[1] = data[1];
00216     mean[2] = data[2];
00217     
00218     max[0] = data[5];
00219     max[1] = data[6];
00220     max[2] = data[7];
00221     
00222     min[0] = data[10];
00223     min[1] = data[11];
00224     min[2] = data[12];
00225     
00226     steps[0] = data[15];
00227     steps[1] = data[16];
00228     steps[2] = data[17];
00229     steps[3] = data[18];
00230     steps[4] = data[19];
00231     
00232     user[1] = 0;
00233     mean[3] = 0;
00234     max[3] = 0;
00235     min[3] = 0;
00236     steps[5] = 0;
00237     
00238     // if you haven't yet processed the data that pi sent
00239     // you in the past, then don't do anything.
00240     
00241     // 2: queue up the displaying of that string
00242     displayEventQueue.call(&displayString);
00243 }
00244 
00245 
00246 /****************************Call Back Functions*******************************/
00247 
00248 // just write the received data to the screen
00249 void displayString() {
00250     if (!processedReceivedData) {
00251         clearScreen();
00252         
00253         processedReceivedData = true;
00254         oled_text_properties_t textProperties = {0};
00255         oled.GetTextProperties(&textProperties);
00256         
00257         textProperties.fontColor   = COLOR_BLUE;
00258         oled.SetTextProperties(&textProperties);
00259         
00260         sprintf(text, "USER: %s\0",user);
00261         oled.Label((uint8_t*)text,0,0);
00262         
00263         sprintf(text, "MEAN HR: %s\0",mean);
00264         oled.Label((uint8_t*)text,0,15);
00265         
00266         sprintf(text, "MAX HR: %s\0",max);
00267         oled.Label((uint8_t*)text,0,30);
00268         
00269         sprintf(text, "MIN HR: %s\0",min);
00270         oled.Label((uint8_t*)text,0,45);
00271         
00272         sprintf(text, "STEPS: %s\0",steps);
00273         oled.Label((uint8_t*)text,0,60);
00274     }
00275 }
00276 
00277 void ButtonUp(void) {
00278     StartHaptic();
00279     flag = 1;
00280 //    processedReceivedData = false;
00281 }
00282 
00283 void ButtonDown(void) {
00284     StartHaptic();
00285     flag = 2;
00286 //    processedReceivedData = false;
00287 }
00288 
00289 void ButtonRight(void) {
00290     StartHaptic();
00291     flag = 3;
00292 //    processedReceivedData = false;
00293 }
00294 
00295 void ButtonLeft(void) {
00296     StartHaptic();
00297     kw40z_device.ToggleAdvertisementMode();
00298 }
00299 
00300 
00301 
00302 // initialize the screen to black
00303 void clearScreen() {    
00304     oled.FillScreen(COLOR_BLACK);
00305 }