Mercurial > public > ostc4
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 |