123

Dependencies:   Hexi_KW40Z Hexi_OLED_SSD1351 MAX30101

Fork of HeartRate by Xi Han

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "mbed_events.h"
00003 #include "MAX30101.h"
00004 #include "string.h"
00005 #include "Hexi_OLED_SSD1351.h"
00006 #include "Hexi_KW40Z.h"
00007 #define FIFO_DATA_MAX 288
00008 void UpdateSensorData(void);
00009 void StartHaptic(void);
00010 void StopHaptic(void const *n);
00011 void txTask(void);
00012 
00013 DigitalOut pwr1v8(PTA29);
00014 DigitalOut pwr3v3b(PTC13);
00015 DigitalOut pwr15v(PTB12);
00016 I2C i2c0(PTB1, PTB0);
00017 InterruptIn maximInterrupt(PTB18);
00018 Serial pc(USBTX, USBRX);
00019 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15);
00020 KW40Z kw40z_device(PTE24, PTE25);
00021 DigitalOut haptic(PTB9);
00022 EventQueue evqueue(32 * EVENTS_EVENT_SIZE);
00023 Thread t;
00024 /* Define timer for haptic feedback */
00025 RtosTimer hapticTimer(StopHaptic, osTimerOnce);
00026 
00027 
00028 /*Create a Thread to handle sending BLE Sensor Data */ 
00029 Thread txThread;
00030 MAX30101 hr(i2c0);
00031 int realHeartRate;
00032 float calorie;
00033 int mask_ppg = 0;
00034 uint32_t count = 0;
00035 uint32_t num;
00036 uint8_t testsignal = 60;
00037 void StartHaptic(void)  {
00038     hapticTimer.start(50);
00039     haptic = 1;
00040 }
00041 void ButtonRight(void)
00042 {
00043     StartHaptic();
00044     kw40z_device.ToggleAdvertisementMode();
00045 }
00046 
00047 void ButtonLeft(void)
00048 {
00049     StartHaptic();
00050     kw40z_device.ToggleAdvertisementMode();
00051 }
00052 
00053 void StopHaptic(void const *n) {
00054     haptic = 0;
00055     hapticTimer.stop();
00056 }
00057 void txTask(void){
00058    
00059    while (true) 
00060    {
00061         UpdateSensorData();
00062         
00063         /*Notify Hexiwear App that it is running Sensor Tag mode*/
00064         kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG);
00065         //send heartrate
00066         kw40z_device.SendHeartRate(testsignal);        
00067         /*The following is sending dummy data over BLE. Replace with real data*/
00068     
00069         /*Send Battery Level for 20%  
00070         kw40z_device.SendBatteryLevel(battery);
00071                
00072         Send Ambient Light Level at 50%  
00073         kw40z_device.SendAmbientLight(light);*/
00074         
00075         /*Send Humidity at 90% */
00076         //kw40z_device.SendHumidity(humidity);
00077         
00078         /*Send Temperature at 25 degrees Celsius 
00079         kw40z_device.SendTemperature(temperature);
00080 
00081         /*Send Pressure at 100kPA */ 
00082         //kw40z_device.SendPressure(pressure);
00083         
00084         /*Send Mag,Accel,Gyro Data. 
00085         kw40z_device.SendGyro(x,y,z);
00086         kw40z_device.SendAccel(z,x,y);
00087         kw40z_device.SendMag(y,z,x);*/
00088 
00089         Thread::wait(1000);                 
00090     }
00091 }
00092 void UpdateSensorData(void)
00093 {    
00094     testsignal+=1; 
00095     /*battery -= 5;
00096     if(battery < 5) battery = 100;
00097     
00098     light += 20;
00099     if(light > 100) light = 0;
00100     
00101     humidity += 500;
00102     if(humidity > 8000) humidity = 2000;
00103     
00104     temperature -= 200;
00105     if(temperature < 200) temperature = 4200;
00106     
00107     pressure += 300;
00108     if(pressure > 10300) pressure = 7500;
00109     
00110     x += 1400;
00111     y -= 2300;
00112     z += 1700;*/
00113 }
00114 
00115 void interruptHandlerQueued() {
00116     
00117     MAX30101::InterruptBitField_u interruptStatus;
00118     hr.getInterruptStatus(interruptStatus);
00119 //    printf("Interrupt Status: 0x%02x\r\n", interruptStatus.all);
00120     
00121     if (interruptStatus.bits.pwr_rdy == 0x1) {
00122 //        printf("Powered on\r\n");
00123         
00124         // Soft reset
00125         MAX30101::ModeConfiguration_u modeConf;
00126         modeConf.all = 0;
00127         modeConf.bits.reset = 1;
00128         hr.setModeConfiguration(modeConf);
00129         wait(0.01);
00130         
00131         // Configure FIFO
00132         MAX30101::FIFO_Configuration_u fifoConf;
00133         hr.getFIFOConfiguration(fifoConf);
00134 //        pc.printf("FIFO Configuration: 0x%02x\r\n", fifoConf.all);
00135           
00136         // Set LED power
00137         hr.setLEDPulseAmplitude(MAX30101::LED1_PA, 0x0C);
00138         hr.setLEDPulseAmplitude(MAX30101::ProxModeLED_PA, 0x19);
00139 //        pc.printf("LED set\r\n");
00140         
00141         MAX30101::SpO2Configuration_u spo2Conf;
00142         hr.getSpO2Configuration(spo2Conf);
00143         spo2Conf.bits.led_pw = MAX30101::PW_1;
00144         spo2Conf.bits.spo2_sr = MAX30101::SR_100_Hz;
00145         hr.setSpO2Configuration(spo2Conf);
00146         hr.getSpO2Configuration(spo2Conf);
00147 //        pc.printf("SpO2 Configuration: 0x%02x\r\n", spo2Conf.all);
00148         
00149         // Proximity settings
00150         hr.setProxIntThreshold(0x14);
00151         
00152         // Enable HR mode
00153         modeConf.all = 0;
00154         modeConf.bits.mode = MAX30101::HeartRateMode;
00155         hr.setModeConfiguration(modeConf);
00156 //        printf("Mode set\r\n");
00157     }
00158     
00159     if (interruptStatus.bits.prox_int == 0x1) {
00160 //        printf("Proximity Triggered, entered HR Mode.");
00161     }
00162     
00163     if (interruptStatus.bits.ppg_rdy == 0x1) {
00164 //        printf("PPG Ready.\r\n");
00165         mask_ppg = 1;
00166     }
00167     
00168     if (interruptStatus.bits.a_full == 0x1) {
00169 //        printf("FIFO Almost Full.\r\n");
00170         uint8_t data[FIFO_DATA_MAX];
00171         uint16_t readBytes = 0;
00172        
00173         
00174         hr.readFIFO(MAX30101::OneLedChannel, data, readBytes);
00175         //printf("data length: %u \r\n",readBytes);
00176         //printf("data length: %u \r\n",data);
00177         for (uint16_t i = 0; i < readBytes; i += 3) {
00178             uint8_t sample[4] = {0};
00179             sample[0] = data[i + 2];
00180             sample[1] = data[i + 1];
00181             sample[2] = data[i];
00182             
00183             num = *(uint32_t *) sample;
00184             if (num < 310000){
00185                 realHeartRate = 0;
00186                 printf("keep closer to your hand \r\n");
00187             }
00188             else {
00189                 
00190                 //realHeartRate = 65;
00191                 realHeartRate = (num - 310000)/100;
00192                 if (realHeartRate >45){
00193                     printf("%d\r\n", realHeartRate);
00194                 }
00195             }
00196             //printf("%u\r\n", num);
00197             
00198             
00199         }
00200     }
00201     
00202     interruptStatus.all = 0xFF;
00203     if (mask_ppg == 1) {
00204         interruptStatus.bits.ppg_rdy = 0;
00205     }
00206     hr.enableInterrupts(interruptStatus);
00207 }
00208 
00209 void interruptHandler() {
00210     evqueue.call(interruptHandlerQueued);
00211 }
00212 
00213 // main() runs in its own thread in the OS
00214 int main() {
00215 //    printf("Hello world.\r\n");
00216 
00217     t.start(callback(&evqueue, &EventQueue::dispatch_forever));
00218     kw40z_device.attach_buttonLeft(&ButtonLeft);
00219     kw40z_device.attach_buttonRight(&ButtonRight);
00220      
00221     pwr1v8 = 1;
00222     pwr3v3b = 1;
00223     pwr15v = 0;
00224     
00225     maximInterrupt.fall(interruptHandler);
00226     maximInterrupt.enable_irq();
00227     
00228     MAX30101::InterruptBitField_u interruptStatus;
00229     interruptStatus.all = 0xFF;
00230     hr.enableInterrupts(interruptStatus);
00231     
00232     char text[20];  /* Text Buffer */ 
00233     oled_text_properties_t textProperties = {0};
00234     oled.GetTextProperties(&textProperties);   
00235     /* Turn on the backlight of the OLED Display */
00236     oled.DimScreenON();
00237     
00238     /* Fills the screen with solid black */         
00239     oled.FillScreen(COLOR_BLACK);
00240     strcpy((char *) text, "Heart Rate:");
00241     oled.Label((uint8_t *)text,7,0);
00242     
00243     strcpy((char *) text, "Calorie/Hr:");
00244     oled.Label((uint8_t *)text,7,40);
00245     //dynamic text setup
00246     textProperties.fontColor = COLOR_WHITE;
00247     textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
00248     oled.SetTextProperties(&textProperties);     
00249     
00250     txThread.start(txTask);
00251     while (true) {
00252         
00253         /* Format the time reading */
00254         sprintf(text,"%d",realHeartRate);
00255         
00256         /* Display time reading in 35px by 15px textbox at(x=55, y=40) */
00257         oled.TextBox((uint8_t *)text,55,15,35,15); //Increase textbox for more digits
00258         if (realHeartRate > 45){
00259             calorie = (-55.1 + (0.6309*realHeartRate)+(0.1988*75)+(0.2017*25))*60/4.184 ;
00260             sprintf(text,"%0.2f",calorie);
00261             
00262             /* Display time reading in 35px by 15px textbox at(x=55, y=40) */
00263             oled.TextBox((uint8_t *)text,55,55,35,15); //Increase textbox for more digits
00264         }
00265         else{
00266             sprintf(text,"wait HR");
00267             
00268             /* Display time reading in 35px by 15px textbox at(x=55, y=40) */
00269             oled.TextBox((uint8_t *)text,55,55,35,15);
00270         }
00271              
00272         Thread::wait(1000);
00273     }    
00274     return 0;
00275 }
00276