2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
27 #include "build/build_config.h"
29 #include "common/filter.h"
30 #include "common/maths.h"
31 #include "common/utils.h"
33 #include "config/config_reset.h"
35 #include "drivers/adc.h"
38 #include "pg/pg_ids.h"
40 #include "sensors/adcinternal.h"
41 #include "sensors/battery.h"
42 #include "sensors/esc_sensor.h"
46 const char * const voltageMeterSourceNames
[VOLTAGE_METER_COUNT
] = {
50 const uint8_t voltageMeterIds
[] = {
51 VOLTAGE_METER_ID_BATTERY_1
,
53 VOLTAGE_METER_ID_12V_1
,
56 VOLTAGE_METER_ID_9V_1
,
59 VOLTAGE_METER_ID_5V_1
,
62 VOLTAGE_METER_ID_ESC_COMBINED_1
,
63 VOLTAGE_METER_ID_ESC_MOTOR_1
,
64 VOLTAGE_METER_ID_ESC_MOTOR_2
,
65 VOLTAGE_METER_ID_ESC_MOTOR_3
,
66 VOLTAGE_METER_ID_ESC_MOTOR_4
,
67 VOLTAGE_METER_ID_ESC_MOTOR_5
,
68 VOLTAGE_METER_ID_ESC_MOTOR_6
,
69 VOLTAGE_METER_ID_ESC_MOTOR_7
,
70 VOLTAGE_METER_ID_ESC_MOTOR_8
,
71 VOLTAGE_METER_ID_ESC_MOTOR_9
,
72 VOLTAGE_METER_ID_ESC_MOTOR_10
,
73 VOLTAGE_METER_ID_ESC_MOTOR_11
,
74 VOLTAGE_METER_ID_ESC_MOTOR_12
,
78 const uint8_t supportedVoltageMeterCount
= ARRAYLEN(voltageMeterIds
);
85 void voltageMeterReset(voltageMeter_t
*meter
)
88 meter
->unfiltered
= 0;
94 #ifndef VBAT_SCALE_DEFAULT
95 #define VBAT_SCALE_DEFAULT 110
98 #ifndef VBAT_RESDIVVAL_DEFAULT
99 #define VBAT_RESDIVVAL_DEFAULT 10
102 #ifndef VBAT_RESDIVMULTIPLIER_DEFAULT
103 #define VBAT_RESDIVMULTIPLIER_DEFAULT 1
106 typedef struct voltageMeterADCState_s
{
107 uint16_t voltageFiltered
; // battery voltage in 0.01V steps (filtered)
108 uint16_t voltageUnfiltered
; // battery voltage in 0.01V steps (unfiltered)
110 } voltageMeterADCState_t
;
112 extern voltageMeterADCState_t voltageMeterADCStates
[MAX_VOLTAGE_SENSOR_ADC
];
114 voltageMeterADCState_t voltageMeterADCStates
[MAX_VOLTAGE_SENSOR_ADC
];
116 voltageMeterADCState_t
*getVoltageMeterADC(uint8_t index
)
118 return &voltageMeterADCStates
[index
];
121 PG_REGISTER_ARRAY_WITH_RESET_FN(voltageSensorADCConfig_t
, MAX_VOLTAGE_SENSOR_ADC
, voltageSensorADCConfig
, PG_VOLTAGE_SENSOR_ADC_CONFIG
, 0);
123 void pgResetFn_voltageSensorADCConfig(voltageSensorADCConfig_t
*instance
)
125 for (int i
= 0; i
< MAX_VOLTAGE_SENSOR_ADC
; i
++) {
126 RESET_CONFIG(voltageSensorADCConfig_t
, &instance
[i
],
127 .vbatscale
= VBAT_SCALE_DEFAULT
,
128 .vbatresdivval
= VBAT_RESDIVVAL_DEFAULT
,
129 .vbatresdivmultiplier
= VBAT_RESDIVMULTIPLIER_DEFAULT
,
135 static const uint8_t voltageMeterAdcChannelMap
[] = {
148 STATIC_UNIT_TESTED
uint16_t voltageAdcToVoltage(const uint16_t src
, const voltageSensorADCConfig_t
*config
)
150 // calculate battery voltage based on ADC reading
151 // result is Vbatt in 0.01V steps. 3.3V = ADC Vref, 0xFFF = 12bit adc, 110 = 10:1 voltage divider (10k:1k) * 100 for 0.01V
152 return ((((uint32_t)src
* config
->vbatscale
* getVrefMv() / 10 + (0xFFF * 5)) / (0xFFF * config
->vbatresdivval
)) / config
->vbatresdivmultiplier
);
155 void voltageMeterADCRefresh(void)
157 for (uint8_t i
= 0; i
< MAX_VOLTAGE_SENSOR_ADC
&& i
< ARRAYLEN(voltageMeterAdcChannelMap
); i
++) {
158 voltageMeterADCState_t
*state
= &voltageMeterADCStates
[i
];
160 // store the battery voltage with some other recent battery voltage readings
162 const voltageSensorADCConfig_t
*config
= voltageSensorADCConfig(i
);
164 uint8_t channel
= voltageMeterAdcChannelMap
[i
];
165 uint16_t rawSample
= adcGetChannel(channel
);
167 uint16_t filteredSample
= pt1FilterApply(&state
->filter
, rawSample
);
169 // always calculate the latest voltage, see getLatestVoltage() which does the calculation on demand.
170 state
->voltageFiltered
= voltageAdcToVoltage(filteredSample
, config
);
171 state
->voltageUnfiltered
= voltageAdcToVoltage(rawSample
, config
);
173 UNUSED(voltageAdcToVoltage
);
175 state
->voltageFiltered
= 0;
176 state
->voltageUnfiltered
= 0;
181 void voltageMeterADCRead(voltageSensorADC_e adcChannel
, voltageMeter_t
*voltageMeter
)
183 voltageMeterADCState_t
*state
= &voltageMeterADCStates
[adcChannel
];
185 voltageMeter
->filtered
= state
->voltageFiltered
;
186 voltageMeter
->unfiltered
= state
->voltageUnfiltered
;
189 void voltageMeterADCInit(void)
191 for (uint8_t i
= 0; i
< MAX_VOLTAGE_SENSOR_ADC
&& i
< ARRAYLEN(voltageMeterAdcChannelMap
); i
++) {
192 // store the battery voltage with some other recent battery voltage readings
194 voltageMeterADCState_t
*state
= &voltageMeterADCStates
[i
];
195 memset(state
, 0, sizeof(voltageMeterADCState_t
));
197 pt1FilterInit(&state
->filter
, pt1FilterGain(GET_BATTERY_LPF_FREQUENCY(batteryConfig()->vbatLpfPeriod
), HZ_TO_INTERVAL(50)));
205 #ifdef USE_ESC_SENSOR
206 typedef struct voltageMeterESCState_s
{
207 uint16_t voltageFiltered
; // battery voltage in 0.01V steps (filtered)
208 uint16_t voltageUnfiltered
; // battery voltage in 0.01V steps (unfiltered)
210 } voltageMeterESCState_t
;
212 static voltageMeterESCState_t voltageMeterESCState
;
217 void voltageMeterESCInit(void)
219 #ifdef USE_ESC_SENSOR
220 memset(&voltageMeterESCState
, 0, sizeof(voltageMeterESCState_t
));
221 pt1FilterInit(&voltageMeterESCState
.filter
, pt1FilterGain(GET_BATTERY_LPF_FREQUENCY(batteryConfig()->vbatLpfPeriod
), HZ_TO_INTERVAL(50)));
225 void voltageMeterESCRefresh(void)
227 #ifdef USE_ESC_SENSOR
228 escSensorData_t
*escData
= getEscSensorData(ESC_SENSOR_COMBINED
);
230 voltageMeterESCState
.voltageUnfiltered
= escData
->dataAge
<= ESC_BATTERY_AGE_MAX
? escData
->voltage
: 0;
231 voltageMeterESCState
.voltageFiltered
= pt1FilterApply(&voltageMeterESCState
.filter
, voltageMeterESCState
.voltageUnfiltered
);
236 void voltageMeterESCReadMotor(uint8_t motorNumber
, voltageMeter_t
*voltageMeter
)
238 #ifndef USE_ESC_SENSOR
240 voltageMeterReset(voltageMeter
);
242 escSensorData_t
*escData
= getEscSensorData(motorNumber
);
244 voltageMeter
->unfiltered
= escData
->dataAge
<= ESC_BATTERY_AGE_MAX
? escData
->voltage
: 0;
245 voltageMeter
->filtered
= voltageMeter
->unfiltered
; // no filtering for ESC motors currently.
247 voltageMeterReset(voltageMeter
);
253 void voltageMeterESCReadCombined(voltageMeter_t
*voltageMeter
)
255 #ifndef USE_ESC_SENSOR
256 voltageMeterReset(voltageMeter
);
258 voltageMeter
->filtered
= voltageMeterESCState
.voltageFiltered
;
259 voltageMeter
->unfiltered
= voltageMeterESCState
.voltageUnfiltered
;
264 // API for using voltage meters using IDs
266 // This API is used by MSP, for configuration/status.
270 // the order of these much match the indexes in voltageSensorADC_e
271 const uint8_t voltageMeterADCtoIDMap
[MAX_VOLTAGE_SENSOR_ADC
] = {
272 VOLTAGE_METER_ID_BATTERY_1
,
274 VOLTAGE_METER_ID_12V_1
,
277 VOLTAGE_METER_ID_9V_1
,
280 VOLTAGE_METER_ID_5V_1
,
284 void voltageMeterRead(voltageMeterId_e id
, voltageMeter_t
*meter
)
286 if (id
== VOLTAGE_METER_ID_BATTERY_1
) {
287 voltageMeterADCRead(VOLTAGE_SENSOR_ADC_VBAT
, meter
);
290 if (id
== VOLTAGE_METER_ID_12V_1
) {
291 voltageMeterADCRead(VOLTAGE_SENSOR_ADC_12V
, meter
);
295 if (id
== VOLTAGE_METER_ID_9V_1
) {
296 voltageMeterADCRead(VOLTAGE_SENSOR_ADC_9V
, meter
);
300 if (id
== VOLTAGE_METER_ID_5V_1
) {
301 voltageMeterADCRead(VOLTAGE_SENSOR_ADC_5V
, meter
);
304 #ifdef USE_ESC_SENSOR
305 if (id
== VOLTAGE_METER_ID_ESC_COMBINED_1
) {
306 voltageMeterESCReadCombined(meter
);
308 if (id
>= VOLTAGE_METER_ID_ESC_MOTOR_1
&& id
<= VOLTAGE_METER_ID_ESC_MOTOR_20
) {
309 int motor
= id
- VOLTAGE_METER_ID_ESC_MOTOR_1
;
310 voltageMeterESCReadMotor(motor
, meter
);
314 voltageMeterReset(meter
);