123
Dependencies: Hexi_KW40Z Hexi_OLED_SSD1351 MAX30101
Fork of HeartRate by
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
Generated on Fri Jul 15 2022 02:50:54 by 1.7.2