comparison Small_CPU/Src/scheduler.c @ 881:5b675077ccfb Evo_2_23

Added filtering of ascent speed: In the previous version the ascent speed was simply calculated based of the last measured pressure values. This may lead to unexpected colorchanges of the depth value. To smooth this behavior a filter has been added which evaluates if a movment direction is valid for a certain period of time. If the condition direction is stable then the ascend speed is provided.
author Ideenmodellierer
date Sat, 31 Aug 2024 17:28:37 +0200
parents 3311b720a072
children 2225c467f1e9
comparison
equal deleted inserted replaced
880:f012fcd7f465 881:5b675077ccfb
41 #include "stm32f4xx_hal_rtc_ex.h" 41 #include "stm32f4xx_hal_rtc_ex.h"
42 #include "decom.h" 42 #include "decom.h"
43 #include "tm_stm32f4_otp.h" 43 #include "tm_stm32f4_otp.h"
44 #include "externalInterface.h" 44 #include "externalInterface.h"
45 #include "uart.h" 45 #include "uart.h"
46 #include "math.h"
46 47
47 /* uncomment to enable restoting of last known date in case of a power loss (RTC looses timing data) */ 48 /* uncomment to enable restoting of last known date in case of a power loss (RTC looses timing data) */
48 /* #define RESTORE_LAST_KNOWN_DATE */ 49 /* #define RESTORE_LAST_KNOWN_DATE */
49 50
50 #define INVALID_PREASURE_VALUE (0.0f) 51 #define INVALID_PREASURE_VALUE (0.0f)
51 #define START_DIVE_MOUNTAIN_MODE_BAR (0.88f) 52 #define START_DIVE_MOUNTAIN_MODE_BAR (0.88f)
52 #define START_DIVE_IMMEDIATLY_BAR (1.16f) 53 #define START_DIVE_IMMEDIATLY_BAR (1.16f)
54
55 /* Ascent rate calculation */
56 typedef enum
57 {
58 ASCENT_NONE = 0,
59 ASCENT_RISING,
60 ASCENT_FALLING,
61 } AscentStates_t;
53 62
54 /* Private types -------------------------------------------------------------*/ 63 /* Private types -------------------------------------------------------------*/
55 const SGas Air = {79,0,0,0,0}; 64 const SGas Air = {79,0,0,0,0};
56 65
57 /* Exported variables --------------------------------------------------------*/ 66 /* Exported variables --------------------------------------------------------*/
91 void copyDeviceData(void); 100 void copyDeviceData(void);
92 void copyPICdata(void); 101 void copyPICdata(void);
93 void copyExtADCdata(); 102 void copyExtADCdata();
94 void copyExtCO2data(); 103 void copyExtCO2data();
95 static void schedule_update_timer_helper(int8_t thisSeconds); 104 static void schedule_update_timer_helper(int8_t thisSeconds);
105 static void evaluateAscentSpeed(void);
96 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow); 106 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow);
97 107
98 void scheduleSetDate(SDeviceLine *line); 108 void scheduleSetDate(SDeviceLine *line);
99 109
100 /* Exported functions --------------------------------------------------------*/ 110 /* Exported functions --------------------------------------------------------*/
478 */ 488 */
479 void scheduleDiveMode(void) 489 void scheduleDiveMode(void)
480 { 490 {
481 uint32_t ticksdiff = 0; 491 uint32_t ticksdiff = 0;
482 uint32_t lasttick = 0; 492 uint32_t lasttick = 0;
483 uint32_t lastPressureTick = 0;
484 uint32_t tickPressureDiff = 0;
485 uint8_t extAdcChannel = 0; 493 uint8_t extAdcChannel = 0;
486 uint8_t counterAscentRate = 0; 494 uint8_t counterAscentRate = 0;
487 float lastPressure_bar = 0.0f;
488 global.dataSendToMaster.mode = MODE_DIVE; 495 global.dataSendToMaster.mode = MODE_DIVE;
489 global.deviceDataSendToMaster.mode = MODE_DIVE; 496 global.deviceDataSendToMaster.mode = MODE_DIVE;
490 uint8_t counter_exit = 0; 497 uint8_t counter_exit = 0;
491 498
492 Scheduler.counterSPIdata100msec = 0; 499 Scheduler.counterSPIdata100msec = 0;
556 #endif 563 #endif
557 564
558 counterAscentRate++; 565 counterAscentRate++;
559 if(counterAscentRate == 4) 566 if(counterAscentRate == 4)
560 { 567 {
561 tickPressureDiff = time_elapsed_ms(lastPressureTick,lasttick); /* Calculate ascent rate every 400ms use timer to take care for small time shifts */ 568 global.lifeData.pressure_ambient_bar = get_pressure_mbar() / 1000.0f;
562 if(tickPressureDiff != 0) 569 evaluateAscentSpeed();
563 {
564 global.lifeData.pressure_ambient_bar = get_pressure_mbar() / 1000.0f;
565 if(lastPressure_bar >= 0)
566 {
567 global.lifeData.ascent_rate_meter_per_min = (lastPressure_bar - global.lifeData.pressure_ambient_bar) * (60000.0 / tickPressureDiff) * 10; /* bar * 10 = meter */
568 }
569 }
570 lastPressure_bar = global.lifeData.pressure_ambient_bar;
571 lastPressureTick = lasttick;
572 counterAscentRate = 0; 570 counterAscentRate = 0;
573 } 571 }
574 copyPressureData(); 572 copyPressureData();
575 Scheduler.counterPressure100msec++; 573 Scheduler.counterPressure100msec++;
576 } 574 }
604 decom_oxygen_calculate_otu(&global.lifeData.otu,global.lifeData.ppO2); 602 decom_oxygen_calculate_otu(&global.lifeData.otu,global.lifeData.ppO2);
605 battery_gas_gauge_get_data(); 603 battery_gas_gauge_get_data();
606 604
607 605
608 /** counter_exit allows safe exit via button for testing 606 /** counter_exit allows safe exit via button for testing
609 * and demo_mode is exited too if aplicable. 607 * and demo_mode is exited too if applicable.
610 */ 608 */
611 if(global.dataSendToMaster.mode == MODE_ENDDIVE) 609 if(global.dataSendToMaster.mode == MODE_ENDDIVE)
612 { 610 {
613 counter_exit++; 611 counter_exit++;
614 if(counter_exit >= 2) 612 if(counter_exit >= 2)
618 } 616 }
619 } 617 }
620 618
621 if(is_ambient_pressure_close_to_surface(&global.lifeData)) 619 if(is_ambient_pressure_close_to_surface(&global.lifeData))
622 { 620 {
621
623 global.lifeData.counterSecondsShallowDepth++; 622 global.lifeData.counterSecondsShallowDepth++;
624 if((global.lifeData.counterSecondsShallowDepth >= global.settings.timeoutDiveReachedZeroDepth) || ((global.lifeData.dive_time_seconds < 60) && (global.demo_mode == 0)) 623 if((global.lifeData.counterSecondsShallowDepth >= global.settings.timeoutDiveReachedZeroDepth) || ((global.lifeData.dive_time_seconds < 60) && (global.demo_mode == 0))
625 || (ManualExitDiveCounter)) 624 || (ManualExitDiveCounter))
626 { 625 {
627 global.seconds_since_last_dive = 1; // start counter 626 global.seconds_since_last_dive = 1; // start counter
655 } 654 }
656 655
657 // surface break 656 // surface break
658 if(is_ambient_pressure_close_to_surface(&global.lifeData)) 657 if(is_ambient_pressure_close_to_surface(&global.lifeData))
659 { 658 {
659 global.lifeData.ascent_rate_meter_per_min = 0;
660 global.lifeData.counterSecondsShallowDepth++; 660 global.lifeData.counterSecondsShallowDepth++;
661 if(global.lifeData.counterSecondsShallowDepth > 3) // time for main cpu to copy to apnea_last_dive_time_seconds 661 if(global.lifeData.counterSecondsShallowDepth > 3) // time for main cpu to copy to apnea_last_dive_time_seconds
662 { 662 {
663 global.lifeData.dive_time_seconds = 0; // this apnea dive ends here 663 global.lifeData.dive_time_seconds = 0; // this apnea dive ends here
664 } 664 }
1812 } 1812 }
1813 } 1813 }
1814 return retval; 1814 return retval;
1815 } 1815 }
1816 1816
1817 void evaluateAscentSpeed()
1818 {
1819 static uint32_t lastPressureTick = 0;
1820 static float lastPressure_bar = 0.0f;
1821 static AscentStates_t ascentState = ASCENT_NONE;
1822 static uint8_t ascentStableCnt = 0;
1823 uint32_t tickPressureDiff = 0;
1824 uint32_t lasttick = HAL_GetTick();
1825 float localAscentRate = 0.0;
1826
1827 tickPressureDiff = time_elapsed_ms(lastPressureTick,lasttick); /* Calculate ascent rate every 400ms use timer to take care for small time shifts */
1828 if(tickPressureDiff != 0)
1829 {
1830 if(lastPressure_bar >= 0)
1831 {
1832 localAscentRate = (lastPressure_bar - global.lifeData.pressure_ambient_bar) * (60000.0 / tickPressureDiff) * 10; /* bar * 10 = meter */
1833 if(fabs(localAscentRate) < 1.0)
1834 {
1835 ascentState = ASCENT_NONE;
1836 ascentStableCnt = 0;
1837 }
1838 else if(localAscentRate > 0.0)
1839 {
1840 if(ascentState != ASCENT_FALLING)
1841 {
1842 if(ascentStableCnt < 5)
1843 {
1844 ascentStableCnt++;
1845 }
1846 else
1847 {
1848 ascentState = ASCENT_RISING;
1849 }
1850 }
1851 else
1852 {
1853 ascentState = ASCENT_NONE;
1854 ascentStableCnt = 0;
1855 }
1856 }
1857 else /* must be falling */
1858 {
1859 if(ascentState != ASCENT_RISING)
1860 {
1861 if(ascentStableCnt < 5)
1862 {
1863 ascentStableCnt++;
1864 }
1865 else
1866 {
1867 ascentState = ASCENT_FALLING;
1868 }
1869 }
1870 else
1871 {
1872 ascentState = ASCENT_NONE;
1873 ascentStableCnt = 0;
1874 }
1875 }
1876 if(ascentState != ASCENT_NONE)
1877 {
1878 global.lifeData.ascent_rate_meter_per_min = localAscentRate;
1879 }
1880 else
1881 {
1882 global.lifeData.ascent_rate_meter_per_min = 0;
1883 }
1884 }
1885 }
1886 lastPressure_bar = global.lifeData.pressure_ambient_bar;
1887 lastPressureTick = lasttick;
1888 }
1817 1889
1818 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/ 1890 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
1819 1891