ACwing FC firmware
STM32WB55: attitude IEKF, altitude Kalman filter, flight core, protocol v2
Loading...
Searching...
No Matches
batt_adc.c
Go to the documentation of this file.
1
6#include "batt_adc.h"
7#include "app_config.h"
8#include "stm32wbxx_hal.h"
9#include "stm32wbxx_ll_adc.h"
10#include "stm32wbxx_ll_bus.h"
11#include "stm32wbxx_ll_gpio.h"
12#include "stm32wbxx_ll_rcc.h"
13
14static uint8_t s_started;
15
16static void delay_us(uint32_t us)
17{
18 const uint32_t n = us * (SystemCoreClock / 1000000u) / 4u;
19 for (volatile uint32_t i = 0; i < n; ++i) { }
20}
21
22static void analog_pin(GPIO_TypeDef *port, uint32_t pin)
23{
24 if (port == GPIOA) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
25 if (port == GPIOC) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
26 LL_GPIO_SetPinMode(port, pin, LL_GPIO_MODE_ANALOG);
27 LL_GPIO_SetPinPull(port, pin, LL_GPIO_PULL_NO);
28}
29
31{
34
35 LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);
36 /* synchronous clock HCLK/4 = 16 MHz: independent of the ADC kernel clock mux */
37 LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CLOCK_SYNC_PCLK_DIV4);
38 LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT);
39
40 if (LL_ADC_IsEnabled(ADC1)) return 0;
41 LL_ADC_DisableDeepPowerDown(ADC1);
42 LL_ADC_EnableInternalRegulator(ADC1);
43 delay_us(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US + 10u);
44
45 LL_ADC_StartCalibration(ADC1, LL_ADC_SINGLE_ENDED);
46 uint32_t t = 0;
47 while (LL_ADC_IsCalibrationOnGoing(ADC1)) if (++t > 1000000u) return -1;
48 delay_us(10u);
49
50 LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B);
51 LL_ADC_SetDataAlignment(ADC1, LL_ADC_DATA_ALIGN_RIGHT);
52 LL_ADC_SetChannelSamplingTime(ADC1, __LL_ADC_DECIMAL_NB_TO_CHANNEL(APP_BATT_VBAT_CH), LL_ADC_SAMPLINGTIME_247CYCLES_5);
53 LL_ADC_SetChannelSamplingTime(ADC1, __LL_ADC_DECIMAL_NB_TO_CHANNEL(APP_BATT_CUR_CH), LL_ADC_SAMPLINGTIME_247CYCLES_5);
54 LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_247CYCLES_5);
55 LL_ADC_SetChannelSingleDiff(ADC1, __LL_ADC_DECIMAL_NB_TO_CHANNEL(APP_BATT_VBAT_CH), LL_ADC_SINGLE_ENDED);
56 LL_ADC_SetChannelSingleDiff(ADC1, __LL_ADC_DECIMAL_NB_TO_CHANNEL(APP_BATT_CUR_CH), LL_ADC_SINGLE_ENDED);
57
58 /* injected group: VBAT, CUR, VREFINT, software trigger */
59 LL_ADC_INJ_SetTriggerSource(ADC1, LL_ADC_INJ_TRIG_SOFTWARE);
60 LL_ADC_INJ_SetSequencerLength(ADC1, LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS);
61 LL_ADC_INJ_SetSequencerRanks(ADC1, LL_ADC_INJ_RANK_1, __LL_ADC_DECIMAL_NB_TO_CHANNEL(APP_BATT_VBAT_CH));
62 LL_ADC_INJ_SetSequencerRanks(ADC1, LL_ADC_INJ_RANK_2, __LL_ADC_DECIMAL_NB_TO_CHANNEL(APP_BATT_CUR_CH));
63 LL_ADC_INJ_SetSequencerRanks(ADC1, LL_ADC_INJ_RANK_3, LL_ADC_CHANNEL_VREFINT);
64 /* 16x oversampling, shift 4: 12-bit average */
65 LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_GRP_INJECTED);
66 LL_ADC_ConfigOverSamplingRatioShift(ADC1, LL_ADC_OVS_RATIO_16, LL_ADC_OVS_SHIFT_RIGHT_4);
67
68 LL_ADC_ClearFlag_ADRDY(ADC1);
69 LL_ADC_Enable(ADC1);
70 t = 0;
71 while (!LL_ADC_IsActiveFlag_ADRDY(ADC1)) if (++t > 1000000u) return -1;
72 delay_us(LL_ADC_DELAY_VREFINT_STAB_US);
73 LL_ADC_ClearFlag_JEOS(ADC1);
74 LL_ADC_INJ_StartConversion(ADC1);
75 s_started = 1u;
76 return 0;
77}
78
79int batt_adc_read(float *vbat_pin, float *cur_pin)
80{
81 if (!s_started || !LL_ADC_IsActiveFlag_JEOS(ADC1)) return -1;
82 const uint32_t v = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_1);
83 const uint32_t c = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_2);
84 const uint32_t vr = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_3);
85 LL_ADC_ClearFlag_JEOS(ADC1);
86 LL_ADC_INJ_StartConversion(ADC1); /* next sample, read at the next call */
87 if (vr == 0u) return -1;
88 /* VDDA = 3.0 V × VREFINT_CAL / VREFINT (factory calibration at 3.0 V) */
89 const float vdda = (float)VREFINT_CAL_VREF * 1e-3f * (float)(*VREFINT_CAL_ADDR) / (float)vr;
90 *vbat_pin = vdda * (float)v / 4095.0f;
91 *cur_pin = vdda * (float)c / 4095.0f;
92 return 0;
93}
Phase-1 configuration: P-NUCLEO-WB55 (NUCLEO-WB55RG) + X-NUCLEO-IKS4A1 in Mode 3 (LSM6DSV16X is the s...
#define APP_BATT_VBAT_PORT
Definition app_config.h:155
#define APP_BATT_CUR_PIN
Definition app_config.h:159
#define APP_BATT_VBAT_CH
Definition app_config.h:154
#define APP_BATT_VBAT_PIN
Definition app_config.h:156
#define APP_BATT_CUR_PORT
Definition app_config.h:158
#define APP_BATT_CUR_CH
Definition app_config.h:157
static uint8_t s_started
Definition batt_adc.c:14
static void analog_pin(GPIO_TypeDef *port, uint32_t pin)
Definition batt_adc.c:22
static void delay_us(uint32_t us)
Definition batt_adc.c:16
int batt_adc_read(float *vbat_pin, float *cur_pin)
0 = a new sample: pin voltages in volts
Definition batt_adc.c:79
int batt_adc_init(void)
0 = ok
Definition batt_adc.c:30
ADC1 binding of the BattTask: VBAT and current pins, VREFINT.
uint32_t n
Definition calib_mgr.c:35
uint8_t port
Definition log_task.c:48