refactor(radio): unified battery and RTC voltage (#6065)

This commit is contained in:
Raphael Coeffic
2025-04-27 13:46:18 +10:00
committed by GitHub
parent f237e9d40b
commit b52e7717ab
13 changed files with 185 additions and 154 deletions
@@ -32,6 +32,7 @@ set(BOARD_LIB_SRC
boards/generic_stm32/switches.cpp
boards/generic_stm32/bor_level.cpp
boards/generic_stm32/rgb_leds.cpp
boards/generic_stm32/battery_voltage.cpp
)
add_library(minimal_board_lib OBJECT EXCLUDE_FROM_ALL ${MINIMAL_BOARD_LIB_SRC})
@@ -0,0 +1,113 @@
/*
* Copyright (C) EdgeTx
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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.
*/
#include "hal/adc_driver.h"
#include "board.h"
#include "edgetx.h"
#if defined(STM32F407xx) || defined(STM32F205xx)
// internal bridge measure Vbat/2
#define VBAT_RTC_DIV 2
#else
// internal bridge measure Vbat/4
#define VBAT_RTC_DIV 4
#endif
#define __weak __attribute__((weak))
static uint16_t scale_rtc_voltage(uint16_t v)
{
return (v * ADC_VREF_PREC2 * VBAT_RTC_DIV) / ADC_MAX_FILTERED;
}
uint16_t getRTCBatteryVoltage()
{
if (adcGetMaxInputs(ADC_INPUT_RTC_BAT) < 1) return 0;
uint16_t filtered = anaIn(adcGetInputOffset(ADC_INPUT_RTC_BAT));
return scale_rtc_voltage(filtered);
}
#if (defined(VBAT_DIV_R1) && defined(VBAT_DIV_R2)) || \
defined(BATTERY_DIVIDER) || defined(BATT_SCALE)
#define VREF_FLOAT ((float)ADC_VREF_PREC2 / 100.0)
#if defined(VBAT_DIV_R1) && defined(VBAT_DIV_R2)
// defined as a voltage divider
// Vbat --- R1 --+-- ADC
// |
// +-- R2 --- GND
//
#define VOLTAGE_DIVIDER(r1, r2) (((float)r1 + (float)r2) / (float)r2)
#define VBAT_DIVIDER VOLTAGE_DIVIDER(VBAT_DIV_R1, VBAT_DIV_R2)
// Scale of Vbat calibration setting
#define VBAT_CAL 1000.0
#elif defined(BATT_SCALE)
// defined as a simple ratio (old style: mostly taranis targets)
#define VBAT_DIVIDER \
(((float)BATT_SCALE * (float)ADC_MAX_FILTERED) / \
((float)BATTERY_DIVIDER * VREF_FLOAT))
// Scale of Vbat calibration setting
#define VBAT_CAL 128.0
#elif defined(BATTERY_DIVIDER)
// defined a a simple factor (old style: mostly color targets)
#define VBAT_DIVIDER \
(((float)ADC_MAX_FILTERED * 10.0) / ((float)BATTERY_DIVIDER * VREF_FLOAT))
// Scale of Vbat calibration setting
#define VBAT_CAL 1000.0
#endif
// Fixed offset in hundredth of volt (*10 mV)
#if defined(VBAT_MOSFET_DROP)
#define VBAT_OFFSET VBAT_MOSFET_DROP
#elif defined(VOLTAGE_DROP)
#define VBAT_OFFSET VOLTAGE_DROP
#else
#define VBAT_OFFSET 0
#endif
__weak uint16_t getBatteryVoltage()
{
// using filtered ADC value on purpose
if (adcGetMaxInputs(ADC_INPUT_VBAT) < 1) return 0;
float vbat = anaIn(adcGetInputOffset(ADC_INPUT_VBAT));
// apply calibration
vbat = vbat * (VBAT_CAL + g_eeGeneral.txVoltageCalibration) / VBAT_CAL;
// apply voltage divider and ADC scale
vbat *= VBAT_DIVIDER * (VREF_FLOAT / (float)ADC_MAX_FILTERED);
// return hundredth of volt (*10 mV)
return (uint16_t)(100.0 * vbat) + VBAT_OFFSET;
}
#endif
+2 -54
View File
@@ -29,10 +29,6 @@ const etx_hal_adc_inputs_t* _hal_adc_inputs = nullptr;
static uint16_t adcValues[MAX_ANALOG_INPUTS] __DMA_NO_CACHE;
#if defined(CSD203_SENSOR)
extern uint16_t getCSD203BatteryVoltage(void);
#endif
bool adcInit(const etx_hal_adc_driver_t* driver)
{
// Init buffer, provides non random values before mixer task starts
@@ -197,7 +193,7 @@ void adcCalibSetMinMax()
}
xpot.stepsCount = ++count;
writeXPotCalib(i, xpot.steps, count);
writeXPotCalib(i, xpot.steps, count);
}
}
}
@@ -234,19 +230,6 @@ void adcCalibStore()
storageDirty(EE_GENERAL);
}
uint16_t getRTCBatteryVoltage()
{
// anaIn() outputs value divided by (1 << ANALOG_SCALE)
if (adcGetMaxInputs(ADC_INPUT_RTC_BAT) < 1) return 0;
#if defined(STM32F413xx)
return (anaIn(adcGetInputOffset(ADC_INPUT_RTC_BAT)) * ADC_VREF_PREC2) /
(1024 >> ANALOG_SCALE);
#else
return (anaIn(adcGetInputOffset(ADC_INPUT_RTC_BAT)) * ADC_VREF_PREC2) /
(2048 >> ANALOG_SCALE);
#endif
}
uint16_t getAnalogValue(uint8_t index)
{
if (index >= MAX_ANALOG_INPUTS) return 0;
@@ -307,41 +290,6 @@ JitterMeter<uint16_t> avgJitter[MAX_ANALOG_INPUTS];
tmr10ms_t jitterResetTime = 0;
#endif
uint16_t getBatteryVoltage()
{
#if defined(CSD203_SENSOR) && !defined(SIMU)
return getCSD203BatteryVoltage() / 10;
#else
// using filtered ADC value on purpose
if (adcGetMaxInputs(ADC_INPUT_VBAT) < 1) return 0;
int32_t instant_vbat = anaIn(adcGetInputOffset(ADC_INPUT_VBAT));
// TODO: remove BATT_SCALE / BATTERY_DIVIDER defines
#if defined(VBAT_MOSFET_DROP)
// 1000 is used as multiplier for both numerator and denominator to allow to stay in integer domain
return (uint16_t)((instant_vbat * ADC_VREF_PREC2 * ((((1000 + g_eeGeneral.txVoltageCalibration)) * (VBAT_DIV_R2 + VBAT_DIV_R1)) / VBAT_DIV_R1)) / (2*RESX*1000)) + VBAT_MOSFET_DROP;
#elif defined(BATT_SCALE)
instant_vbat =
(instant_vbat * BATT_SCALE * (128 + g_eeGeneral.txVoltageCalibration)) /
BATTERY_DIVIDER;
// add voltage drop because of the diode TODO check if this is needed, but
// removal will break existing calibrations!
instant_vbat += VOLTAGE_DROP;
return (uint16_t)instant_vbat;
#elif defined(VOLTAGE_DROP)
instant_vbat = ((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) /
BATTERY_DIVIDER);
// add voltage drop because of the diode
// removal will break existing calibrations!
instant_vbat += VOLTAGE_DROP;
return (uint16_t)instant_vbat;
#else
return (uint16_t)((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) /
BATTERY_DIVIDER);
#endif
#endif
}
static uint32_t apply_low_pass_filter(uint32_t v, uint32_t v_prev,
bool is_main_input)
{
@@ -470,7 +418,7 @@ void getADC()
#endif
DEBUG_TIMER_START(debugTimerAdcRead);
if (!adcRead()) TRACE("adcRead failed");
if (!adcRead()) { TRACE("adcRead failed"); }
DEBUG_TIMER_STOP(debugTimerAdcRead);
for (uint8_t x = 0; x < max_analogs; x++) {
+9 -14
View File
@@ -35,6 +35,8 @@
#define ANALOG_SCALE 1
#define JITTER_ALPHA (1<<JITTER_FILTER_STRENGTH)
#define ADC_MAX_FILTERED (ADC_MAX_VALUE >> ANALOG_SCALE)
enum {
ADC_INPUT_MAIN=0, // gimbals / wheel + throttle
ADC_INPUT_FLEX,
@@ -85,11 +87,9 @@ struct etx_hal_adc_driver_t {
bool adcInit(const etx_hal_adc_driver_t* driver);
// void adcDeInit();
bool adcRead();
uint16_t getBatteryVoltage();
uint16_t getRTCBatteryVoltage();
uint16_t getAnalogValue(uint8_t index);
void setAnalogValue(uint8_t index, uint16_t value);
bool adcRead();
uint16_t getAnalogValue(uint8_t index);
void setAnalogValue(uint8_t index, uint16_t value);
uint16_t* getAnalogValues();
// Run calibration steps:
@@ -114,10 +114,9 @@ extern JitterMeter<uint16_t> avgJitter[MAX_ANALOG_INPUTS];
void getADC();
uint16_t anaIn(uint8_t chan);
uint32_t anaIn_diag(uint8_t chan);
uint16_t getBatteryVoltage();
// Warning:
// STM32 uses a 25K+25K voltage divider bridge to measure the battery voltage
// STM32 uses a voltage divider bridge to measure the battery voltage
// Measuring VBAT puts considerable drain (22 µA) on the battery instead of
// normal drain (~10 nA)
void enableVBatBridge();
@@ -143,10 +142,6 @@ const char* adcGetInputShortLabel(uint8_t type, uint8_t idx);
void adcSetInputMask(uint32_t mask);
uint32_t adcGetInputMask();
// To be implemented by the target driver
// int8_t adcGetVRTC();
// int8_t adcGetVBAT();
// const char* adcGetStickName(uint8_t idx);
// const char* adcGetPotName(uint8_t idx);
// uint8_t adcGetMaxSticks();
// uint8_t adcGetMaxPots();
// these 2 must be implemented as part of board drivers
uint16_t getBatteryVoltage();
uint16_t getRTCBatteryVoltage();
@@ -88,6 +88,16 @@ uint32_t stm32_hal_get_inputs_mask()
return _adc_input_inhibt_mask;
}
#if defined(STM32H7)
#if defined(ADC3)
#define VBAT_ADC ADC3
#else
#define VBAT_ADC ADC2
#endif
#else
#define VBAT_ADC ADC1
#endif
// STM32 uses a 25K+25K voltage divider bridge to measure the battery voltage
// Measuring VBAT puts considerable drain (22 µA) on the battery instead of
// normal drain (~10 nA)
@@ -96,7 +106,7 @@ void enableVBatBridge()
if (adcGetMaxInputs(ADC_INPUT_RTC_BAT) < 1) return;
// Set internal measurement path for vbat sensor
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VBAT);
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(VBAT_ADC), LL_ADC_PATH_INTERNAL_VBAT);
auto channel = adcGetInputOffset(ADC_INPUT_RTC_BAT);
_adc_inhibit_mask &= ~(1 << channel);
@@ -110,13 +120,13 @@ void disableVBatBridge()
_adc_inhibit_mask |= (1 << channel);
// Set internal measurement path to none
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_NONE);
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(VBAT_ADC), LL_ADC_PATH_INTERNAL_NONE);
}
bool isVBatBridgeEnabled()
{
// && !(_adc_inhibit_mask & (1 << channel));
return LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1)) == LL_ADC_PATH_INTERNAL_VBAT;
return LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(VBAT_ADC)) == LL_ADC_PATH_INTERNAL_VBAT;
}
static void adc_enable_clock(ADC_TypeDef* ADCx)
+6 -1
View File
@@ -382,11 +382,16 @@ void initCSD203(void)
}
}
uint16_t getCSD203BatteryVoltage(void)
static uint16_t getCSD203BatteryVoltage(void)
{ // 1000=1000mV
return csd203extvbus;
}
uint16_t getBatteryVoltage()
{
return getCSD203BatteryVoltage() / 10;
}
void readCSD203(void)
{ // 5ms
static uint16_t GetSenSorStep = 0;
+5 -5
View File
@@ -397,7 +397,7 @@
#define ADC_DMA_STREAM_IRQ DMA2_Stream0_IRQn
#define ADC_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler
#define ADC_SAMPTIME LL_ADC_SAMPLINGTIME_56CYCLES
#define ADC_VREF_PREC2 600
#define ADC_VREF_PREC2 300
#elif defined(RADIO_V16)
#define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_0 // PA.00
#define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_1 // PA.01
@@ -446,7 +446,7 @@
#define ADC_DMA_STREAM LL_DMA_STREAM_0
#define ADC_DMA_STREAM_IRQ DMA2_Stream0_IRQn
#define ADC_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler
#define ADC_VREF_PREC2 660
#define ADC_VREF_PREC2 330
#elif defined(PCBX10)
#if defined(RADIO_T15)
#define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_1 // PA.01
@@ -546,11 +546,11 @@
// VBat divider is /4 on F42x and F43x devices
#if defined(RADIO_TX16S) || defined(RADIO_T15) || defined(RADIO_F16) || defined(RADIO_V16)
#define ADC_VREF_PREC2 660
#define ADC_VREF_PREC2 330
#elif defined(RADIO_T16) || defined(RADIO_T18)
#define ADC_VREF_PREC2 600
#define ADC_VREF_PREC2 300
#else
#define ADC_VREF_PREC2 500
#define ADC_VREF_PREC2 250
#endif
#endif
+1 -1
View File
@@ -161,7 +161,7 @@
#define ADC_EXT_DMA_STREAM_IRQ DMA2_Stream0_IRQn
#define ADC_EXT_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler
#define ADC_EXT_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES
#define ADC_VREF_PREC2 660
#define ADC_VREF_PREC2 330
#define ADC_DIRECTION \
{ 0 /*STICK1*/, 0 /*STICK2*/, 0 /*STICK3*/, 0 /*STICK4*/, \
+3 -3
View File
@@ -162,7 +162,7 @@
#define ADC_EXT_DMA_STREAM_IRQ DMA2_Stream0_IRQn
#define ADC_EXT_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler
#define ADC_EXT_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES
#define ADC_VREF_PREC2 660
#define ADC_VREF_PREC2 330
#define ADC_DIRECTION \
{ 0 /*STICK1*/, 0 /*STICK2*/, 0 /*STICK3*/, 0 /*STICK4*/, \
@@ -223,7 +223,7 @@
#define ADC_DMA_STREAM_IRQ DMA2_Stream4_IRQn
#define ADC_DMA_STREAM_IRQHandler DMA2_Stream4_IRQHandler
#define ADC_VREF_PREC2 660
#define ADC_VREF_PREC2 330
#define ADC_DIRECTION { \
0,0, /* gimbals */ \
@@ -454,7 +454,7 @@
#define ADC_EXT_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler
#define ADC_EXT_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES
#define ADC_VREF_PREC2 660
#define ADC_VREF_PREC2 330
#if defined(RADIO_PL18EV)
#define ADC_DIRECTION { \
+13 -31
View File
@@ -33,6 +33,17 @@ void enableVBatBridge(){}
void disableVBatBridge(){}
bool isVBatBridgeEnabled(){ return false; }
uint16_t getBatteryVoltage()
{
if (adcGetMaxInputs(ADC_INPUT_VBAT) < 1) return 0;
return anaIn(adcGetInputOffset(ADC_INPUT_VBAT));
}
uint16_t getRTCBatteryVoltage()
{
return 300;
}
extern uint16_t simu_get_analog(uint8_t idx);
static bool simu_start_conversion()
@@ -44,38 +55,9 @@ static bool simu_start_conversion()
// set batteries default voltages
int i = adcGetInputOffset(ADC_INPUT_VBAT);
if (i > 0) {
// calculate default voltage on 1st call
uint32_t adc = (simu_get_analog(i) - 2048) * 1000 / 2000;
// TRACE("raw ana: %d adj ana: %d", simu_get_analog(i), vbat);
// just in case the voltage has not been initialised in sim initialisation/startup
// these formulae must mirror OpenTxSimulator::voltageToAdc
if (adc == 0) {
uint32_t volts = (uint32_t)((g_eeGeneral.vBatWarn > 0 ? g_eeGeneral.vBatWarn : BATTERY_WARN) + 5) * 10; // +0.5V and prec2
#if defined(VBAT_MOSFET_DROP)
// TRACE("volts: %d r1: %d r2: %d drop: %d vref: %d calib: %d", volts, VBAT_DIV_R1, VBAT_DIV_R2, VBAT_MOSFET_DROP, ADC_VREF_PREC2, g_eeGeneral.txVoltageCalibration);
adc = (volts - VBAT_MOSFET_DROP) * (2 * RESX * 1000) / ADC_VREF_PREC2 / (((1000 + g_eeGeneral.txVoltageCalibration) * (VBAT_DIV_R2 + VBAT_DIV_R1)) / VBAT_DIV_R1);
#elif defined(BATT_SCALE)
// TRACE("volts: %d div: %d drop: %d scale: %d calib: %d", volts, BATTERY_DIVIDER, VOLTAGE_DROP, BATT_SCALE, g_eeGeneral.txVoltageCalibration);
adc = (volts - VOLTAGE_DROP) * BATTERY_DIVIDER / (128 + g_eeGeneral.txVoltageCalibration) / BATT_SCALE;
#elif defined(VOLTAGE_DROP)
// TRACE("volts: %d div: %d drop: %d", volts, BATTERY_DIVIDER, VOLTAGE_DROP);
adc = (volts - VOLTAGE_DROP) * BATTERY_DIVIDER / (1000 + g_eeGeneral.txVoltageCalibration);
#else
// TRACE("volts: %d div: %d calib: %d", volts, BATTERY_DIVIDER, g_eeGeneral.txVoltageCalibration);
adc = volts * BATTERY_DIVIDER / (1000 + g_eeGeneral.txVoltageCalibration);
#endif
// TRACE("calc adc: %d", adc);
adc = adc * 2; // div by 2 in firmware filtered adc calcs
}
setAnalogValue(i, adc);
}
if (adcGetMaxInputs(ADC_INPUT_RTC_BAT) > 0) {
uint32_t rtc_bat = (300 * (2048 >> ANALOG_SCALE)) / ADC_VREF_PREC2;
setAnalogValue(adcGetInputOffset(ADC_INPUT_RTC_BAT), rtc_bat * 2);
uint16_t volts = (uint16_t)((g_eeGeneral.vBatWarn > 0 ? g_eeGeneral.vBatWarn : BATTERY_WARN) + 5) * 10; // +0.5V and prec2
setAnalogValue(i, volts * 2);
}
return true;
+1 -23
View File
@@ -391,7 +391,7 @@ void OpenTxSimulator::setInputValue(int type, uint8_t index, int16_t value)
case INPUT_SRC_TXVIN :
if (adcGetMaxInputs(ADC_INPUT_VBAT) > 0) {
auto idx = adcGetInputOffset(ADC_INPUT_VBAT);
setAnalogValue(idx, voltageToAdc(value));
setAnalogValue(idx, value);
emit txBatteryVoltageChanged((unsigned int)value);
}
break;
@@ -907,28 +907,6 @@ const char * OpenTxSimulator::getError()
return main_thread_error;
}
const int OpenTxSimulator::voltageToAdc(const int voltage)
{
int volts = voltage * 10; // prec2
int adc = 0;
#if defined(VBAT_MOSFET_DROP)
// TRACE("volts: %d r1: %d r2: %d drop: %d vref: %d calib: %d", volts, VBAT_DIV_R1, VBAT_DIV_R2, VBAT_MOSFET_DROP, ADC_VREF_PREC2, g_eeGeneral.txVoltageCalibration);
adc = (volts - VBAT_MOSFET_DROP) * (2 * RESX * 1000) / ADC_VREF_PREC2 / (((1000 + g_eeGeneral.txVoltageCalibration) * (VBAT_DIV_R2 + VBAT_DIV_R1)) / VBAT_DIV_R1);
#elif defined(BATT_SCALE)
// TRACE("volts: %d div: %d drop: %d scale: %d calib: %d", volts, BATTERY_DIVIDER, VOLTAGE_DROP, BATT_SCALE, g_eeGeneral.txVoltageCalibration);
adc = (volts - VOLTAGE_DROP) * BATTERY_DIVIDER / (128 + g_eeGeneral.txVoltageCalibration) / BATT_SCALE;
#elif defined(VOLTAGE_DROP)
// TRACE("volts: %d div: %d drop: %d", volts, BATTERY_DIVIDER, VOLTAGE_DROP);
adc = (volts - VOLTAGE_DROP) * BATTERY_DIVIDER / (1000 + g_eeGeneral.txVoltageCalibration);
#else
// TRACE("volts: %d div: %d calib: %d", volts, BATTERY_DIVIDER, g_eeGeneral.txVoltageCalibration);
adc = volts * BATTERY_DIVIDER / (1000 + g_eeGeneral.txVoltageCalibration);
#endif
// TRACE("calc adc: %d", adc);
return adc * 2; // div by 2 in firmware filtered adc calcs
}
/*
* OpenTxSimulatorFactory
-1
View File
@@ -106,7 +106,6 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface
const char * getPhaseName(unsigned int phase);
const QString getCurrentPhaseName();
const char * getError();
const int voltageToAdc(const int voltage);
QString simuSdDirectory;
QString simuSettingsDirectory;
+18 -18
View File
@@ -359,26 +359,26 @@ void setTopBatteryValue(uint32_t volts);
#define BATTERY_DIVIDER 27500 // TODO: fix when we have proper schematics
#define VOLTAGE_DROP 20
#elif defined(MANUFACTURER_RADIOMASTER) || defined(MANUFACTURER_JUMPER)
// --- MOSFET ---- R2 --- MCU
// |__ R1 --- GND
//
#define VBAT_DIV_R1 160 // kOhms
#define VBAT_DIV_R2 499 // kOhms
#if defined(MANUFACTURER_JUMPER)
#define VBAT_MOSFET_DROP 50 // * 10mV
// --- MOSFET ---- R1 --- MCU
// |__ R2 --- GND
//
#define VBAT_DIV_R1 499 // kOhms
#define VBAT_DIV_R2 160 // kOhms
#if defined(MANUFACTURER_JUMPER)
#define VBAT_MOSFET_DROP 50 // * 10mV
#else
#define VBAT_MOSFET_DROP 25 // * 10mV
#endif
#else
#define VBAT_MOSFET_DROP 25 // * 10mV
#if defined (RADIO_T8) || defined(RADIO_COMMANDO8)
#define BATTERY_DIVIDER 50000
#elif defined (RADIO_LR3PRO)
#define BATTERY_DIVIDER 39500
#else
#define BATTERY_DIVIDER 26214
#endif
#define VOLTAGE_DROP 20
#endif
#else //--- MOSFET ---- R2 --- MCU
#if defined (RADIO_T8) || defined(RADIO_COMMANDO8)
#define BATTERY_DIVIDER 50000
#elif defined (RADIO_LR3PRO)
#define BATTERY_DIVIDER 39500
#else
#define BATTERY_DIVIDER 26214
#endif
#define VOLTAGE_DROP 20
#endif //--- MOSFET ---- R2 --- MCU
#if defined(RADIO_FAMILY_T20)
#define NUM_TRIMS 8