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 |
