The HexiHeart is a demo project product that takes advantage of many of the onboard Hexiwear sensors and capabilities to create a multifunctional fitness and safety watch.
Dependencies: FXAS21002 FXOS8700 Hexi_KW40Z Hexi_OLED_SSD1351 MAXIM W25Q64FVSSIG HTU21D MPL3115A2 TSL2561
Fork of HexiHeart_Alex by
Diff: main.cpp
- Revision:
- 7:3d5a8aea0b63
- Parent:
- 6:84e3ba00b995
- Child:
- 8:a5c77b45008d
--- a/main.cpp Tue Feb 13 15:42:22 2018 +0000 +++ b/main.cpp Wed Feb 14 22:53:49 2018 +0000 @@ -84,6 +84,7 @@ bool Heart_Rate_Mode = 0; // Initialize with Heart rate off float Accel_Mag=0.0; // Vector magnitude calculated from sensor data float Accel_Data[3]; // Accel Data from sensor +float Accel_Data_Event[3]; // Accel Data from sensor at interupt float Gyro_Mag=0.0; // Vector magnitude calculated from sensor data float Gyro_Data[3]; // Gyro data from sensor float Fall_Thresh=0.5; // Initialize Fall detect Threshold @@ -712,6 +713,8 @@ int main() { +// set_time(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37 + set_time(48*365*24*3600+61*24*3600+10*3600); // Set RTC time to Mon, 19 Feb 2018 10:00 OLED_PWR = 1; // Turn on OLED power supply @@ -722,9 +725,9 @@ // ************** configure sensor modules ****************** // accel.accel_config(); // configure sensor - fall_config(1); // configure sensor for fall detect - // Fall_config(Fall_Alert_Mode); // configure sensor for fall mode - mag.mag_config(); + // fall_config(1); // configure sensor for fall detect + fall_config(3); // configure sensor for fall mode +// mag.mag_config(); gyro.gyro_config(); RED_Led = LED_OFF; @@ -745,7 +748,7 @@ // ***** attaching interupts to functions ********* Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine - // Accel_INT2.fall(&impact_detect); //Accel sensor's int#2 calls interupt routine + Accel_INT2.fall(&impact_detect); //Accel sensor's int#2 calls interupt routine // **** Get OLED Class Default Text Properties **************** @@ -830,9 +833,27 @@ oled.Label((uint8_t *)"Date",35,20); // Display "Date" at x,y oled.Label((uint8_t *)"Time",35,40); // Display "Time" at x,y // oled.Label((uint8_t *)"H.I.",10,80); // Display "H.I." at x,y + oled.Label((uint8_t *)"BT",40,80); //Display "BT" at x,y oled.Label((uint8_t *)"Menu",60,80); //Display "Menu" at x,y + textProperties.fontColor = COLOR_GRAY; + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"BT",40,80); //Display "BT" at x,y + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + +// added real time and date information + char buffer[32]; + time_t seconds = time(NULL); + strftime(buffer,32, "%a,%d %m %Y.%H:%M:%S\r", localtime(&seconds)); + sprintf(text_1,"%c%c/%c%c/%c%c%c%c ",buffer[7],buffer[8],buffer[4],buffer[5],buffer[10],buffer[11],buffer[12],buffer[13]); + oled.Label((uint8_t *)text_1,20,20);// Date at x,y + sprintf(text_1,"%c%c:%c%c:%c%c ",buffer[15],buffer[16],buffer[18],buffer[19],buffer[21],buffer[22]); + oled.Label((uint8_t *)text_1,25,40);// Time at x,y + + + Heat_Index_Calculation(); sprintf(text,"%i",heat_index); oled.TextBox((uint8_t *)text,3,80,15,15); @@ -857,7 +878,7 @@ oled.Label((uint8_t *)"Fall Alert",20,5); // Display at x,y oled.Label((uint8_t *)"Protection",15,25); if (Fall_Alert == 1){ - oled.Label((uint8_t *)" On ",42,40); + oled.Label((uint8_t *)" On ",40,40); } else { oled.Label((uint8_t *)" Off ",40,40); @@ -879,7 +900,7 @@ } case 4: {// Alert History option oled.FillScreen(COLOR_BLACK); // Clear screen - oled.Label((uint8_t *)"Alert History",5,5); // Display at x,y + oled.Label((uint8_t *)"Alert History",10,5); // Display at x,y oled.Label((uint8_t *)"*",85,15); // "*" at x,y oled.Label((uint8_t *)"*",85,60); // "*" at x,y oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y @@ -974,13 +995,13 @@ oled.FillScreen(COLOR_BLACK); // Clear screen textProperties.fontColor = COLOR_RED; oled.SetTextProperties(&textProperties); - oled.Label((uint8_t *)"Fall",30,5); // Display at x,y - oled.Label((uint8_t *)"Diagnostic",25,5); // Display at x,y + oled.Label((uint8_t *)"Fall-Diag",25,5); // Display at x,y + // oled.Label((uint8_t *)"Diagnostic",25,5); // Display at x,y textProperties.fontColor = COLOR_WHITE; oled.SetTextProperties(&textProperties); accel.acquire_accel_data_g(Accel_Data); // gyro.acquire_gyro_data_g(Gyro_Data); - Accel_Mag = sqrt(((Accel_Data[0]*Accel_Data[0])+(Accel_Data[1]*Accel_Data[1])+(Accel_Data[2]*Accel_Data[2]))); + Accel_Mag = 2*sqrt(((Accel_Data[0]*Accel_Data[0])+(Accel_Data[1]*Accel_Data[1])+(Accel_Data[2]*Accel_Data[2]))); // Gyro_Mag = (abs(Gyro_Data[0])+abs(Gyro_Data[1])+abs(Gyro_Data[3])); sprintf(text_1," Accel:%2.2f g ",Accel_Mag); oled.Label((uint8_t *)text_1,10,40);// text_1 at x,y @@ -1764,9 +1785,9 @@ void fall_detect(){// fall detect interupt rutine if(Fall_Alert == 1){ - + accel.acquire_accel_data_g(Accel_Data_Event); // for now just turn on display and give haptic feedback - Screen_Num = 22; //Change to screen 22 (Fall diag screen) + Screen_Num = 21; //Change to screen 21 (Fall diag screen) Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED if (OLED_ON == 0) { OLED_ON = 1; // Scree was off, set to On @@ -1776,6 +1797,10 @@ // oled.Label((uint8_t *)" Fall Detected ",05,70); // Display at x,y update_display(); + Accel_Mag = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2]))); + sprintf(text_1,"Free-Fall:%2.2fg",Accel_Mag); + oled.Label((uint8_t *)text_1,10,5);// text_1 at x,y + BLU_Led = LED_ON; // LEDs default to on, need to turn off Led_clk2 = 1; // Turn LED2 on docking station on haptic = 1; @@ -1805,9 +1830,23 @@ ******************************************************************************/ void impact_detect(){ - // oled.Label((uint8_t *)" Impact Detected ",05,60); // Display at x,y - // GRN_Led = LED_ON; // LEDs default to on, need to turn off - Led_clk3 = 1; // Turn LED2 on docking station on + if(Fall_Alert == 1){ + accel.acquire_accel_data_g(Accel_Data_Event); +// for now just turn on display and give haptic feedback + Screen_Num = 21; //Change to screen 21 (Fall diag screen) + Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED + if (OLED_ON == 0) { + OLED_ON = 1; // Scree was off, set to On + } // endif + // update_display(); + + accel.acquire_accel_data_g(Accel_Data); + Accel_Mag = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2]))); + sprintf(text_1,"Impact:%2.2fg",Accel_Mag); + oled.Label((uint8_t *)text_1,10,20);// text_1 at x,y + + Led_clk3 = 1; // Turn LED2 on docking station on + }// end if }//end impact_detect interupt routine /***************************************************************************** @@ -1919,7 +1958,145 @@ oled.Label((uint8_t *)" Mode 1 ",30,60); // Display "mode" at x,y GRN_Led = LED_ON; // LEDs default to on, need to turn on break; - } + }// end of case 1 + + // case 2 was an attempt at using vector-mag int for free-fall + + case 3: {// configure FFMT for free-fall event AND config for vector impact + + StartHaptic(); // for debug + char d[2]; + + d[0] = FXOS8700_CTRL_REG1; //Config reg1 0x2a + d[1] = 0x00; //Put device in Standby mode + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step1 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x0e; //XYZ_DATA_CFG (set full-scall range) + d[1] = 0b00000001; //Set data to +/-4g for full range (0.488mg/LSB), High-pass filter off + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step1a error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x0a; //TRIG_CFG (address of trigger config reg) + d[1] = 0b00000110; //Trigger on freefall and on Vector + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step2 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x15; //A_FFMT_CFG (address of Free fall trigger config reg), write in Standby only + d[1] = 0b00111000; //set to freefall, and look at all axis. + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step3 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x17; //A_FFMT_THS (address of Free fall threshold reg), write in Active or Standby + d[1] = 0b00001000; //set freefall threshold to about 756mg for now + // d[1] = uint8_t(1000*Fall_Thresh/63); //set freefall threshold - Resolution is 63mg/LSB, 0b111_1111 is maximum value + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step4 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x18; //A_FFMT_COUNT (address of Free fall debounce counter), write in Active or Standby + d[1] = 0b00000110; //with ODR at 100Hz, should equal 60mS debounce time or 120mS in Sleep + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step5 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x5f; //A_VECM_CFG (address of Vector config reg), write in Standby only + d[1] = 0b00111000; //Use reference values, don't update ref, enable. + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step3 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x60; //A_VECM_MSB (address of Vector threshold reg), write in Active or Standby + d[1] = 0b00001111; //set impact threshold to less than 1g for now + // d[1] = uint8_t((1000*Impact_Thresh/0.488)/256); //set MSB Impact threshold - Resolution is 0.488mg/LSB so 0.5g=1024.6 => MSB=0b00000100 LSB=0b00000000 + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step4a error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x61; //A_VECM_LSB (address of Vector threshold reg), write in Active or Standby + d[1] = 0b00000011; //set impact threshold to less than 1g for now + // d[1] = uint8_t(256*((1000*Impact_Thresh/0.488)%256)); //set MSB Impact threshold - Resolution 0.488mg/LSB so 0.5g=1024.6 => MSB=0b00000100 LSB=0b00000000 + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step4b error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x62; //A_VECM_COUNT (address of Vector debounce counter), write in Active or Standby + d[1] = 0b00000110; //with ODR at 100Hz, should equal ??mS debounce time or ??mS in Sleep + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step5 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + // Registers 0x63 - 0x68 are vector reference values which I'm leaving set to 0 because we want absolute measurements + + d[0] = 0x2b; //CTRL_REG2 (address of control reg), write in Standby only + d[1] = 0b00001101; //Turns Auto-Sleep mode on and low-noise, low power + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step6 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x2c; //CTRL_REG3 (address of Int control reg), write in Standby only + d[1] = 0b00001100; //FFMT or Vector will wake chip from sleep, int are active high + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step7 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x2d; //CTRL_REG4 (address of Int enable reg), write in Standby only + d[1] = 0b00000110; // FFMT and Vector int enabled + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step8 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = 0x2e; //CTRL_REG5 (Int routing reg), write in Standby only + d[1] = 0b00000100; // Make FFMT int output on pin INT1(PTC1) and Vector on INT2(PTD13) + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step9 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + d[0] = FXOS8700_CTRL_REG1; //CTRL_REG1, write in Standby only except for bit[0] + d[1] = 0b00011001; //Auto-Sleep mode on set to 50Hz, ODR set to 100Hz Puts device back into Active mode + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Step10 error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + //oled.FillScreen(COLOR_BLACK); // Clear screen + oled.Label((uint8_t *)" Mode 3 ",30,60); // Display "mode" at x,y + // GRN_Led = LED_ON; // LEDs default to on, need to turn on + + + break; + }// end of case 3 + + case 10: {// reset IC + char d[2]; + d[0] = 0x2b; //CTRL_REG2 + d[1] = 0b01000000; // set bit to force reset of FXOS8700 + if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)" Reset error ",30,05); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + oled.Label((uint8_t *)" reset ",30,60); // Display "reset" at x,y + break; + }// end case 10 + default: { oled.Label((uint8_t *)" Mode ? ",30,60); // Display "mode" at x,y // unknown config