-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Voltage detection method #13350
Voltage detection method #13350
Conversation
Do you want to test this code? You can flash it directly from Betaflight Configurator:
WARNING: It may be unstable. Use only for testing! |
src/main/sensors/voltage.c
Outdated
@@ -201,7 +206,11 @@ void voltageMeterADCRefresh(void) | |||
void voltageMeterADCRead(voltageSensorADC_e adcChannel, voltageMeter_t *voltageMeter) | |||
{ | |||
voltageMeterADCState_t *state = &voltageMeterADCStates[adcChannel]; | |||
|
|||
|
|||
if (millis() - voltageMeter->prevDisplayTime > PREV_DISPLAY_FILTERED_TIME_DIFF) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit problematic - value is stored at 1s intervals (samples at 50Hz), but comparison is done at batteryUpdatePresence (20Hz) rate. So distance between compared samples will be dependent on synchronization of both tasks (and then increased over 1s interval).
Either compare only once per second(per PREV_DISPLAY_FILTERED_TIME_DIFF) so that compared samples are PREV_DISPLAY_FILTERED_TIME_DIFF apart, or compare each filtered sample (roughly equivalent to current worst case) or use some better statistics (sum sqr() of differences over PREV_DISPLAY_FILTERED_TIME_DIFF interval?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to sync with battery update task, changed a bunch, please review again
src/main/sensors/voltage.c
Outdated
@@ -201,7 +206,11 @@ void voltageMeterADCRefresh(void) | |||
void voltageMeterADCRead(voltageSensorADC_e adcChannel, voltageMeter_t *voltageMeter) | |||
{ | |||
voltageMeterADCState_t *state = &voltageMeterADCStates[adcChannel]; | |||
|
|||
|
|||
if (millis() - voltageMeter->prevDisplayTime > PREV_DISPLAY_FILTERED_TIME_DIFF) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO batteryUpdateVoltage is better place for this.,
Also, cmp32 for timestamp with overflow (I know that 49days is a lot of time. Abut eventually someone will get bitten by it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
@ledvinap i thought about the rss approach. I dont know if we actually need this, but i am about to make some examples and test if it is better for the usecase. |
With a threshold of 10 (100mv), and the suggested debug change, this code works very well now. The maximum error from the stable value is probably less than 50mV, since by the time the difference between two values is only 100mV, the curve has become quite flat. In four tests the maximum difference was 30mV. |
… resilient and synced to update battery task
0b787c7
to
0453ef1
Compare
squashed and ready to be tested :) |
I've tested this carefully. On defaults, it is extremely accurate, and reliable, at detecting average voltage, typically within 30-40mV. Even if the battery is very weak, and the motor 'chimes' cause significant voltage drops (such a battery would be un-flyable), the smoothing on defaults is good enough that an accurate reading is taken. It takes between 3.0 and 4.0 seconds to return an accurate value, with the default Choosing a shorter Provided that the battery is good enough that there is no bad 'droop' during the motor chime period, and typically that is the case, a value of 15 will cut detection time to 2.0 to 2.5s, and we will have a reading in about the time that it takes for the motor chimes to stop. If user experience shows that the detection is reliable with Currently, if the pilot arms before the 'stable' voltage is measured, automatic profile selection will fail. There is no user indication that the stable voltage measurement is complete. Hence the pilot must ensure that they wait about 4s from connecting the LiPo before arming - a couple of seconds after the motor chimes stop. We could implement an arming block, with a warning message in OSD, while the user has enabled auto profile switching and the voltage detection period has not yet completed. I'm not convinced that is necessary. People shouldn't be arming and taking off within 4s of plugging the battery in anyway; gyros need to be calibrated etc. If the display_period is 20, it's closer to 3s, and that should be OK for impatient people. |
change voltage detection method and is voltage stable flag to make it resilient and synced to update battery task Co-authored-by: Eike Ahmels <ea@weslink.de>
@freasy user on discord reported: Beeper issue. It acts like the USB configuration is turned on when it isn't. PR13350 seems to have broken it. PR13352 is OK. Support ID: 389823ab-8305-474c-82ea-0d3192b3e57 |
This reverts commit 744ab45.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I missed this before merging
@@ -159,8 +159,21 @@ void batteryUpdateVoltage(timeUs_t currentTimeUs) | |||
break; | |||
} | |||
|
|||
if (!voltageMeter.isVoltageStable && cmp32(millis(), voltageMeter.prevDisplayFilteredTime) >= PREV_DISPLAY_FILTERED_TIME_DIFF) { | |||
if ((voltageState == BATTERY_NOT_PRESENT || voltageState == BATTERY_INIT) && isVoltageFromBattery()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to isVoltageFromBattery()
, isVoltageStable
is never set unless battery is connected.
@@ -226,11 +232,11 @@ void batteryUpdatePresence(void) | |||
batteryCriticalHysteresisVoltage = (batteryCriticalVoltage > batteryConfig()->vbathysteresis) ? batteryCriticalVoltage - batteryConfig()->vbathysteresis : 0; | |||
lowVoltageCutoff.percentage = 100; | |||
lowVoltageCutoff.startTime = 0; | |||
} else if (voltageState != BATTERY_NOT_PRESENT && isVoltageStable() && !isVoltageFromBat()) { | |||
} else if (voltageState != BATTERY_NOT_PRESENT && voltageMeter.isVoltageStable && !isVoltageFromBattery()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will never never be true: voltageMeter.isVoltageStable && !isVoltageFromBattery()
Detection logic is refactored - battery voltage delta is tested each 50ms, voltage is considered stable when difference of last 10 samples is smaller than 100mV This makes stable threshold more forgiving than betaflight#13350 (time for comparison is 50 instead of 500ms).
…13599) * battery - fix BATTERY_NOT_PRESENT detection, detection logic change Detection logic is refactored - battery voltage delta is tested each 50ms, voltage is considered stable when difference of last 10 samples is smaller than 100mV This makes stable threshold more forgiving than #13350 (time for comparison is 50 instead of 500ms). * battery - improve stable voltage detection - voltageStablePrevFiltered every time delta is exceeded - voltage within range is ANDed over 100ms periods - voltage is stable if it was within range for 10 out of 11 periods - slowly changing voltage will update threshold, but voltage will be considered stable - 1 update/s (100mV/s) is tolerated * battery - fuix typos, improve comments
…etaflight#13599) * battery - fix BATTERY_NOT_PRESENT detection, detection logic change Detection logic is refactored - battery voltage delta is tested each 50ms, voltage is considered stable when difference of last 10 samples is smaller than 100mV This makes stable threshold more forgiving than betaflight#13350 (time for comparison is 50 instead of 500ms). * battery - improve stable voltage detection - voltageStablePrevFiltered every time delta is exceeded - voltage within range is ANDed over 100ms periods - voltage is stable if it was within range for 10 out of 11 periods - slowly changing voltage will update threshold, but voltage will be considered stable - 1 update/s (100mV/s) is tolerated * battery - fuix typos, improve comments
…change (#13623) battery - fix BATTERY_NOT_PRESENT detection, detection logic change (#13599) * battery - fix BATTERY_NOT_PRESENT detection, detection logic change Detection logic is refactored - battery voltage delta is tested each 50ms, voltage is considered stable when difference of last 10 samples is smaller than 100mV This makes stable threshold more forgiving than #13350 (time for comparison is 50 instead of 500ms). * battery - improve stable voltage detection - voltageStablePrevFiltered every time delta is exceeded - voltage within range is ANDed over 100ms periods - voltage is stable if it was within range for 10 out of 11 periods - slowly changing voltage will update threshold, but voltage will be considered stable - 1 update/s (100mV/s) is tolerated * battery - fuix typos, improve comments Co-authored-by: Petr Ledvina <ledvinap@gmail.com>
The isVoltageStable method before compared filtered and unfiltered voltage data to determine if the voltage is stable or not. This lead to multiple instances of wrong detected cell counts, thus profile switching based on cell count was screwed.
This PR changes it so, that the method always uses filtered data to check for stable voltage. Also, the previous value gets set in 1 second intervals. Also, I changed from 200mV to 30mV difference, because filtered values are way more stable.
To test this PR:
Set your quad up for BATTERY debug mode and observe Debug 4, which will go to 1 if the voltage is set stable. It should be some seconds later than before and at a state of really stable voltage.