diff --git a/src/deck/drivers/src/Kconfig b/src/deck/drivers/src/Kconfig index 345eab1acd..b236ea7354 100644 --- a/src/deck/drivers/src/Kconfig +++ b/src/deck/drivers/src/Kconfig @@ -65,18 +65,23 @@ config DECK_BIGQUAD accessories such as external receiver (CPPM input) and GPS. It can also monitor battery voltage and current. -config DECK_BIGQUAD_ENABLE - bool "Enable Bigquad deck capabilities" +config DECK_BIGQUAD_BAT_VOLT_MULT_MV + int "Battery voltage divider multiplier (in mV)." depends on DECK_BIGQUAD - default n + default 7800 + +config DECK_BIGQUAD_BAT_AMP_PER_VOLT_MA + int "Battery ampere per volt (in mA)." + depends on DECK_BIGQUAD + default 1000 config DECK_BIGQUAD_ENABLE_OSD - depends on DECK_BIGQUAD_ENABLE + depends on DECK_BIGQUAD bool "Enable Bigquad deck OSD" default n config DECK_BIGQUAD_ENABLE_PM - depends on DECK_BIGQUAD_ENABLE + depends on DECK_BIGQUAD bool "Enable Bigquad deck PM" default n diff --git a/src/deck/drivers/src/bigquad.c b/src/deck/drivers/src/bigquad.c index 87ca3be8d8..42ca446703 100644 --- a/src/deck/drivers/src/bigquad.c +++ b/src/deck/drivers/src/bigquad.c @@ -44,11 +44,11 @@ #include "task.h" #define BIGQUAD_BAT_VOLT_PIN DECK_GPIO_MISO -#define BIGQUAD_BAT_VOLT_MULT 7.8f +#define BIGQUAD_BAT_VOLT_MULT (CONFIG_DECK_BIGQUAD_BAT_VOLT_MULT_MV / 1000.0) #define BIGQUAD_BAT_CURR_PIN DECK_GPIO_SCK -#define BIGQUAD_BAT_AMP_PER_VOLT 1.0f +#define BIGQUAD_BAT_AMP_PER_VOLT (CONFIG_DECK_BIGQUAD_BAT_AMP_PER_VOLT_MA / 1000.0) -#ifdef CONFIG_DECK_BIGQUAD_ENABLE +#ifdef CONFIG_DECK_BIGQUAD //Hardware configuration static bool isInit; @@ -83,6 +83,10 @@ static void bigquadInit(DeckInfo *info) DEBUG_PRINT("Switching to brushless.\n"); motorsInit(motorMapBigQuadDeck); extRxInit(); + + // Ignore charging/charged state to allow low-battery warning. + pmIgnoreChargedState(true); + #ifdef CONFIG_DECK_BIGQUAD_ENABLE_PM pmEnableExtBatteryVoltMeasuring(BIGQUAD_BAT_VOLT_PIN, BIGQUAD_BAT_VOLT_MULT); pmEnableExtBatteryCurrMeasuring(BIGQUAD_BAT_CURR_PIN, BIGQUAD_BAT_AMP_PER_VOLT); @@ -132,4 +136,5 @@ PARAM_GROUP_START(deck) PARAM_ADD_CORE(PARAM_UINT8 | PARAM_RONLY, bcBigQuad, &isInit) PARAM_GROUP_STOP(deck) -#endif // CONFIG_DECK_BIGQUAD_ENABLE + +#endif // CONFIG_DECK_BIGQUAD diff --git a/src/hal/interface/pm.h b/src/hal/interface/pm.h index 8d0c96a89f..6e16de6f60 100644 --- a/src/hal/interface/pm.h +++ b/src/hal/interface/pm.h @@ -132,6 +132,12 @@ void pmEnableExtBatteryCurrMeasuring(const deckPin_t pin, float ampPerVolt); */ float pmMeasureExtBatteryCurrent(void); +/* + * Ignore charging/charge state in the PM state machine. + * This can be useful if a platform doesn't have a charger. + */ +void pmIgnoreChargedState(bool ignore); + /** * Register a callback to be run when the NRF51 signals shutdown */ diff --git a/src/hal/src/pm_stm32f4.c b/src/hal/src/pm_stm32f4.c index 2beed40135..b52cb84169 100644 --- a/src/hal/src/pm_stm32f4.c +++ b/src/hal/src/pm_stm32f4.c @@ -57,9 +57,10 @@ typedef struct _PmSyslinkInfo uint8_t flags; struct { - uint8_t chg : 1; - uint8_t pgood : 1; - uint8_t unused : 6; + uint8_t isCharging : 1; + uint8_t usbPluggedIn : 1; + uint8_t canCharge : 1; + uint8_t unused : 5; }; }; float vBat; @@ -102,6 +103,8 @@ static PmSyslinkInfo pmSyslinkInfo; static uint8_t batteryLevel; +static bool ignoreChargedState = false; + static void pmSetBatteryVoltage(float voltage); const static float LiPoTypicalChargeCurve[10] = @@ -256,8 +259,17 @@ static void pmGracefulShutdown() void pmSyslinkUpdate(SyslinkPacket *slp) { if (slp->type == SYSLINK_PM_BATTERY_STATE) { + // First byte of the packet contains some PM flags such as USB power, charging etc. memcpy(&pmSyslinkInfo, &slp->data[0], sizeof(pmSyslinkInfo)); - pmSetBatteryVoltage(pmSyslinkInfo.vBat); + + // If using voltage measurements from external battery, we'll set the + // voltage to this instead of the one sent from syslink. + if (isExtBatVoltDeckPinSet) { + pmSetBatteryVoltage(extBatteryVoltage); + } else { + pmSetBatteryVoltage(pmSyslinkInfo.vBat); + } + #ifdef PM_SYSTLINK_INLCUDE_TEMP temp = pmSyslinkInfo.temp; #endif @@ -273,31 +285,37 @@ void pmSetChargeState(PMChargeStates chgState) PMStates pmUpdateState() { - PMStates state; - bool isCharging = pmSyslinkInfo.chg; - bool isPgood = pmSyslinkInfo.pgood; - uint32_t batteryLowTime; + bool usbPluggedIn = pmSyslinkInfo.usbPluggedIn; + bool isCharging = pmSyslinkInfo.isCharging; + PMStates nextState; - batteryLowTime = xTaskGetTickCount() - batteryLowTimeStamp; + uint32_t batteryLowTime = xTaskGetTickCount() - batteryLowTimeStamp; - if (isPgood && !isCharging) + if (ignoreChargedState) { - state = charged; + // For some scenarios we might not care about the charging/charged state. + nextState = battery; } - else if (isPgood && isCharging) + else if (usbPluggedIn && !isCharging) { - state = charging; + nextState = charged; } - else if (!isPgood && !isCharging && (batteryLowTime > PM_BAT_LOW_TIMEOUT)) + else if (usbPluggedIn && isCharging) { - state = lowPower; + nextState = charging; } else { - state = battery; + nextState = battery; } - return state; + if (nextState == battery && batteryLowTime > PM_BAT_LOW_TIMEOUT) + { + // This is to avoid setting state to lowPower when we're plugged in to USB. + nextState = lowPower; + } + + return nextState; } void pmEnableExtBatteryCurrMeasuring(const deckPin_t pin, float ampPerVolt) @@ -346,6 +364,10 @@ float pmMeasureExtBatteryVoltage(void) return voltage; } +void pmIgnoreChargedState(bool ignore) { + ignoreChargedState = ignore; +} + bool pmIsBatteryLow(void) { return (pmState == lowPower); }