# HG changeset patch # User Ideenmodellierer # Date 1725118117 -7200 # Node ID 5b675077ccfb5abf24398c717aafaed9899d1631 # Parent f012fcd7f465764c3de9917b559dfa1f1bbb9d87 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. diff -r f012fcd7f465 -r 5b675077ccfb Small_CPU/Src/scheduler.c --- a/Small_CPU/Src/scheduler.c Thu Aug 29 15:01:30 2024 +0200 +++ b/Small_CPU/Src/scheduler.c Sat Aug 31 17:28:37 2024 +0200 @@ -43,6 +43,7 @@ #include "tm_stm32f4_otp.h" #include "externalInterface.h" #include "uart.h" +#include "math.h" /* uncomment to enable restoting of last known date in case of a power loss (RTC looses timing data) */ /* #define RESTORE_LAST_KNOWN_DATE */ @@ -51,6 +52,14 @@ #define START_DIVE_MOUNTAIN_MODE_BAR (0.88f) #define START_DIVE_IMMEDIATLY_BAR (1.16f) +/* Ascent rate calculation */ +typedef enum +{ + ASCENT_NONE = 0, + ASCENT_RISING, + ASCENT_FALLING, +} AscentStates_t; + /* Private types -------------------------------------------------------------*/ const SGas Air = {79,0,0,0,0}; @@ -93,6 +102,7 @@ void copyExtADCdata(); void copyExtCO2data(); static void schedule_update_timer_helper(int8_t thisSeconds); +static void evaluateAscentSpeed(void); uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow); void scheduleSetDate(SDeviceLine *line); @@ -480,11 +490,8 @@ { uint32_t ticksdiff = 0; uint32_t lasttick = 0; - uint32_t lastPressureTick = 0; - uint32_t tickPressureDiff = 0; uint8_t extAdcChannel = 0; uint8_t counterAscentRate = 0; - float lastPressure_bar = 0.0f; global.dataSendToMaster.mode = MODE_DIVE; global.deviceDataSendToMaster.mode = MODE_DIVE; uint8_t counter_exit = 0; @@ -558,17 +565,8 @@ counterAscentRate++; if(counterAscentRate == 4) { - tickPressureDiff = time_elapsed_ms(lastPressureTick,lasttick); /* Calculate ascent rate every 400ms use timer to take care for small time shifts */ - if(tickPressureDiff != 0) - { - global.lifeData.pressure_ambient_bar = get_pressure_mbar() / 1000.0f; - if(lastPressure_bar >= 0) - { - global.lifeData.ascent_rate_meter_per_min = (lastPressure_bar - global.lifeData.pressure_ambient_bar) * (60000.0 / tickPressureDiff) * 10; /* bar * 10 = meter */ - } - } - lastPressure_bar = global.lifeData.pressure_ambient_bar; - lastPressureTick = lasttick; + global.lifeData.pressure_ambient_bar = get_pressure_mbar() / 1000.0f; + evaluateAscentSpeed(); counterAscentRate = 0; } copyPressureData(); @@ -606,7 +604,7 @@ /** counter_exit allows safe exit via button for testing - * and demo_mode is exited too if aplicable. + * and demo_mode is exited too if applicable. */ if(global.dataSendToMaster.mode == MODE_ENDDIVE) { @@ -620,6 +618,7 @@ if(is_ambient_pressure_close_to_surface(&global.lifeData)) { + global.lifeData.counterSecondsShallowDepth++; if((global.lifeData.counterSecondsShallowDepth >= global.settings.timeoutDiveReachedZeroDepth) || ((global.lifeData.dive_time_seconds < 60) && (global.demo_mode == 0)) || (ManualExitDiveCounter)) @@ -657,6 +656,7 @@ // surface break if(is_ambient_pressure_close_to_surface(&global.lifeData)) { + global.lifeData.ascent_rate_meter_per_min = 0; global.lifeData.counterSecondsShallowDepth++; if(global.lifeData.counterSecondsShallowDepth > 3) // time for main cpu to copy to apnea_last_dive_time_seconds { @@ -1814,6 +1814,78 @@ return retval; } +void evaluateAscentSpeed() +{ + static uint32_t lastPressureTick = 0; + static float lastPressure_bar = 0.0f; + static AscentStates_t ascentState = ASCENT_NONE; + static uint8_t ascentStableCnt = 0; + uint32_t tickPressureDiff = 0; + uint32_t lasttick = HAL_GetTick(); + float localAscentRate = 0.0; + + tickPressureDiff = time_elapsed_ms(lastPressureTick,lasttick); /* Calculate ascent rate every 400ms use timer to take care for small time shifts */ + if(tickPressureDiff != 0) + { + if(lastPressure_bar >= 0) + { + localAscentRate = (lastPressure_bar - global.lifeData.pressure_ambient_bar) * (60000.0 / tickPressureDiff) * 10; /* bar * 10 = meter */ + if(fabs(localAscentRate) < 1.0) + { + ascentState = ASCENT_NONE; + ascentStableCnt = 0; + } + else if(localAscentRate > 0.0) + { + if(ascentState != ASCENT_FALLING) + { + if(ascentStableCnt < 5) + { + ascentStableCnt++; + } + else + { + ascentState = ASCENT_RISING; + } + } + else + { + ascentState = ASCENT_NONE; + ascentStableCnt = 0; + } + } + else /* must be falling */ + { + if(ascentState != ASCENT_RISING) + { + if(ascentStableCnt < 5) + { + ascentStableCnt++; + } + else + { + ascentState = ASCENT_FALLING; + } + } + else + { + ascentState = ASCENT_NONE; + ascentStableCnt = 0; + } + } + if(ascentState != ASCENT_NONE) + { + global.lifeData.ascent_rate_meter_per_min = localAscentRate; + } + else + { + global.lifeData.ascent_rate_meter_per_min = 0; + } + } + } + lastPressure_bar = global.lifeData.pressure_ambient_bar; + lastPressureTick = lasttick; +} /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/