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:
- 10:eaea844e763c
- Parent:
- 9:d2e39ee9fedd
- Child:
- 11:ccda4d44bd8e
diff -r d2e39ee9fedd -r eaea844e763c main.cpp --- a/main.cpp Tue Mar 06 00:22:47 2018 +0000 +++ b/main.cpp Mon Mar 26 00:29:18 2018 +0000 @@ -13,6 +13,10 @@ Function and interupt routines Display data screen update routines +v2.09 - Added final fall mode (full sequential fall algorithm), including alert screen +and dismiss alert screen. Added FAP (Fall Alert Protection) to main screen. fixed "aggressive Haptic" problem by using a Ticker to +turn off Haptic instead of RTOS timer. + v2.08 - Fixed impact detect functionality, all fall detect parameters are now adjustable, added motion detect function, incorporated new heat index calc, increased font by 20% for time/date. Added SW and power resetting to initialize sensors in known state. @@ -46,7 +50,7 @@ // Definitions -#define SW_Ver 2.08 // For displaying software version +#define SW_Ver 2.09 // For displaying software version #define LED_ON 0 #define LED_OFF 1 #define SCRN_TIME 10.0 @@ -64,6 +68,7 @@ //#define MPL3115A2_I2C_ADDRESS_ ? // void StartHaptic(void); +void Haptic_Off_(void); // added by NRB void StartHaptic(int x); void StopHaptic(void const *n); void error_screen(void); // display error screen @@ -85,17 +90,26 @@ void Disable_Heart_Rate(); void Led_Zone_Indicator(); void Heat_Index_Calculation(); -void fall_config(uint8_t); -void gyro_sensor_config(uint8_t); +void fall_config(uint8_t); //function call to setup fall detecting modes +void accel_sensor_config(uint8_t); +void gyro_sensor_config(uint8_t); void light_config(uint8_t); void press_config(uint8_t); -void fall_detect(void); -void fall_det_end(void); -void fall_detect_off(void); -void impact_detect(void); -void motion_detect(); +void fall_detect(void); // Interupt routine +void fall_detect_debug(void); // Interupt routine +void fall_det_end(void); // Interupt routine +void fall_det_end_debug(void); // Interupt routine +void chkfall(void); // Routine used with Ticker +void interupt_off(void); +void clear_fall(void); // Routine used with Ticker +void impact_detect(void); // Interupt routine +void impact_detect_debug(void); // Interupt routine +void motion_detect(); // Interupt routine +void motion_detect_debug(); // Interupt routine +void chkmotion(void); // Routine used with Ticker +void chk_help_needed(void); // Routine used with Ticker void MAX30101_test_config(uint8_t); - +void Send_Alert(uint8_t); // fuction to store and send alert // ***************** Global variables *********************** char text_1[20]; // Text buffer - Do we need more? @@ -108,18 +122,21 @@ bool OLED_ON = 1; // Turn OLED power on/off bool Fall_Alert = 1; // Initialize as no active alert bool Panic_Alert = 0; // Initialize as no active alert -uint8_t Fall_Alert_Mode = 4; // Initialize with fall alert mode on +uint8_t Fall_Alert_Mode = 5; // Initialize with fall alert mode on 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 Fall_Event_Data[7]; // Fall event Data ff-value, ff-time, impact-value, 4byte timestamp 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 -float Impact_Thresh=3.0; // Initialize Impact detect Threshold -float Movement_Thresh=50.0; // Initialize Movement detect Threshold +float Gyro_Data[3]; // Gyro data from sensor +float Fall_Thresh=0.5; // Initialize Free-Fall detect Threshold as being <= 0.5g +float Fall_Impact_Max_Wait_Time=2.0;// maximum wait time from end of fall detect to impact detect +float Impact_Thresh=3.0; // Initialize Impact detect Threshold +float Movement_Thresh=50.0; // Initialize Movement detect Threshold float Min_Movement_Time=5.0; // Initialize Movement minimum movement time to 5 sec float Min_Movement_duration=60.0; // Initialize Movement min-movement testing duration to 60 sec +float Do_You_Need_Help_Time=10.0; // Time to dismiss "Do you need Help" screen uint8_t Current_Zone = 1; uint8_t Prev_Zone = 1; uint8_t Heart_Rate = 100; @@ -203,6 +220,10 @@ //***************** Tickers and Timers ***************** Ticker Screen_Timer;// use ticker to turn off OLED +Timer f_time; // Timer used to measure fall +Ticker chk_fall; // Ticker used to check on active fall +Ticker chk_motion; // Ticker used to check on post fall motion +Ticker Haptic_Timer; void timout_timer(){ // turn off display mode #ifdef Debug // in debug keep screens on for demo @@ -272,6 +293,9 @@ case 6: {// Panic Alert StartHaptic(); Panic_Alert = !Panic_Alert; + if(Panic_Alert == 1){ + Send_Alert(0); // send/store alert type zero + }//endif update_display(); break; } @@ -373,19 +397,19 @@ break; } - case 41: {//Fall mode 0,1,2,3,4 - // 0=nothing, 1=fall_only, 2=impact only, 3=motion_only, 4=all + case 41: {//Fall mode 0,1,2,3,4,5 + // 0=nothing, 1=fall_only, 2=impact only, 3=motion_only, 4=all, 5=main sequence StartHaptic(); Fall_Alert_Mode++; - if(Fall_Alert_Mode > 4){ + if(Fall_Alert_Mode > 5){ Fall_Alert_Mode = 0; }//endif update_display(); __disable_irq(); // Disable all Interrupts fall_config(10); // reset accel sensor - gyro_sensor_config(10); // reset gyro sensor + //gyro_sensor_config(10); // reset gyro sensor wait(0.1); - gyro_sensor_config(Fall_Alert_Mode); // leave gyro sensor active + //gyro_sensor_config(Fall_Alert_Mode); // leave gyro sensor active fall_config(Fall_Alert_Mode); wait(0.1); __enable_irq(); // Enable all Interrupts @@ -608,19 +632,19 @@ update_display(); break; } - case 41: {//Fall mode 0,1,2,3 - // 0=nothing, 1=fall_only, 2=impact only, 3=motion_only, 4=all + case 41: {//Fall mode 0,1,2,3,4,5 + // 0=nothing, 1=fall_only, 2=impact only, 3=motion_only, 4=all, 5=main sequence StartHaptic(); Fall_Alert_Mode--; - if(Fall_Alert_Mode > 3){// should be 0xff if decr from zero - Fall_Alert_Mode = 3; + if(Fall_Alert_Mode > 5){// should be 0xff if decr from zero + Fall_Alert_Mode = 5; } //endif update_display(); __disable_irq(); // Disable all Interrupts fall_config(10); // reset accel sensor - gyro_sensor_config(10); // reset gyro sensor + //gyro_sensor_config(10); // reset gyro sensor wait(0.1); - gyro_sensor_config(Fall_Alert_Mode); // leave gyro sensor active + //gyro_sensor_config(Fall_Alert_Mode); // leave gyro sensor active fall_config(Fall_Alert_Mode); wait(0.1); __enable_irq(); // Enable all Interrupts @@ -715,12 +739,13 @@ case 2: {// Fall Alert option StartHaptic(); if(Fall_Alert == 1){ - Accel_INT1.fall(&fall_detect_off); // turn off Accel sensor's int#1 calls interupt routine Fall_Alert = 0; + fall_config(0); // configure sensors for standby } else{ - Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine + //Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine Fall_Alert = 1; + fall_config(Fall_Alert_Mode); // configure sensors for current fall mode } update_display(); break; @@ -842,7 +867,13 @@ //do nothing for now break; } - + case 47: {// Fall-Detected screen "are you ok?" + StartHaptic(); + Send_Alert(1); // send/store alert type one + Screen_Num = 48; //Change to screen 48 (send alert screen) + update_display(); + break; + } case 71: {// BLE StartHaptic(); Screen_Num = 72; //Change to screen 72 @@ -1054,7 +1085,24 @@ Screen_Num = 45; //Change to screen 45 update_display(); break; - } + } + case 47: {// Fall-detected screen + StartHaptic(); + Led_clk1 = 0; // Turn off LED1, on docking station + Led_clk2 = 0; // Turn off LED2, on docking station + Screen_Num = 0; //Change to screen 0 + update_display(); + break; + } + case 48: {// Sending Fall-Alert screen + StartHaptic(); + Led_clk1 = 0; // Turn off LED1, on docking station + Led_clk2 = 0; // Turn off LED2, on docking station + // stop/dismiss alert + Screen_Num = 0; //Change to screen 0 + update_display(); + break; + } case 71: {// BLE StartHaptic(); @@ -1094,8 +1142,9 @@ { // set_time(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37 // set_time((Year-1970)*365*24*3600+(days of this year)*24*3600+(hr)*3600 + (min)*60 + (Sec) - fudge factor); // Set RTC time to Mon, 19 Feb 2018 10:00 - // set_time(48*365*24*3600 + 61*24*3600 + 10*3600-4); // Set RTC time to Mon, 19 Feb 2018 10:00 - set_time((2018-1970)*365.25f*24*3600 + (31+28+1-1)*24*3600 + (16)*3600 + (5)*60+ (1) + 38); // Set RTC time + //set_time(48*365*24*3600 + 61*24*3600 + 10*3600-4); // Set RTC time to Mon, 19 Feb 2018 10:00 + //set_time((2018-1970)*365.25f*24*3600 + (31+28+1-1)*24*3600 + (16)*3600 + (5)*60+ (1) + 38); // Set RTC time to 3/01/2018 16:04:20 + set_time((2018-1970)*365.25f*24*3600 + (31+28+26-1)*24*3600 + (10)*3600 + (0)*60+ (0) + 28); // Set RTC time to 3/26/2018 10:00:00 RED_Led = LED_OFF; GRN_Led = LED_OFF; BLU_Led = LED_OFF; @@ -1115,8 +1164,8 @@ wait(0.2); // how long should we wait for sensors to power up? oled.FillScreen(COLOR_BLACK); // Clear screen - fall_config(10); // SW reset accell sensor - gyro_sensor_config(10); // SW reset gyro sensor + fall_config(10); // SW reset accell and gyro sensor + // gyro_sensor_config(10); // SW reset gyro sensor press_config(0); // put pressure sensor into 2uA standby, we're not using it MAX30101_test_config(10); // SW reset accell sensor oled.FillScreen(COLOR_BLACK); // Clear screen @@ -1127,14 +1176,14 @@ // ************** configure sensor modules ****************** -// accel.accel_config(); // original configure accel sensor + //accel.accel_config(); // original configure accel sensor fall_config(Fall_Alert_Mode); // configure sensor (I2C1) for current fall mode - //Fall_Alert_Mode: 0=none, 1=fall_only, 2=impact only, 3=motion_only, 4=all -// gyro.gyro_config(); // original configure gyro sensor - gyro_sensor_config(Fall_Alert_Mode); // configure gyro sensor (I2C1) 0=standby, 1=active, 2=interupt set up -// mag.mag_config(); // we don't need mag -// light_config(0); // config TSL2561 ambient light sensor (I2C0) for lowest power - cycling PowerEn should have reset it to state -// Configure HTU21(Temp/Hum)? No need, it seems to draw 0.02uA when not being activly read over data bus + //Fall_Alert_Mode: 0=none, 1=fall_only, 2=impact only, 3=motion_only, 4=all three, 5=full sequencial + //gyro.gyro_config(); // original configure gyro sensor + //gyro_sensor_config(Fall_Alert_Mode); // configure gyro sensor (I2C1) 0=standby, 1=active, 2=interupt set up (now setup in fall_config()) + //mag.mag_config(); // we don't need mag + //light_config(0); // config TSL2561 ambient light sensor (I2C0) for lowest power - cycling PowerEn should have reset it to state + //Configure HTU21(Temp/Hum)? No need, it seems to draw 0.02uA when not being activly read over data bus // need to configure MAX30101 at some point // MAX30101_test_config(0); @@ -1148,11 +1197,11 @@ // kw40z_device.attach_buttonSlide(&ButtonSlide); // ***** 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 - Gyro_INT1.fall(&motion_detect); // Gyro sensor's int#1 (PTD1) calls interupt routine - //Gyro_INT2.fall(&motion_detect); // Gyro sensor's int#2 (PTC18) calls interupt routine - //HR_INT1.fall(&some_HR_read_function_yet_to_be_named); // MAX30101 - Heart rate sensor's interupt + //Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 (PTC1) calls interupt routine (now setup in fall_config()) + //Accel_INT2.fall(&impact_detect); //Accel sensor's int#2 (PTD13) calls interupt routine(now setup in fall_config()) + //Gyro_INT1.fall(&motion_detect); // Gyro sensor's int#1 (PTD1) calls interupt routine (now setup in fall_config()) + //Gyro_INT2.fall(&motion_detect); // Gyro sensor's int#2 (PTC18) calls interupt routine (not used) + //HR_INT1.fall(&some_HR_read_function_yet_to_be_named); // MAX30101 - Heart rate sensor's interupt (PTB18) // **** Get OLED Class Default Text Properties **************** oled_text_properties_t textProperties = {0}; @@ -1264,6 +1313,21 @@ oled.Label((uint8_t *)"BT",40,80); //Display "BT" at x,y textProperties.fontColor = COLOR_WHITE; oled.SetTextProperties(&textProperties); + + textProperties.fontColor = COLOR_GRAY; + if(Fall_Alert == 1){ + textProperties.fontColor = COLOR_GREEN; // is Fall protection on? + } + if(Fall_Alert == 1 && Led_clk1 == 1){ + textProperties.fontColor = COLOR_YELLOW; // is Fall detected? + } + if(Fall_Alert == 1 && Led_clk1 == 1 && Led_clk2 == 1){ + textProperties.fontColor = COLOR_RED; // is impact detected? + } + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"FAP",1,0); //Display "FAP" at x,y + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); // added real time and date information char buffer[32]; @@ -1306,16 +1370,17 @@ oled.FillScreen(COLOR_BLACK); // Clear screen oled.Label((uint8_t *)"Fall Alert",20,5); // Display at x,y oled.Label((uint8_t *)"Protection",15,20); + oled.Label((uint8_t *)"FAP",15,40); if (Fall_Alert == 1){ textProperties.fontColor = COLOR_GREEN; oled.SetTextProperties(&textProperties); - oled.Label((uint8_t *)" On ",32,40); + oled.Label((uint8_t *)" On ",42,40); } else { textProperties.fontColor = COLOR_GRAY; oled.SetTextProperties(&textProperties); - oled.Label((uint8_t *)" Off ",30,40); + oled.Label((uint8_t *)" Off ",40,40); } textProperties.fontColor = COLOR_WHITE; @@ -1531,23 +1596,23 @@ textProperties.fontColor = COLOR_GREEN; oled.SetTextProperties(&textProperties); sprintf(text_1," %i ",Fall_Alert_Mode); - oled.Label((uint8_t *)text_1,35,20);// text_1 at x,y + oled.Label((uint8_t *)text_1,36,20);// text_1 at x,y textProperties.fontColor = COLOR_GRAY; - if(Fall_Alert_Mode == 1 || Fall_Alert_Mode == 4){ + if(Fall_Alert_Mode == 1 || Fall_Alert_Mode >= 4){ textProperties.fontColor = COLOR_GREEN; } oled.SetTextProperties(&textProperties); sprintf(text_1," %1.2f g ",Fall_Thresh); oled.Label((uint8_t *)text_1,35,35);// text_1 at x,y textProperties.fontColor = COLOR_GRAY; - if(Fall_Alert_Mode == 2 || Fall_Alert_Mode == 4){ + if(Fall_Alert_Mode == 2 || Fall_Alert_Mode >= 4){ textProperties.fontColor = COLOR_GREEN; } oled.SetTextProperties(&textProperties); sprintf(text_1," %2.2f g ",Impact_Thresh); oled.Label((uint8_t *)text_1,35,50);// text_1 at x,y textProperties.fontColor = COLOR_GRAY; - if(Fall_Alert_Mode == 3 || Fall_Alert_Mode == 4){ + if(Fall_Alert_Mode == 3 || Fall_Alert_Mode >= 4){ textProperties.fontColor = COLOR_GREEN; } oled.SetTextProperties(&textProperties); @@ -2016,6 +2081,44 @@ oled.SetTextProperties(&textProperties); break; }//end case 46 + + case 47: { //Post fall "are you OK?" screen + oled.FillScreen(COLOR_BLACK); + textProperties.fontColor = COLOR_RED; + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"Fall Detected!", 5, 5); + textProperties.font = OpenSans_12x18_Regular; // Max Width of Character = 12px, Max Height of Character = 18px + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"Do you need", 5, 20); + oled.Label((uint8_t *)"Help?", 10, 35); + //oled.Label((uint8_t *)"+",85,15); // "*" at x,y + //oled.Label((uint8_t *)"-",85,60); // "*" at x,y + oled.Label((uint8_t *)"No",10,75); // Display "Back" at x,y + oled.Label((uint8_t *)"YES!",60,75); //Display "Next" at x,y + textProperties.font = OpenSans_10x15_Regular; // Max Width of Character = 10px, Max Height of Character = 15px + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + break; + }//end case 47 + + case 48: { //Sending Fall alert screen + oled.FillScreen(COLOR_BLACK); + textProperties.fontColor = COLOR_RED; + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"Fall Detected!", 5, 5); + textProperties.font = OpenSans_12x18_Regular; // Max Width of Character = 12px, Max Height of Character = 18px + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"Sending", 20, 40); + oled.Label((uint8_t *)"Alert", 25, 55); + oled.Label((uint8_t *)"Dismiss?",5,75); // Display "Back" at x,y + //oled.Label((uint8_t *)"YES!",60,80); //Display "Next" at x,y + textProperties.font = OpenSans_10x15_Regular; // Max Width of Character = 10px, Max Height of Character = 15px + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + break; + }//end case 48 #endif // end of non-production/debug version code @@ -2083,12 +2186,17 @@ ******************************************************************************/ void StartHaptic(void) { - hapticTimer.start(30); // was originaly 50, then 30 + Haptic_Timer.attach(&Haptic_Off_,(0.05)); + // hapticTimer.start(30); // was originaly 50, then 30 /* this 30 value seems to not work after Neil added a global __disable_irq() and __enable_irq() for the update_display() functions on 2/18/18 */ haptic = 1; } +void Haptic_Off_(void) +{ + haptic = 0; + } /***************************************************************************** Name: StartHaptic @@ -2465,12 +2573,12 @@ } /***************************************************************************** -Name: fall_detect() -Purpose: Interupt rutine called when accelerometer IC has detected a free-fall >= 0.5g - +Name: fall_detect_debug() +Purpose: Debug Interupt routine called when accelerometer IC has detected a +free-fall (accel <= 0.5g) +Inputs: interupt1 of accel sensor ******************************************************************************/ - -void fall_detect(){// fall detect interupt rutine +void fall_detect_debug(){// fall detect interupt routine if(Fall_Alert == 1){ accel.acquire_accel_data_g(Accel_Data_Event); // for now just turn on display and give haptic feedback @@ -2493,39 +2601,40 @@ oled.Label((uint8_t *)text_1,2,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; - Accel_INT1.rise(&fall_det_end); // Accel sensor's int#1 calls interupt routine + Led_clk1 = 1; // Turn on LED1, on docking station + StartHaptic(); + // haptic = 1; + Accel_INT1.rise(&fall_det_end_debug); // reset accel sensor's int#1 to active high and proper int routine //__enable_irq(); // Enable all Interrupts }// end if -}//end fall_detect interupt routine - +}//end fall_detect_debug interupt routine -void fall_detect_off(){// fall detect interupt rutine -// for now just turn on display and give haptic feedback -}//end fall_detect_off interupt routine - -void fall_det_end(){ +/***************************************************************************** +Name: fall_det_end_debug() +Purpose: Debug interupt routine called when accelerometer IC has detected that the +free-fall acceleration has ended (accel now >0.5g) +Inputs: interupt1 of accel sensor +******************************************************************************/ +void fall_det_end_debug(){ haptic = 0; // Turn off Haptic BLU_Led = LED_OFF; // Turn off HexiHeart Blue LED - Led_clk2 = 0; // Turn off LED2 on docking station on + Led_clk1 = 0; // Turn off LED1, on docking station fall_config(21); // reads interrupts to clear old interupt // oled.Label((uint8_t *)" ",05,70); // clear display at x,y - Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine -} //end fall_det_end interupt routine + Accel_INT1.fall(&fall_detect_debug); // reset accel sensor's int#1 to active low and proper int routine +} //end fall_det_end_debug interupt routine /***************************************************************************** -Name: impact_detect() -Purpose: Interupt rutine called when accelerometer IC has detected a vector +Name: impact_detect_debug() +Purpose: Debug Interupt routine called when accelerometer IC has detected a vector magnitude acceleration >= 3.0g - +Inputs: interupt2 of accel sensor ******************************************************************************/ - -void impact_detect(){ +void impact_detect_debug(){ if(Fall_Alert == 1){ accel.acquire_accel_data_g(Accel_Data_Event); haptic = 1; - Led_clk3 = 1; // Turn LED2 on docking station on + Led_clk2 = 1; // Turn LED2 on docking station on Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED if (OLED_ON == 0) { @@ -2542,23 +2651,24 @@ sprintf(text_1,"Impact:%2.2fg",Accel_Mag); oled.Label((uint8_t *)text_1,3,20);// text_1 at x,y wait(0.1); - Led_clk3 = 0; // Turn LED2 off docking station on + Led_clk2 = 0; // Turn LED2 off docking station on haptic = 0; }// end if -}//end impact_detect interupt routine +}//end impact_detect_debug interupt routine /***************************************************************************** -Name: motion_detect() -Purpose: Interupt rutine called when gyro IC has detected motion >= 50 deg/sec +Name: motion_detect_debug() +Purpose: Debug Interupt routine called when gyro IC has detected motion >= 50 deg/sec in order to see if fall-impact resulted in motion-less person. +Inputs: interupt1 of gyro sensor ******************************************************************************/ -void motion_detect(){ +void motion_detect_debug(){ float Gyro_Data_Event[3]; // store right away to see what it was if(Fall_Alert == 1 && Fall_Alert_Mode > 2){// only service interupt if automatic fall detect is selected by user gyro.acquire_gyro_data_dps(Gyro_Data_Event); Gyro_Mag = (abs(Gyro_Data_Event[0])+abs(Gyro_Data_Event[1])+abs(Gyro_Data_Event[2])); haptic = 1; - Led_clk1 = 1; // Turn LED1 on docking station on + Led_clk3 = 1; // Turn on LED3, on docking station Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED if (OLED_ON == 0) { @@ -2572,21 +2682,374 @@ } // endif sprintf(text_1,"Motion:%4.0f d/s",Gyro_Mag); oled.Label((uint8_t *)text_1,3,20);// text_1 at x,y + gyro_sensor_config(13); // reset motion counter wait(0.1); - Led_clk1 = 0; // Turn LED1 off docking station on + Led_clk3 = 0; // Turn LED3 off docking station on haptic = 0; }// end if +}//end motion_detect_debug interupt routine + +//********** Full sequential fall interup routines below ********************* +/***************************************************************************** +Name: fall_detect() +Purpose: Interupt routine called when accelerometer IC has detected a +free-fall (accel <= 0.5g) +Inputs: interupt1 of accel sensor +******************************************************************************/ +void fall_detect(){// fall detect interupt routine +if(Fall_Alert == 1 && Led_clk2 == 0){// are we looking for falls? Have we already det impact? + accel.acquire_accel_data_g(Accel_Data_Event); + f_time.reset(); + f_time.start(); //start measuring fall time + for (int i=0; i<7; i++){ + Fall_Event_Data[i] = 0; // clear any old information + }//end for loop + +// Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED + //time_t seconds = time(NULL); + //store time into Fall_Event_Data buffer + Fall_Event_Data[0] = 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]))); + Led_clk1 = 1; // Turn on LED1, on docking station + //Led_clk2 = 0; // Turn off LED2, on docking station + Accel_INT1.rise(&fall_det_end); // look for end of fall by reseting accel sensor's int#1 to active high + // Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine + Accel_INT2.fall(&impact_detect); //Start looking for vector impacts + // Gyro_INT1.fall(&motion_detect); // Gyro sensor's int#1 (PTD1) calls interupt routine + chk_fall.attach(&chkfall,(0.5)); //initialize ticker to check for end of fall every half second + +}// end if +}//end fall_detect interupt routine + + +/***************************************************************************** +Name: chkfall() +Purpose: Ticker interupt routine called every 0.5 Seconds (after a free-fall has been detected) +to check to see if we've missed the interupt indicating the free-fall event is over. +Inputs: chk_fall Ticker +******************************************************************************/ +void chkfall(){// Ticker fall-end detect routine to see if we missed interupt + if(Accel_INT1 == 0){//fall still active + accel.acquire_accel_data_g(Accel_Data_Event); + 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]))); + if (Accel_Mag < Fall_Event_Data[0]){ + Fall_Event_Data[0] = Accel_Mag;// if fall is less than previous re-store value + }//endif + }//endif + else{//fall interupt off + f_time.stop(); // stop fall timer + chk_fall.detach(); //stop ticker, interupt caught end of fall + chk_fall.attach(&clear_fall,(2.0)); //initialize ticker to check no impact in 2 seconds + Accel_INT1.fall(NULL); // turn off accel sensor's int#1 + }//end else + +}//end chkfall ticker interupt routine + +/***************************************************************************** +Name: interupt_off() +Purpose: Interupts are supposed to be turned off by using "Int_name.fall(NULL);", but +that doesn't seem to work. +******************************************************************************/ +void interupt_off(){// turn off an interupt by substituting this one +// Do nothing +}//end interupt_off routine + + +/***************************************************************************** +Name: fall_det_end() +Purpose: Interupt routine called when accelerometer IC has detected that the +free-fall acceleration has ended (accel now >0.5g) +Inputs: interupt1 of accel sensor +******************************************************************************/ +void fall_det_end(){ // accel detected end of free-fall + f_time.stop(); // stop fall timer + chk_fall.detach(); //stop ticker, interupt caught end of fall + chk_fall.attach(&clear_fall,(Fall_Impact_Max_Wait_Time)); //initialize ticker to check no impact in 2 seconds + // fall_config(21); // reads interrupts to clear old interupt + Accel_INT1.fall(NULL); // Turn off accel sensor's int#1 +} //end fall_det_end interupt routine + + +/***************************************************************************** +Name: clear_fall() +Purpose: Ticker interupt routine called to clear/cancel fall detection routine if +no impact was detected withing 2.0 seconds after the free-fall event +Inputs: chk_fall Ticker +******************************************************************************/ +void clear_fall(){// Ticker routine to clear_fall detect routine if no impact in 2.0 seconds after free-fall event is over + if(Led_clk2 == 1){// have we detected an impact? + chk_fall.detach(); //just stop ticker + }//endif + else{ + Accel_INT1.fall(&fall_detect); // reset accel sensor's int#1 to active low and reset for next fall + Accel_INT2.fall(NULL); //Stop looking for vector impacts, + Led_clk1 = 0; // Turn off LED1, on docking station + }//end else +}//end clear_fall ticker interupt routine + + +/***************************************************************************** +Name: impact_detect() +Purpose: Interupt routine called when accelerometer IC has detected a vector +magnitude acceleration >= 3.0g +Inputs: interupt2 of accel sensor +******************************************************************************/ +void impact_detect(){// we may detect multiple impacts, this needs to work from last impact detected + if(Fall_Alert == 1){ + f_time.stop(); // stop fall timer + accel.acquire_accel_data_g(Accel_Data_Event); + chk_fall.detach(); //detach/stop ticker, impact was detected + wait(0.1); + Fall_Event_Data[1] = f_time;// store free-fall time + Led_clk2 = 1; // Turn on LED2, on docking station + gyro_sensor_config(13); // reset motion counter + Gyro_INT1.fall(&motion_detect); // Start looking for motion + chk_motion.attach(&chkmotion,(Min_Movement_duration)); //initialize ticker to check for motion during Min_Movement_duration + } // endif + 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]))); + if(Accel_Mag>Fall_Event_Data[2]){ + Fall_Event_Data[2] = Accel_Mag; // if impact accel is higher than last measured, update + }//endif + //wait(0.1); + //Led_clk3 = 1; // Turn on LED3, on docking station - we're looking for motion +}//end impact_detect interupt routine + +/***************************************************************************** +Name: motion_detect() +Purpose: Interupt routine called when gyro IC has detected motion >= 50 deg/sec +in order to see if fall-impact resulted in motion-less person. +Inputs: interupt1 of gyro sensor +******************************************************************************/ +void motion_detect(){// 2 seconds of motion was detected + chk_motion.detach(); //stop ticker, we've detected motion + Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine + Accel_INT2.fall(NULL); //Reset for next event + Gyro_INT1.fall(NULL); //Reset for next event + //wait(0.1); + Led_clk1 = 0; // Turn off LED1, on docking station + Led_clk2 = 0; // Turn off LED2, on docking station + }//end motion_detect interupt routine + +/***************************************************************************** +Name: chkmotion() +Purpose: Ticker interupt routine called when 60sec window has elapsed without +2seconds of motion being detected. +Inputs: chk_motion Ticker +******************************************************************************/ +void chkmotion(){// if we got here we didn't detect motion + // + chk_motion.detach(); //stop ticker + Screen_Num = 47; //Change to screen 47 (Fall diag screen) + Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED + if (OLED_ON == 0) { + OLED_ON = 1; // Screen was off, set to On + } // endif + update_display(); // + chk_motion.attach(&chk_help_needed,(Do_You_Need_Help_Time)); //initialize ticker to send automatic alert + haptic = 1; + wait(0.2);// very aggressive hapic + haptic = 0; + wait(0.2); + haptic = 1; + wait(0.2);// very aggressive hapic + haptic = 0; + wait(0.2); + haptic = 1; + wait(0.2);// very aggressive hapic + haptic = 0; + + }//end of chkmotion ticker interupt routine + +/***************************************************************************** +Name: chk_help_needed() +Purpose: Ticker interupt routine called when X sec window has elapsed without +user dimissing "Are you OK" screen, sends automatic alert. +Inputs: chk_motion Ticker +******************************************************************************/ +void chk_help_needed(){// Were they able to dismiss on their own? + // + chk_motion.detach(); //stop ticker + if (Screen_Num == 47){// are we still on screen 47? + Screen_Num = 48; //Change to screen 48 and send alert + Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED to keep it on + if (OLED_ON == 0) { + OLED_ON = 1; // Screen was off, set to On + } // endif + update_display(); + oled_text_properties_t textProperties = {0}; + oled.GetTextProperties(&textProperties); + textProperties.fontColor = COLOR_RED; + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"No responce!", 5, 20); + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + Send_Alert(2); // send alert type two + haptic = 1; + wait(0.5);// very aggressive hapic + haptic = 0; + wait(0.2); + haptic = 1; + wait(0.5);// very aggressive hapic + haptic = 0; + wait(0.2); + haptic = 1; + wait(0.5);// very aggressive hapic + haptic = 0; + } // endif + + }//end of chkmotion ticker interupt routine + + +/***************************************************************************** +Name: Send_Alert() +Purpose: routine used to store and send alert +Inputs: int value from 0 to 256 +0=Panic, 1=Fall+asked for help, 2=Fall+No responce, 3=? +Returns: None +******************************************************************************/ +void Send_Alert(uint8_t Num){ + + // store alert + // transmit alert + + }//end Send_Alert routine + /***************************************************************************** Name: fall_config() +Purpose: routine used to set accelerometer and gyro sensors' internal registers for chip +level interrupts +Inputs: int value from 0 to 256 +Returns: None +******************************************************************************/ +void fall_config(uint8_t Num){ // this is more than just accel config +// use case switches here to configure for +switch(Num) { + case 0: {// put in standby + accel_sensor_config(0); // set accel sensor to standby + /*For lowest accel power ~2uA in standby mode */ + gyro_sensor_config(0); // set gyro sensor to standby + /*For lowest gyro power ~2.8uA in standby mode */ + Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1 + Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2 + Gyro_INT1.fall(NULL); // Turn off Gyro sensor's int#1 + break; + }// end of case 0 + + case 1: {// configure for free-fall int only + accel_sensor_config(1); // set accel sensor for free-fall + gyro_sensor_config(0); // set gyro sensor to standby + Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1 + Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2 + Gyro_INT1.fall(NULL); // Turn off Gyro sensor's int#1 + + Accel_INT1.fall(&fall_detect_debug); // Accel sensor's int#1 calls interupt routine + break; + }// end of case 1 + + case 2: {// configure for vector impact only + accel_sensor_config(2); // set accel sensor vector impact only + gyro_sensor_config(0); // set gyro sensor to standby + Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1 + // Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2 + Gyro_INT1.fall(NULL); // Turn off Gyro sensor's int#1 + Accel_INT2.fall(&impact_detect_debug); //Accel sensor's int#2 calls interupt routine + + break; + }// end of case 2 + + case 3: {// configure for motion int only + accel_sensor_config(0); // set accel sensor vector impact only + gyro_sensor_config(3); // set gyro sensor to standby + Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1 + Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2 + Gyro_INT1.fall(&motion_detect_debug); // Gyro sensor's int#1 (PTD1) calls interupt routine + break; + }// end of case 3 + + case 4: {// configure FFMT for free-fall event AND config for vector impact + accel_sensor_config(4); // set accel sensor Free-fall and vector impact + gyro_sensor_config(3); // set gyro sensor motion + Accel_INT1.fall(&fall_detect_debug); // Accel sensor's int#1 calls interupt routine + Accel_INT2.fall(&impact_detect_debug); //Accel sensor's int#2 calls interupt routine + Gyro_INT1.fall(&motion_detect_debug); // Gyro sensor's int#1 (PTD1) calls interupt routine + break; + }// end of case 4 + + case 5: {// configure for sequential free-fall, vector impact then motion + accel_sensor_config(4); // set accel sensor Free-fall and vector impact + gyro_sensor_config(3); // set gyro sensor motion + Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine + Accel_INT2.fall(NULL); //Accel sensor's int#2 calls interupt routine + Gyro_INT1.fall(NULL); // Gyro sensor's int#1 (PTD1) calls interupt routine + break; + }// end of case 4 + + case 10: {// reset IC + accel_sensor_config(10); // reset accel sensor + gyro_sensor_config(10); // reset gyro sensor + break; + }// end case 10 + + case 11: {// wake both sensors for simple data read, they were in stanby + accel_sensor_config(11); // set accel sensor active for read + gyro_sensor_config(11); // set accel sensor active for read + break; + }// end of case 11 + + case 12: {// put into standby for low power + accel_sensor_config(12); // set accel sensor to standby + gyro_sensor_config(12); // set gyro sensor to standby + break; + }// end of case 112 + + case 20: {// read INT_Source to clear VECM int, shouldn't have to do this + // This was not working for me but it was due to me using the wrong FXOS8700_I2C_ADDRESS_ + char d[2];//, data_byte_[1]; + d[0] = 0x0c; // 0x0c is INT_Source Reg + i2c_bus1.write(FXOS8700_I2C_ADDRESS_,d,1,true); // "true" is needed to prevent stop + wait(0.01); + if(i2c_bus1.read(FXOS8700_I2C_ADDRESS_,d,1) == 1){ // read Who am I Reg for debug + sprintf(text_1," INT_Read_Err "); + oled.Label((uint8_t *)text_1,5,50); // Display error at x,y + wait(1); // wait 1 seconds + }//endif + break; + }// end of case 20 + + case 21: {// read A_FFMT_SRC reg to clear FFMT int, shouldn't have to do this + // This was not working for me but it was due to me using the wrong FXOS8700_I2C_ADDRESS_ + char d[2];//, data_byte_[1]; + d[0] = 0x16; // 0x16 is A_FFMT_SRC Reg + i2c_bus1.write(FXOS8700_I2C_ADDRESS_,d,1,true); // "true" is needed to prevent stop + wait(0.01); + if(i2c_bus1.read(FXOS8700_I2C_ADDRESS_,d,1) == 1){ // read Who am I Reg for debug + sprintf(text_1," INT_Read_Err "); + oled.Label((uint8_t *)text_1,5,50); // Display error at x,y + wait(1); // wait 1 seconds + }//endif + break; + }// end of case 21 + + default: { + oled.Label((uint8_t *)" Mode? ",30,60); // Display "mode" at x,y + // unknown config + break; + } +}// end switch + +}// end Fall_config + + +/***************************************************************************** +Name: accel_sensor_config() Purpose: Used to set accelerometer IC's internal registers to set up chip level interrupts Inputs: int value from 0 to 256 Returns: None ******************************************************************************/ -void fall_config(uint8_t Num){ // this is more than just accel config +void accel_sensor_config(uint8_t Num){ // use case switches here to configure for switch(Num) { case 0: {// put in standby @@ -2958,7 +3421,7 @@ 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 *)"Acc_Reset",20,60); // Display "reset" at x,y + // oled.Label((uint8_t *)"Acc_Reset",20,60); // Display "reset" at x,y break; }// end case 10 @@ -3023,7 +3486,7 @@ } }// end switch -}// end Fall_config +}// end accel_sensor_cconfig /***************************************************************************** Name: gyro_sensor_config() @@ -3040,7 +3503,7 @@ /*For lowest power ~2.8uA in standby mode */ char d[2]; d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 - d[1] = 0x08; //Puts device in standby mode + d[1] = 0b00001100; //puts device in standby mode and leaves ODR set to 100Hz if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ oled.Label((uint8_t *)"gyr_err0a",20,45); // Display "error" at x,y wait(3.0); // display for 3 seconds @@ -3048,7 +3511,7 @@ break; }// end of case 0 - case 1: {// Fall_Alert mode=1 or 2, put in active mode se we can read gyro measurments + case 1: {// Fall_Alert mode=1, put in active mode se we can read gyro measurments char d[2]; d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 d[1] = 0x00; //Puts device in standby mode @@ -3071,30 +3534,7 @@ break; }// end of case 1 - case 2: {// Fall_Alert mode=1 or 2, put in active mode se we can read gyro measurments - char d[2]; - d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 - d[1] = 0x00; //Puts device in standby mode - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err2a",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - d[0] = FXAS21002_CTRL_REG0; //CTRL_REG0=0x0d - d[1] = 0x00; //sets FS =+/- 2000 dps - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err2b",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 - d[1] = 0x0e; //0x0e puts device in active mode with ODR = 100Hz - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err2c",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - break; - }// end of case 2 - - case 3: {// Fall_Alert mode 3 or 4, set up interupt, put in active mode + case 3: {// Fall_Alert mode 3, set up interupt, put in active mode char d[2]; d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 d[1] = 0x00; //0x08 puts device in standby mode @@ -3162,78 +3602,7 @@ wait(3.0); // display for 3 seconds }//end if break; - }// end of case 2 - - case 4: {// Fall_Alert mode 3 or 4, set up interupt, put in active mode - char d[2]; - d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 - d[1] = 0x00; //0x08 puts device in standby mode - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - - // set RT_CFG reg 0x0e - Rate int config - d[0] = 0x0e; //set RT_CFG reg 0x0e - Rate int config - d[1] = 0b00000111; // enable x,y,z axis - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4a",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - - // set RT_THS reg 0x10 - Rate Threshold value - d[0] = 0x10; //set RT_THS reg 0x10 - Rate Threshold config - // d[1] = 0b00000111; // bit7=couter mode(1=clr,0=dec), rate Tresh(dps)=(THS+1)*Sensitivity(dps/LSB - // Sensitivity(dps/LSB), we should have mdps/LSB=62.50 or a full range of +/- 2000 dps - // Movement_Thresh 50 dps=(THS+1)*256*Sensitivity(dps/LSB) => THS = Movement_Thresh/(16.0f)-1 - // We specified that 50 dps was the magnitude some of all 3 axis so THS is 1/3 of that - d[1] = (uint8_t)((Movement_Thresh/(3*16.0f))-1); // Movement_Thresh 50 dps setting Tresh(dps)=(THS+1)*256*Sensitivity(dps/LSB) - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4b",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - - // set RT_COUNT reg 0x11 - Rate Threshold counter - d[0] = 0x11; //set RT_COUNT reg 0x11 - Rate Threshold counter - // d[1] = 0b10000000; // debounce count value (Count=10, ODR=100Hz => 100mS) - d[1] = (uint8_t)(Min_Movement_Time/0.01f); // debounce count value (at ODR=100Hz, each count = 10mS) 2.55s=255 - // need to calculate and store this value - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4c",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - - // set CTRL_REG2 reg 0x14 - Int config - d[0] = 0x14; //set CTRL_REG2 reg 0x14 - Int config - d[1] = 0b01110000; // enable RT &FIFO interupts, int=act_low, push/pull - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4d",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - - // set CTRL_REG3 reg 0x15 - Auto inc config, external power, FSR <=don't need? - d[0] = 0x15; //CTRL_REG3 reg 0x15 - d[1] = 0x00; //Auto inc config, external power, FSR - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4e",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - - d[0] = FXAS21002_CTRL_REG0; //CTRL_REG0=0x0d - d[1] = 0x00; //sets FS=0,mdps/LSB=62.50 => +/- 2000 dps - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4f",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1 0x13 - Op mode, ODR selection, reset - d[1] = 0b00001110; //0x0e puts device in active mode and sets ODR to 100Hz - if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ - oled.Label((uint8_t *)"gyr_err4g",20,45); // Display "error" at x,y - wait(3.0); // display for 3 seconds - }//end if - break; - }// end of case 4 - + }// end of case 3 case 10: {// reset Gyro IC char d[2]; @@ -3243,14 +3612,14 @@ oled.Label((uint8_t *)"gyr_err10a",20,45); // Display "error" at x,y wait(3.0); // display for 3 seconds }//end if - oled.Label((uint8_t *)"G_Reset ",30,45); // Display "reset" at x,y + // oled.Label((uint8_t *)"G_Reset ",30,45); // Display "reset" at x,y break; }// end case 10 - case 11: {// read gyro measurments + case 11: {// set sensor to active to read gyro measurments char d[2]; d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 - d[1] = 0x0e; //0x0e puts device in active mode with ODR = 100Hz + d[1] = 0b00001110; //0x0e puts device in active mode with ODR = 100Hz if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ oled.Label((uint8_t *)"gyr_err11a",20,45); // Display "error" at x,y wait(3.0); // display for 3 seconds @@ -3262,13 +3631,31 @@ /*For lowest power ~2.8uA in standby mode */ char d[2]; d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 - d[1] = 0x08; //Puts device in standby mode + d[1] = 0b00001100; //puts device in standby mode and leaves ODR set to 100Hz if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ oled.Label((uint8_t *)"gyr_err12a",20,45); // Display "error" at x,y wait(3.0); // display for 3 seconds }//end if break; }// end of case 12 + + case 13: {// put in standby then back to active, to clear counter + /*For lowest power ~2.8uA in standby mode */ + char d[2]; + d[0] = FXAS21002_CTRL_REG1; //CTRL_REG1=0x13 + d[1] = 0b00001100; //puts device in standby mode and leaves ODR set to 100Hz + if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)"gyr_err12a",20,45); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + d[1] = 0b00001110; //0x0e puts device in active mode with ODR = 100Hz + if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){ + oled.Label((uint8_t *)"gyr_err11a",20,45); // Display "error" at x,y + wait(3.0); // display for 3 seconds + }//end if + + break; + }// end of case 13 default: { oled.Label((uint8_t *)"Gyro_Mode?",20,45); // Display "mode" at x,y @@ -3354,11 +3741,12 @@ d[1] = 0b01000000; //resets IC if(i2c_bus0.write(0xaf, d, 2) ==1){ oled.Label((uint8_t *)"MAX_W_Err10a",5,1); // Display "error" at x,y + wait(2.0); // wait 0 seconds }//end if else { - oled.Label((uint8_t *)"MAX_Reset",20,30); // Display "reset" at x,y + // oled.Label((uint8_t *)"MAX_Reset",20,30); // Display "reset" at x,y } - wait(0.1); // wait 5 seconds + wait(0.01); // wait 0.01 seconds break; }// end of case 10 @@ -3461,6 +3849,22 @@ Heat_Index_Calculation(); sprintf(text,"%i",heat_index); oled.TextBox((uint8_t *)text,3,80,15,15); //show HI in a 15px by 15px text box at x=3, y=80 + + textProperties.fontColor = COLOR_GRAY; + if(Fall_Alert == 1){ + textProperties.fontColor = COLOR_GREEN; // is Fall protection on? + } + if(Fall_Alert == 1 && Led_clk1 == 1){ + textProperties.fontColor = COLOR_YELLOW; // is Fall detected? + } + if(Fall_Alert == 1 && Led_clk1 == 1 && Led_clk2 == 1){ + textProperties.fontColor = COLOR_RED; // is impact detected? + } + oled.SetTextProperties(&textProperties); + oled.Label((uint8_t *)"FAP",1,0); //Display "FAP" at x,y + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); + break; }// end case 0