mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-26 01:35:35 +03:00
Add power limits (#6929)
* Add power limits * condition USE_ADC * Minor changes * Increase max burst time to 5m
This commit is contained in:
parent
e2052a7c8f
commit
e5888089a8
15 changed files with 557 additions and 18 deletions
|
@ -214,6 +214,17 @@
|
||||||
| inav_w_z_surface_v | 6.1 | 0 | 100 | |
|
| inav_w_z_surface_v | 6.1 | 0 | 100 | |
|
||||||
| iterm_windup | 50 | 0 | 90 | Used to prevent Iterm accumulation on during maneuvers. Iterm will be dampened when motors are reaching it's limit (when requested motor correction range is above percentage specified by this parameter) |
|
| iterm_windup | 50 | 0 | 90 | Used to prevent Iterm accumulation on during maneuvers. Iterm will be dampened when motors are reaching it's limit (when requested motor correction range is above percentage specified by this parameter) |
|
||||||
| ledstrip_visual_beeper | OFF | | | |
|
| ledstrip_visual_beeper | OFF | | | |
|
||||||
|
| limit_attn_filter_cutoff | 1.2 | | 100 | Throttle attenuation PI control output filter cutoff frequency |
|
||||||
|
| limit_burst_current | 0 | | 4000 | Burst current limit (dA): the current which is allowed during `limit_burst_current_time` after which `limit_cont_current` will be enforced, set to 0 to disable |
|
||||||
|
| limit_burst_current_falldown_time | 0 | | 3000 | Time slice at the end of the burst time during which the current limit will be ramped down from `limit_burst_current` back down to `limit_cont_current` |
|
||||||
|
| limit_burst_current_time | 0 | | 3000 | Allowed current burst time (ds) during which `limit_burst_current` is allowed and after which `limit_cont_current` will be enforced |
|
||||||
|
| limit_burst_power | 0 | | 40000 | Burst power limit (dW): the current which is allowed during `limit_burst_power_time` after which `limit_cont_power` will be enforced, set to 0 to disable |
|
||||||
|
| limit_burst_power_falldown_time | 0 | | 3000 | Time slice at the end of the burst time during which the power limit will be ramped down from `limit_burst_power` back down to `limit_cont_power` |
|
||||||
|
| limit_burst_power_time | 0 | | 3000 | Allowed power burst time (ds) during which `limit_burst_power` is allowed and after which `limit_cont_power` will be enforced |
|
||||||
|
| limit_cont_current | 0 | | 4000 | Continous current limit (dA), set to 0 to disable |
|
||||||
|
| limit_cont_power | 0 | | 40000 | Continous power limit (dW), set to 0 to disable |
|
||||||
|
| limit_pi_i | 100 | | 10000 | Throttle attenuation PI control I term |
|
||||||
|
| limit_pi_p | 100 | | 10000 | Throttle attenuation PI control P term |
|
||||||
| log_level | ERROR | | | Defines serial debugging log level. See `docs/development/serial_printf_debugging.md` for usage. |
|
| log_level | ERROR | | | Defines serial debugging log level. See `docs/development/serial_printf_debugging.md` for usage. |
|
||||||
| log_topics | 0 | 0 | 4294967295 | Defines serial debugging log topic. See `docs/development/serial_printf_debugging.md` for usage. |
|
| log_topics | 0 | 0 | 4294967295 | Defines serial debugging log topic. See `docs/development/serial_printf_debugging.md` for usage. |
|
||||||
| looptime | 1000 | | 9000 | This is the main loop time (in us). Changing this affects PID effect with some PID controllers (see PID section for details). A very conservative value of 3500us/285Hz should work for everyone. Setting it to zero does not limit loop time, so it will go as fast as possible. |
|
| looptime | 1000 | | 9000 | This is the main loop time (in us). Changing this affects PID effect with some PID controllers (see PID section for details). A very conservative value of 3500us/285Hz should work for everyone. Setting it to zero does not limit loop time, so it will go as fast as possible. |
|
||||||
|
|
|
@ -327,6 +327,8 @@ main_sources(COMMON_SRC
|
||||||
flight/pid.c
|
flight/pid.c
|
||||||
flight/pid.h
|
flight/pid.h
|
||||||
flight/pid_autotune.c
|
flight/pid_autotune.c
|
||||||
|
flight/power_limits.c
|
||||||
|
flight/power_limits.h
|
||||||
flight/rth_estimator.c
|
flight/rth_estimator.c
|
||||||
flight/rth_estimator.h
|
flight/rth_estimator.h
|
||||||
flight/servos.c
|
flight/servos.c
|
||||||
|
|
|
@ -316,6 +316,14 @@ static const OSD_Entry menuOsdElemsEntries[] =
|
||||||
OSD_ELEMENT_ENTRY("ESC TEMPERATURE", OSD_ESC_TEMPERATURE),
|
OSD_ELEMENT_ENTRY("ESC TEMPERATURE", OSD_ESC_TEMPERATURE),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
OSD_ELEMENT_ENTRY("PLIM BURST TIME", OSD_PLIMIT_REMAINING_BURST_TIME),
|
||||||
|
OSD_ELEMENT_ENTRY("PLIM CURR LIMIT", OSD_PLIMIT_ACTIVE_CURRENT_LIMIT),
|
||||||
|
#ifdef USE_ADC
|
||||||
|
OSD_ELEMENT_ENTRY("PLIM POWER LIMIT", OSD_PLIMIT_ACTIVE_POWER_LIMIT),
|
||||||
|
#endif // USE_ADC
|
||||||
|
#endif // USE_POWER_LIMITS
|
||||||
|
|
||||||
OSD_BACK_AND_END_ENTRY,
|
OSD_BACK_AND_END_ENTRY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,8 @@
|
||||||
#define PG_DJI_OSD_CONFIG 1027
|
#define PG_DJI_OSD_CONFIG 1027
|
||||||
#define PG_PROGRAMMING_PID 1028
|
#define PG_PROGRAMMING_PID 1028
|
||||||
#define PG_SECONDARY_IMU 1029
|
#define PG_SECONDARY_IMU 1029
|
||||||
#define PG_INAV_END 1029
|
#define PG_POWER_LIMITS_CONFIG 1030
|
||||||
|
#define PG_INAV_END 1030
|
||||||
|
|
||||||
// OSD configuration (subject to change)
|
// OSD configuration (subject to change)
|
||||||
//#define PG_OSD_FONT_CONFIG 2047
|
//#define PG_OSD_FONT_CONFIG 2047
|
||||||
|
@ -132,4 +133,3 @@
|
||||||
#define PG_ID_INVALID 0
|
#define PG_ID_INVALID 0
|
||||||
#define PG_ID_FIRST PG_CF_START
|
#define PG_ID_FIRST PG_CF_START
|
||||||
#define PG_ID_LAST PG_INAV_END
|
#define PG_ID_LAST PG_INAV_END
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ FILE_COMPILE_FOR_SPEED
|
||||||
#include "flight/imu.h"
|
#include "flight/imu.h"
|
||||||
|
|
||||||
#include "flight/failsafe.h"
|
#include "flight/failsafe.h"
|
||||||
|
#include "flight/power_limits.h"
|
||||||
|
|
||||||
#include "config/feature.h"
|
#include "config/feature.h"
|
||||||
#include "common/vector.h"
|
#include "common/vector.h"
|
||||||
|
@ -892,6 +893,10 @@ void taskMainPidLoop(timeUs_t currentTimeUs)
|
||||||
// FIXME: throttle pitch comp for FW
|
// FIXME: throttle pitch comp for FW
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
powerLimiterApply(&rcCommand[THROTTLE]);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Calculate stabilisation
|
// Calculate stabilisation
|
||||||
pidController(dT);
|
pidController(dT);
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,9 @@
|
||||||
#include "flight/imu.h"
|
#include "flight/imu.h"
|
||||||
#include "flight/mixer.h"
|
#include "flight/mixer.h"
|
||||||
#include "flight/pid.h"
|
#include "flight/pid.h"
|
||||||
#include "flight/servos.h"
|
#include "flight/power_limits.h"
|
||||||
#include "flight/rpm_filter.h"
|
#include "flight/rpm_filter.h"
|
||||||
|
#include "flight/servos.h"
|
||||||
#include "flight/secondary_imu.h"
|
#include "flight/secondary_imu.h"
|
||||||
|
|
||||||
#include "io/asyncfatfs/asyncfatfs.h"
|
#include "io/asyncfatfs/asyncfatfs.h"
|
||||||
|
@ -709,6 +710,10 @@ void init(void)
|
||||||
ioPortExpanderInit();
|
ioPortExpanderInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
powerLimiterInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Considering that the persistent reset reason is only used during init
|
// Considering that the persistent reset reason is only used during init
|
||||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
|
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
|
||||||
|
|
||||||
|
|
|
@ -43,14 +43,15 @@
|
||||||
#include "fc/rc_controls.h"
|
#include "fc/rc_controls.h"
|
||||||
#include "fc/runtime_config.h"
|
#include "fc/runtime_config.h"
|
||||||
|
|
||||||
|
#include "flight/dynamic_lpf.h"
|
||||||
#include "flight/imu.h"
|
#include "flight/imu.h"
|
||||||
#include "flight/mixer.h"
|
#include "flight/mixer.h"
|
||||||
#include "flight/pid.h"
|
#include "flight/pid.h"
|
||||||
#include "flight/wind_estimator.h"
|
#include "flight/power_limits.h"
|
||||||
#include "flight/secondary_imu.h"
|
|
||||||
#include "flight/rpm_filter.h"
|
#include "flight/rpm_filter.h"
|
||||||
|
#include "flight/secondary_imu.h"
|
||||||
#include "flight/servos.h"
|
#include "flight/servos.h"
|
||||||
#include "flight/dynamic_lpf.h"
|
#include "flight/wind_estimator.h"
|
||||||
|
|
||||||
#include "navigation/navigation.h"
|
#include "navigation/navigation.h"
|
||||||
|
|
||||||
|
@ -112,18 +113,29 @@ void taskHandleSerial(timeUs_t currentTimeUs)
|
||||||
void taskUpdateBattery(timeUs_t currentTimeUs)
|
void taskUpdateBattery(timeUs_t currentTimeUs)
|
||||||
{
|
{
|
||||||
static timeUs_t batMonitoringLastServiced = 0;
|
static timeUs_t batMonitoringLastServiced = 0;
|
||||||
timeUs_t BatMonitoringTimeSinceLastServiced = cmpTimeUs(currentTimeUs, batMonitoringLastServiced);
|
timeDelta_t BatMonitoringTimeSinceLastServiced = cmpTimeUs(currentTimeUs, batMonitoringLastServiced);
|
||||||
|
|
||||||
if (isAmperageConfigured())
|
if (isAmperageConfigured()) {
|
||||||
currentMeterUpdate(BatMonitoringTimeSinceLastServiced);
|
currentMeterUpdate(BatMonitoringTimeSinceLastServiced);
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
currentLimiterUpdate(BatMonitoringTimeSinceLastServiced);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_ADC
|
#ifdef USE_ADC
|
||||||
if (feature(FEATURE_VBAT))
|
if (feature(FEATURE_VBAT)) {
|
||||||
batteryUpdate(BatMonitoringTimeSinceLastServiced);
|
batteryUpdate(BatMonitoringTimeSinceLastServiced);
|
||||||
|
}
|
||||||
|
|
||||||
if (feature(FEATURE_VBAT) && isAmperageConfigured()) {
|
if (feature(FEATURE_VBAT) && isAmperageConfigured()) {
|
||||||
powerMeterUpdate(BatMonitoringTimeSinceLastServiced);
|
powerMeterUpdate(BatMonitoringTimeSinceLastServiced);
|
||||||
sagCompensatedVBatUpdate(currentTimeUs, BatMonitoringTimeSinceLastServiced);
|
sagCompensatedVBatUpdate(currentTimeUs, BatMonitoringTimeSinceLastServiced);
|
||||||
|
#if defined(USE_POWER_LIMITS) && defined(USE_ADC)
|
||||||
|
powerLimiterUpdate(BatMonitoringTimeSinceLastServiced);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
batMonitoringLastServiced = currentTimeUs;
|
batMonitoringLastServiced = currentTimeUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3613,3 +3613,68 @@ groups:
|
||||||
default_value: 1
|
default_value: 1
|
||||||
field: dshot_beeper_tone
|
field: dshot_beeper_tone
|
||||||
type: uint8_t
|
type: uint8_t
|
||||||
|
|
||||||
|
- name: PG_POWER_LIMITS_CONFIG
|
||||||
|
type: powerLimitsConfig_t
|
||||||
|
headers: ["flight/power_limits.h"]
|
||||||
|
condition: USE_POWER_LIMITS
|
||||||
|
members:
|
||||||
|
- name: limit_cont_current
|
||||||
|
description: "Continous current limit (dA), set to 0 to disable"
|
||||||
|
default_value: 0
|
||||||
|
field: continuousCurrent
|
||||||
|
max: 4000
|
||||||
|
- name: limit_burst_current
|
||||||
|
description: "Burst current limit (dA): the current which is allowed during `limit_burst_current_time` after which `limit_cont_current` will be enforced, set to 0 to disable"
|
||||||
|
default_value: 0
|
||||||
|
field: burstCurrent
|
||||||
|
max: 4000
|
||||||
|
- name: limit_burst_current_time
|
||||||
|
description: "Allowed current burst time (ds) during which `limit_burst_current` is allowed and after which `limit_cont_current` will be enforced"
|
||||||
|
default_value: 0
|
||||||
|
field: burstCurrentTime
|
||||||
|
max: 3000
|
||||||
|
- name: limit_burst_current_falldown_time
|
||||||
|
description: "Time slice at the end of the burst time during which the current limit will be ramped down from `limit_burst_current` back down to `limit_cont_current`"
|
||||||
|
default_value: 0
|
||||||
|
field: burstCurrentFalldownTime
|
||||||
|
max: 3000
|
||||||
|
- name: limit_cont_power
|
||||||
|
condition: USE_ADC
|
||||||
|
description: "Continous power limit (dW), set to 0 to disable"
|
||||||
|
default_value: 0
|
||||||
|
field: continuousPower
|
||||||
|
max: 40000
|
||||||
|
- name: limit_burst_power
|
||||||
|
condition: USE_ADC
|
||||||
|
description: "Burst power limit (dW): the current which is allowed during `limit_burst_power_time` after which `limit_cont_power` will be enforced, set to 0 to disable"
|
||||||
|
default_value: 0
|
||||||
|
field: burstPower
|
||||||
|
max: 40000
|
||||||
|
- name: limit_burst_power_time
|
||||||
|
condition: USE_ADC
|
||||||
|
description: "Allowed power burst time (ds) during which `limit_burst_power` is allowed and after which `limit_cont_power` will be enforced"
|
||||||
|
default_value: 0
|
||||||
|
field: burstPowerTime
|
||||||
|
max: 3000
|
||||||
|
- name: limit_burst_power_falldown_time
|
||||||
|
condition: USE_ADC
|
||||||
|
description: "Time slice at the end of the burst time during which the power limit will be ramped down from `limit_burst_power` back down to `limit_cont_power`"
|
||||||
|
default_value: 0
|
||||||
|
field: burstPowerFalldownTime
|
||||||
|
max: 3000
|
||||||
|
- name: limit_pi_p
|
||||||
|
description: "Throttle attenuation PI control P term"
|
||||||
|
default_value: 100
|
||||||
|
field: piP
|
||||||
|
max: 10000
|
||||||
|
- name: limit_pi_i
|
||||||
|
description: "Throttle attenuation PI control I term"
|
||||||
|
default_value: 100
|
||||||
|
field: piI
|
||||||
|
max: 10000
|
||||||
|
- name: limit_attn_filter_cutoff
|
||||||
|
description: "Throttle attenuation PI control output filter cutoff frequency"
|
||||||
|
default_value: 1.2
|
||||||
|
field: attnFilterCutoff
|
||||||
|
max: 100
|
||||||
|
|
292
src/main/flight/power_limits.c
Normal file
292
src/main/flight/power_limits.c
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
* This file is part of iNav.
|
||||||
|
*
|
||||||
|
* iNav is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* iNav is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
FILE_COMPILE_FOR_SPEED
|
||||||
|
|
||||||
|
#if defined(USE_POWER_LIMITS)
|
||||||
|
|
||||||
|
#include "flight/power_limits.h"
|
||||||
|
|
||||||
|
#include "build/debug.h"
|
||||||
|
|
||||||
|
#include "common/filter.h"
|
||||||
|
#include "common/maths.h"
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "config/parameter_group.h"
|
||||||
|
#include "config/parameter_group_ids.h"
|
||||||
|
|
||||||
|
#include "drivers/time.h"
|
||||||
|
|
||||||
|
#include "fc/settings.h"
|
||||||
|
|
||||||
|
#include "rx/rx.h"
|
||||||
|
|
||||||
|
#include "sensors/battery.h"
|
||||||
|
|
||||||
|
#define LIMITING_THR_FILTER_TCONST 50
|
||||||
|
|
||||||
|
PG_REGISTER_WITH_RESET_TEMPLATE(powerLimitsConfig_t, powerLimitsConfig, PG_POWER_LIMITS_CONFIG, 0);
|
||||||
|
|
||||||
|
PG_RESET_TEMPLATE(powerLimitsConfig_t, powerLimitsConfig,
|
||||||
|
.continuousCurrent = SETTING_LIMIT_CONT_CURRENT_DEFAULT, // dA
|
||||||
|
.burstCurrent = SETTING_LIMIT_BURST_CURRENT_DEFAULT, // dA
|
||||||
|
.burstCurrentTime = SETTING_LIMIT_BURST_CURRENT_TIME_DEFAULT, // dS
|
||||||
|
.burstCurrentFalldownTime = SETTING_LIMIT_BURST_CURRENT_FALLDOWN_TIME_DEFAULT, // dS
|
||||||
|
#ifdef USE_ADC
|
||||||
|
.continuousPower = SETTING_LIMIT_CONT_POWER_DEFAULT, // dW
|
||||||
|
.burstPower = SETTING_LIMIT_BURST_POWER_DEFAULT, // dW
|
||||||
|
.burstPowerTime = SETTING_LIMIT_BURST_POWER_TIME_DEFAULT, // dS
|
||||||
|
.burstPowerFalldownTime = SETTING_LIMIT_BURST_POWER_FALLDOWN_TIME_DEFAULT, // dS
|
||||||
|
#endif
|
||||||
|
.piP = SETTING_LIMIT_PI_P_DEFAULT,
|
||||||
|
.piI = SETTING_LIMIT_PI_I_DEFAULT,
|
||||||
|
.attnFilterCutoff = SETTING_LIMIT_ATTN_FILTER_CUTOFF_DEFAULT, // Hz
|
||||||
|
);
|
||||||
|
|
||||||
|
static float burstCurrentReserve; // cA.µs
|
||||||
|
static float burstCurrentReserveMax; // cA.µs
|
||||||
|
static float burstCurrentReserveFalldown; // cA.µs
|
||||||
|
static int32_t activeCurrentLimit; // cA
|
||||||
|
static float currentThrAttnIntegrator = 0;
|
||||||
|
static pt1Filter_t currentThrAttnFilter;
|
||||||
|
static pt1Filter_t currentThrLimitingBaseFilter;
|
||||||
|
static bool wasLimitingCurrent = false;
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
static float burstPowerReserve; // cW.µs
|
||||||
|
static float burstPowerReserveMax; // cW.µs
|
||||||
|
static float burstPowerReserveFalldown; // cW.µs
|
||||||
|
static int32_t activePowerLimit; // cW
|
||||||
|
static float powerThrAttnIntegrator = 0;
|
||||||
|
static pt1Filter_t powerThrAttnFilter;
|
||||||
|
static pt1Filter_t powerThrLimitingBaseFilter;
|
||||||
|
static bool wasLimitingPower = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void powerLimiterInit(void) {
|
||||||
|
if (powerLimitsConfig()->burstCurrent < powerLimitsConfig()->continuousCurrent) {
|
||||||
|
powerLimitsConfigMutable()->burstCurrent = powerLimitsConfig()->continuousCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeCurrentLimit = powerLimitsConfig()->burstCurrent;
|
||||||
|
|
||||||
|
uint16_t currentBurstOverContinuous = powerLimitsConfig()->burstCurrent - powerLimitsConfig()->continuousCurrent;
|
||||||
|
burstCurrentReserve = burstCurrentReserveMax = currentBurstOverContinuous * powerLimitsConfig()->burstCurrentTime * 1e6;
|
||||||
|
burstCurrentReserveFalldown = currentBurstOverContinuous * powerLimitsConfig()->burstCurrentFalldownTime * 1e6;
|
||||||
|
|
||||||
|
pt1FilterInit(¤tThrAttnFilter, powerLimitsConfig()->attnFilterCutoff, 0);
|
||||||
|
pt1FilterInitRC(¤tThrLimitingBaseFilter, LIMITING_THR_FILTER_TCONST, 0);
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
if (powerLimitsConfig()->burstPower < powerLimitsConfig()->continuousPower) {
|
||||||
|
powerLimitsConfigMutable()->burstPower = powerLimitsConfig()->continuousPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
activePowerLimit = powerLimitsConfig()->burstPower;
|
||||||
|
|
||||||
|
uint16_t powerBurstOverContinuous = powerLimitsConfig()->burstPower - powerLimitsConfig()->continuousPower;
|
||||||
|
burstPowerReserve = burstPowerReserveMax = powerBurstOverContinuous * powerLimitsConfig()->burstPowerTime * 1e6;
|
||||||
|
burstPowerReserveFalldown = powerBurstOverContinuous * powerLimitsConfig()->burstPowerFalldownTime * 1e6;
|
||||||
|
|
||||||
|
pt1FilterInit(&powerThrAttnFilter, powerLimitsConfig()->attnFilterCutoff, 0);
|
||||||
|
pt1FilterInitRC(&powerThrLimitingBaseFilter, LIMITING_THR_FILTER_TCONST, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t calculateActiveLimit(int32_t value, uint32_t continuousLimit, uint32_t burstLimit, float *burstReserve, float burstReserveFalldown, float burstReserveMax, timeDelta_t timeDelta) {
|
||||||
|
int32_t continuousDiff = value - continuousLimit * 10;
|
||||||
|
float spentReserveChunk = continuousDiff * timeDelta;
|
||||||
|
*burstReserve = constrainf(*burstReserve - spentReserveChunk, 0, burstReserveMax);
|
||||||
|
|
||||||
|
if (powerLimitsConfig()->burstCurrentFalldownTime) {
|
||||||
|
return scaleRangef(MIN(*burstReserve, burstReserveFalldown), 0, burstReserveFalldown, continuousLimit, burstLimit) * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*burstReserve ? burstLimit : continuousLimit) * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void currentLimiterUpdate(timeDelta_t timeDelta) {
|
||||||
|
activeCurrentLimit = calculateActiveLimit(getAmperage(),
|
||||||
|
powerLimitsConfig()->continuousCurrent, powerLimitsConfig()->burstCurrent,
|
||||||
|
&burstCurrentReserve, burstCurrentReserveFalldown, burstCurrentReserveMax,
|
||||||
|
timeDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
void powerLimiterUpdate(timeDelta_t timeDelta) {
|
||||||
|
activePowerLimit = calculateActiveLimit(getPower(),
|
||||||
|
powerLimitsConfig()->continuousPower, powerLimitsConfig()->burstPower,
|
||||||
|
&burstPowerReserve, burstPowerReserveFalldown, burstPowerReserveMax,
|
||||||
|
timeDelta);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void powerLimiterApply(int16_t *throttleCommand) {
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
if (!activeCurrentLimit && !activePowerLimit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!activeCurrentLimit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static timeUs_t lastCallTimestamp = 0;
|
||||||
|
timeUs_t currentTimeUs = micros();
|
||||||
|
timeDelta_t callTimeDelta = cmpTimeUs(currentTimeUs, lastCallTimestamp);
|
||||||
|
|
||||||
|
int16_t throttleBase;
|
||||||
|
int16_t currentThrottleCommand;
|
||||||
|
#ifdef USE_ADC
|
||||||
|
int16_t powerThrottleCommand;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int16_t current = getAmperageSample();
|
||||||
|
#ifdef USE_ADC
|
||||||
|
uint16_t voltage = getVBatSample();
|
||||||
|
int32_t power = (int32_t)voltage * current / 100;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Current limiting
|
||||||
|
int32_t overCurrent = current - activeCurrentLimit;
|
||||||
|
|
||||||
|
if (lastCallTimestamp) {
|
||||||
|
currentThrAttnIntegrator = constrainf(currentThrAttnIntegrator + overCurrent * powerLimitsConfig()->piI * callTimeDelta * 2e-7, 0, PWM_RANGE_MAX - PWM_RANGE_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentThrAttnProportional = MAX(0, overCurrent) * powerLimitsConfig()->piP * 1e-3;
|
||||||
|
|
||||||
|
uint16_t currentThrAttn = lrintf(pt1FilterApply3(¤tThrAttnFilter, currentThrAttnProportional + currentThrAttnIntegrator, callTimeDelta * 1e-6));
|
||||||
|
|
||||||
|
throttleBase = wasLimitingCurrent ? lrintf(pt1FilterApply3(¤tThrLimitingBaseFilter, *throttleCommand, callTimeDelta * 1e-6)) : *throttleCommand;
|
||||||
|
uint16_t currentThrAttned = MAX(PWM_RANGE_MIN, (int16_t)throttleBase - currentThrAttn);
|
||||||
|
|
||||||
|
if (activeCurrentLimit && currentThrAttned < *throttleCommand) {
|
||||||
|
if (!wasLimitingCurrent && getAmperage() >= activeCurrentLimit) {
|
||||||
|
pt1FilterReset(¤tThrLimitingBaseFilter, *throttleCommand);
|
||||||
|
wasLimitingCurrent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentThrottleCommand = currentThrAttned;
|
||||||
|
} else {
|
||||||
|
wasLimitingCurrent = false;
|
||||||
|
currentThrAttnIntegrator = 0;
|
||||||
|
pt1FilterReset(¤tThrAttnFilter, 0);
|
||||||
|
|
||||||
|
currentThrottleCommand = *throttleCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
// Power limiting
|
||||||
|
int32_t overPower = power - activePowerLimit;
|
||||||
|
|
||||||
|
if (lastCallTimestamp) {
|
||||||
|
powerThrAttnIntegrator = constrainf(powerThrAttnIntegrator + overPower * powerLimitsConfig()->piI * callTimeDelta / voltage * 2e-5, 0, PWM_RANGE_MAX - PWM_RANGE_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
float powerThrAttnProportional = MAX(0, overPower) * powerLimitsConfig()->piP / voltage * 1e-1;
|
||||||
|
|
||||||
|
uint16_t powerThrAttn = lrintf(pt1FilterApply3(&powerThrAttnFilter, powerThrAttnProportional + powerThrAttnIntegrator, callTimeDelta * 1e-6));
|
||||||
|
|
||||||
|
throttleBase = wasLimitingPower ? lrintf(pt1FilterApply3(&powerThrLimitingBaseFilter, *throttleCommand, callTimeDelta * 1e-6)) : *throttleCommand;
|
||||||
|
uint16_t powerThrAttned = MAX(PWM_RANGE_MIN, (int16_t)throttleBase - powerThrAttn);
|
||||||
|
|
||||||
|
if (activePowerLimit && powerThrAttned < *throttleCommand) {
|
||||||
|
if (!wasLimitingPower && getPower() >= activePowerLimit) {
|
||||||
|
pt1FilterReset(&powerThrLimitingBaseFilter, *throttleCommand);
|
||||||
|
wasLimitingPower = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
powerThrottleCommand = powerThrAttned;
|
||||||
|
} else {
|
||||||
|
wasLimitingPower = false;
|
||||||
|
powerThrAttnIntegrator = 0;
|
||||||
|
pt1FilterReset(&powerThrAttnFilter, 0);
|
||||||
|
|
||||||
|
powerThrottleCommand = *throttleCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
*throttleCommand = MIN(currentThrottleCommand, powerThrottleCommand);
|
||||||
|
#else
|
||||||
|
*throttleCommand = currentThrottleCommand;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lastCallTimestamp = currentTimeUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool powerLimiterIsLimiting(void) {
|
||||||
|
#ifdef USE_ADC
|
||||||
|
return wasLimitingPower || wasLimitingCurrent;
|
||||||
|
#else
|
||||||
|
return wasLimitingCurrent;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool powerLimiterIsLimitingCurrent(void) {
|
||||||
|
return wasLimitingCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
bool powerLimiterIsLimitingPower(void) {
|
||||||
|
return wasLimitingPower;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// returns seconds
|
||||||
|
float powerLimiterGetRemainingBurstTime(void) {
|
||||||
|
uint16_t currentBurstOverContinuous = powerLimitsConfig()->burstCurrent - powerLimitsConfig()->continuousCurrent;
|
||||||
|
float remainingCurrentBurstTime = burstCurrentReserve / currentBurstOverContinuous / 1e7;
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
uint16_t powerBurstOverContinuous = powerLimitsConfig()->burstPower - powerLimitsConfig()->continuousPower;
|
||||||
|
float remainingPowerBurstTime = burstPowerReserve / powerBurstOverContinuous / 1e7;
|
||||||
|
|
||||||
|
if (!powerLimitsConfig()->continuousCurrent) {
|
||||||
|
return remainingPowerBurstTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!powerLimitsConfig()->continuousPower) {
|
||||||
|
return remainingCurrentBurstTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MIN(remainingCurrentBurstTime, remainingPowerBurstTime);
|
||||||
|
#else
|
||||||
|
return remainingCurrentBurstTime;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns cA
|
||||||
|
uint16_t powerLimiterGetActiveCurrentLimit(void) {
|
||||||
|
return activeCurrentLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
// returns cW
|
||||||
|
uint16_t powerLimiterGetActivePowerLimit(void) {
|
||||||
|
return activePowerLimit;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
66
src/main/flight/power_limits.h
Normal file
66
src/main/flight/power_limits.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* This file is part of iNav
|
||||||
|
*
|
||||||
|
* iNav free software. You can redistribute
|
||||||
|
* this software and/or modify this software under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* iNav distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this software.
|
||||||
|
*
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <common/time.h>
|
||||||
|
|
||||||
|
#include "config/parameter_group.h"
|
||||||
|
|
||||||
|
#if defined(USE_POWER_LIMITS)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t continuousCurrent; // dA
|
||||||
|
uint16_t burstCurrent; // dA
|
||||||
|
uint16_t burstCurrentTime; // ds
|
||||||
|
uint16_t burstCurrentFalldownTime; // ds
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
uint16_t continuousPower; // dW
|
||||||
|
uint16_t burstPower; // dW
|
||||||
|
uint16_t burstPowerTime; // ds
|
||||||
|
uint16_t burstPowerFalldownTime; // ds
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t piP;
|
||||||
|
uint16_t piI;
|
||||||
|
|
||||||
|
float attnFilterCutoff; // Hz
|
||||||
|
} powerLimitsConfig_t;
|
||||||
|
|
||||||
|
PG_DECLARE(powerLimitsConfig_t, powerLimitsConfig);
|
||||||
|
|
||||||
|
void powerLimiterInit(void);
|
||||||
|
void currentLimiterUpdate(timeDelta_t timeDelta);
|
||||||
|
void powerLimiterUpdate(timeDelta_t timeDelta);
|
||||||
|
void powerLimiterApply(int16_t *throttleCommand);
|
||||||
|
bool powerLimiterIsLimiting(void);
|
||||||
|
bool powerLimiterIsLimitingCurrent(void);
|
||||||
|
float powerLimiterGetRemainingBurstTime(void); // returns seconds
|
||||||
|
uint16_t powerLimiterGetActiveCurrentLimit(void); // returns cA
|
||||||
|
#ifdef USE_ADC
|
||||||
|
uint16_t powerLimiterGetActivePowerLimit(void); // returns cW
|
||||||
|
bool powerLimiterIsLimitingPower(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -85,10 +85,11 @@ FILE_COMPILE_FOR_SPEED
|
||||||
#include "flight/imu.h"
|
#include "flight/imu.h"
|
||||||
#include "flight/mixer.h"
|
#include "flight/mixer.h"
|
||||||
#include "flight/pid.h"
|
#include "flight/pid.h"
|
||||||
|
#include "flight/power_limits.h"
|
||||||
#include "flight/rth_estimator.h"
|
#include "flight/rth_estimator.h"
|
||||||
#include "flight/wind_estimator.h"
|
|
||||||
#include "flight/secondary_imu.h"
|
#include "flight/secondary_imu.h"
|
||||||
#include "flight/servos.h"
|
#include "flight/servos.h"
|
||||||
|
#include "flight/wind_estimator.h"
|
||||||
|
|
||||||
#include "navigation/navigation.h"
|
#include "navigation/navigation.h"
|
||||||
#include "navigation/navigation_private.h"
|
#include "navigation/navigation_private.h"
|
||||||
|
@ -915,9 +916,15 @@ static void osdFormatThrottlePosition(char *buff, bool autoThr, textAttributes_t
|
||||||
if (autoThr && navigationIsControllingThrottle()) {
|
if (autoThr && navigationIsControllingThrottle()) {
|
||||||
buff[0] = SYM_AUTO_THR0;
|
buff[0] = SYM_AUTO_THR0;
|
||||||
buff[1] = SYM_AUTO_THR1;
|
buff[1] = SYM_AUTO_THR1;
|
||||||
if (isFixedWingAutoThrottleManuallyIncreased())
|
if (isFixedWingAutoThrottleManuallyIncreased()) {
|
||||||
TEXT_ATTRIBUTES_ADD_BLINK(*elemAttr);
|
TEXT_ATTRIBUTES_ADD_BLINK(*elemAttr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
if (powerLimiterIsLimiting()) {
|
||||||
|
TEXT_ATTRIBUTES_ADD_BLINK(*elemAttr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
tfp_sprintf(buff + 2, "%3d", getThrottlePercent());
|
tfp_sprintf(buff + 2, "%3d", getThrottlePercent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2697,9 +2704,47 @@ static bool osdDrawSingleElement(uint8_t item)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OSD_NAV_FW_CONTROL_SMOOTHNESS:
|
case OSD_NAV_FW_CONTROL_SMOOTHNESS:
|
||||||
osdDisplayAdjustableDecimalValue(elemPosX, elemPosY, "CTL S", 0, navConfig()->fw.control_smoothness, 1, 0, ADJUSTMENT_NAV_FW_CONTROL_SMOOTHNESS);
|
osdDisplayAdjustableDecimalValue(elemPosX, elemPosY, "CTL S", 0, navConfig()->fw.control_smoothness, 1, 0, ADJUSTMENT_NAV_FW_CONTROL_SMOOTHNESS);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
case OSD_PLIMIT_REMAINING_BURST_TIME:
|
||||||
|
osdFormatCentiNumber(buff, powerLimiterGetRemainingBurstTime() * 100, 0, 1, 0, 3);
|
||||||
|
buff[3] = 'S';
|
||||||
|
buff[4] = '\0';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OSD_PLIMIT_ACTIVE_CURRENT_LIMIT:
|
||||||
|
if (powerLimitsConfig()->continuousCurrent) {
|
||||||
|
osdFormatCentiNumber(buff, powerLimiterGetActiveCurrentLimit(), 0, 2, 0, 3);
|
||||||
|
buff[3] = SYM_AMP;
|
||||||
|
buff[4] = '\0';
|
||||||
|
|
||||||
|
if (powerLimiterIsLimitingCurrent()) {
|
||||||
|
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
case OSD_PLIMIT_ACTIVE_POWER_LIMIT:
|
||||||
|
{
|
||||||
|
if (powerLimitsConfig()->continuousPower) {
|
||||||
|
bool kiloWatt = osdFormatCentiNumber(buff, powerLimiterGetActivePowerLimit(), 1000, 2, 2, 3);
|
||||||
|
buff[3] = kiloWatt ? SYM_KILOWATT : SYM_WATT;
|
||||||
|
buff[4] = '\0';
|
||||||
|
|
||||||
|
if (powerLimiterIsLimitingPower()) {
|
||||||
|
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // USE_ADC
|
||||||
|
#endif // USE_POWER_LIMITS
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2774,6 +2819,12 @@ static uint8_t osdIncElementIndex(uint8_t elementIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_POWER_LIMITS
|
||||||
|
if (elementIndex == OSD_NAV_FW_CONTROL_SMOOTHNESS) {
|
||||||
|
elementIndex = OSD_ITEM_COUNT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (elementIndex == OSD_ITEM_COUNT) {
|
if (elementIndex == OSD_ITEM_COUNT) {
|
||||||
elementIndex = 0;
|
elementIndex = 0;
|
||||||
}
|
}
|
||||||
|
@ -3020,6 +3071,12 @@ void pgResetFn_osdLayoutsConfig(osdLayoutsConfig_t *osdLayoutsConfig)
|
||||||
osdLayoutsConfig->item_pos[0][OSD_RC_SOURCE] = OSD_POS(3, 4);
|
osdLayoutsConfig->item_pos[0][OSD_RC_SOURCE] = OSD_POS(3, 4);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POWER_LIMITS
|
||||||
|
osdLayoutsConfig->item_pos[0][OSD_PLIMIT_REMAINING_BURST_TIME] = OSD_POS(3, 4);
|
||||||
|
osdLayoutsConfig->item_pos[0][OSD_PLIMIT_ACTIVE_CURRENT_LIMIT] = OSD_POS(3, 5);
|
||||||
|
osdLayoutsConfig->item_pos[0][OSD_PLIMIT_ACTIVE_POWER_LIMIT] = OSD_POS(3, 6);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Under OSD_FLYMODE. TODO: Might not be visible on NTSC?
|
// Under OSD_FLYMODE. TODO: Might not be visible on NTSC?
|
||||||
osdLayoutsConfig->item_pos[0][OSD_MESSAGES] = OSD_POS(1, 13) | OSD_VISIBLE_FLAG;
|
osdLayoutsConfig->item_pos[0][OSD_MESSAGES] = OSD_POS(1, 13) | OSD_VISIBLE_FLAG;
|
||||||
|
|
||||||
|
|
|
@ -228,6 +228,9 @@ typedef enum {
|
||||||
OSD_NAV_FW_CONTROL_SMOOTHNESS,
|
OSD_NAV_FW_CONTROL_SMOOTHNESS,
|
||||||
OSD_VERSION,
|
OSD_VERSION,
|
||||||
OSD_RANGEFINDER,
|
OSD_RANGEFINDER,
|
||||||
|
OSD_PLIMIT_REMAINING_BURST_TIME,
|
||||||
|
OSD_PLIMIT_ACTIVE_CURRENT_LIMIT,
|
||||||
|
OSD_PLIMIT_ACTIVE_POWER_LIMIT,
|
||||||
OSD_ITEM_COUNT // MUST BE LAST
|
OSD_ITEM_COUNT // MUST BE LAST
|
||||||
} osd_items_e;
|
} osd_items_e;
|
||||||
|
|
||||||
|
|
|
@ -218,9 +218,7 @@ static void updateBatteryVoltage(timeUs_t timeDelta, bool justConnected)
|
||||||
switch (batteryMetersConfig()->voltage.type) {
|
switch (batteryMetersConfig()->voltage.type) {
|
||||||
case VOLTAGE_SENSOR_ADC:
|
case VOLTAGE_SENSOR_ADC:
|
||||||
{
|
{
|
||||||
// calculate battery voltage based on ADC reading
|
vbat = getVBatSample();
|
||||||
// result is Vbatt in 0.01V steps. 3.3V = ADC Vref, 0xFFF = 12bit adc, 1100 = 11:1 voltage divider (10k:1k)
|
|
||||||
vbat = (uint64_t)adcGetChannel(ADC_BATTERY) * batteryMetersConfig()->voltage.scale * ADCVREF / (0xFFF * 1000);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if defined(USE_ESC_SENSOR)
|
#if defined(USE_ESC_SENSOR)
|
||||||
|
@ -375,6 +373,14 @@ bool isBatteryVoltageConfigured(void)
|
||||||
return feature(FEATURE_VBAT);
|
return feature(FEATURE_VBAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ADC
|
||||||
|
uint16_t getVBatSample(void) {
|
||||||
|
// calculate battery voltage based on ADC reading
|
||||||
|
// result is Vbatt in 0.01V steps. 3.3V = ADC Vref, 0xFFF = 12bit adc, 1100 = 11:1 voltage divider (10k:1k)
|
||||||
|
return (uint64_t)adcGetChannel(ADC_BATTERY) * batteryMetersConfig()->voltage.scale * ADCVREF / (0xFFF * 1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t getBatteryVoltage(void)
|
uint16_t getBatteryVoltage(void)
|
||||||
{
|
{
|
||||||
if (batteryMetersConfig()->voltageSource == BAT_VOLTAGE_SAG_COMP) {
|
if (batteryMetersConfig()->voltageSource == BAT_VOLTAGE_SAG_COMP) {
|
||||||
|
@ -448,6 +454,12 @@ int16_t getAmperage(void)
|
||||||
return amperage;
|
return amperage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t getAmperageSample(void)
|
||||||
|
{
|
||||||
|
int32_t microvolts = ((uint32_t)adcGetChannel(ADC_CURRENT) * ADCVREF * 100) / 0xFFF * 10 - (int32_t)batteryMetersConfig()->current.offset * 100;
|
||||||
|
return microvolts / batteryMetersConfig()->current.scale; // current in 0.01A steps
|
||||||
|
}
|
||||||
|
|
||||||
int32_t getPower(void)
|
int32_t getPower(void)
|
||||||
{
|
{
|
||||||
return power;
|
return power;
|
||||||
|
@ -463,7 +475,6 @@ int32_t getMWhDrawn(void)
|
||||||
return mWhDrawn;
|
return mWhDrawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void currentMeterUpdate(timeUs_t timeDelta)
|
void currentMeterUpdate(timeUs_t timeDelta)
|
||||||
{
|
{
|
||||||
static pt1Filter_t amperageFilterState;
|
static pt1Filter_t amperageFilterState;
|
||||||
|
@ -472,9 +483,7 @@ void currentMeterUpdate(timeUs_t timeDelta)
|
||||||
switch (batteryMetersConfig()->current.type) {
|
switch (batteryMetersConfig()->current.type) {
|
||||||
case CURRENT_SENSOR_ADC:
|
case CURRENT_SENSOR_ADC:
|
||||||
{
|
{
|
||||||
int32_t microvolts = ((uint32_t)adcGetChannel(ADC_CURRENT) * ADCVREF * 100) / 0xFFF * 10 - (int32_t)batteryMetersConfig()->current.offset * 100;
|
amperage = pt1FilterApply4(&erageFilterState, getAmperageSample(), AMPERAGE_LPF_FREQ, timeDelta * 1e-6f);
|
||||||
amperage = microvolts / batteryMetersConfig()->current.scale; // current in 0.01A steps
|
|
||||||
amperage = pt1FilterApply4(&erageFilterState, amperage, AMPERAGE_LPF_FREQ, timeDelta * 1e-6f);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CURRENT_SENSOR_VIRTUAL:
|
case CURRENT_SENSOR_VIRTUAL:
|
||||||
|
|
|
@ -151,6 +151,7 @@ uint16_t getPowerSupplyImpedance(void);
|
||||||
|
|
||||||
bool isAmperageConfigured(void);
|
bool isAmperageConfigured(void);
|
||||||
int16_t getAmperage(void);
|
int16_t getAmperage(void);
|
||||||
|
int16_t getAmperageSample(void);
|
||||||
int32_t getPower(void);
|
int32_t getPower(void);
|
||||||
int32_t getMAhDrawn(void);
|
int32_t getMAhDrawn(void);
|
||||||
int32_t getMWhDrawn(void);
|
int32_t getMWhDrawn(void);
|
||||||
|
@ -159,6 +160,7 @@ int32_t getMWhDrawn(void);
|
||||||
void batteryUpdate(timeUs_t timeDelta);
|
void batteryUpdate(timeUs_t timeDelta);
|
||||||
void sagCompensatedVBatUpdate(timeUs_t currentTime, timeUs_t timeDelta);
|
void sagCompensatedVBatUpdate(timeUs_t currentTime, timeUs_t timeDelta);
|
||||||
void powerMeterUpdate(timeUs_t timeDelta);
|
void powerMeterUpdate(timeUs_t timeDelta);
|
||||||
|
uint16_t getVBatSample(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void currentMeterUpdate(timeUs_t timeDelta);
|
void currentMeterUpdate(timeUs_t timeDelta);
|
||||||
|
|
|
@ -167,6 +167,8 @@
|
||||||
#define USE_SECONDARY_IMU
|
#define USE_SECONDARY_IMU
|
||||||
#define USE_IMU_BNO055
|
#define USE_IMU_BNO055
|
||||||
|
|
||||||
|
#define USE_POWER_LIMITS
|
||||||
|
|
||||||
#else // MCU_FLASH_SIZE < 256
|
#else // MCU_FLASH_SIZE < 256
|
||||||
#define LOG_LEVEL_MAXIMUM LOG_LEVEL_ERROR
|
#define LOG_LEVEL_MAXIMUM LOG_LEVEL_ERROR
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue