4040#include " concurrency/LockGuard.h"
4141#endif
4242
43+ #if defined(ARCH_STM32WL) && defined(BATTERY_PIN)
44+ #include " stm32yyxx_ll_adc.h"
45+
46+ /* Analog read resolution */
47+ #if defined(LL_ADC_RESOLUTION_12B)
48+ #define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_12B
49+ #define BATTERY_SENSE_RESOLUTION_BITS 12
50+ #elif defined(LL_ADC_DS_DATA_WIDTH_12_BIT)
51+ #define LL_ADC_RESOLUTION LL_ADC_DS_DATA_WIDTH_12_BIT
52+ #define BATTERY_SENSE_RESOLUTION_BITS 12
53+ #else
54+ #error "ADC resolution could not be defined!"
55+ #endif
56+ #define ADC_RANGE (1 << BATTERY_SENSE_RESOLUTION_BITS)
57+ #endif
58+
4359#if defined(DEBUG_HEAP_MQTT) && !MESHTASTIC_EXCLUDE_MQTT
4460#include " mqtt/MQTT.h"
4561#include " target_specific.h"
@@ -328,11 +344,17 @@ class AnalogBatteryLevel : public HasBatteryLevel
328344 float scaled = 0 ;
329345
330346 battery_adcEnable ();
331- #ifdef ARCH_ESP32 // ADC block for espressif platforms
347+ #ifdef ARCH_STM32WL
348+ // STM32 ADC with VREFINT runtime calibration
349+ Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE (analogRead (AVREF), LL_ADC_RESOLUTION);
350+ raw = analogRead (BATTERY_PIN);
351+ scaled = __LL_ADC_CALC_DATA_TO_VOLTAGE (Vref, raw, LL_ADC_RESOLUTION);
352+ scaled *= operativeAdcMultiplier;
353+ #elif defined(ARCH_ESP32) // ADC block for espressif platforms
332354 raw = espAdcRead ();
333355 scaled = esp_adc_cal_raw_to_voltage (raw, adc_characs);
334356 scaled *= operativeAdcMultiplier;
335- #else // block for all other platforms
357+ #else // block for all other platforms
336358#ifdef ARCH_NRF52
337359 concurrency::LockGuard saadcGuard (concurrency::nrf52SaadcLock);
338360#endif
@@ -530,6 +552,11 @@ class AnalogBatteryLevel : public HasBatteryLevel
530552 bool initial_read_done = false ;
531553 float last_read_value = (OCV[NUM_OCV_POINTS - 1 ] * NUM_CELLS);
532554 uint32_t last_read_time_ms = 0 ;
555+ #ifdef ARCH_STM32WL
556+ // 3300mV placeholder for STM32 errata where VREFINT factory calibration may be missing
557+ // (e.g. STM32U0, see DS14756 Rev 3 §2.4.1 "VREFINT offset")
558+ uint32_t Vref = 3300 ;
559+ #endif
533560
534561#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT)
535562
@@ -639,7 +666,9 @@ bool Power::analogInit()
639666#define BATTERY_SENSE_RESOLUTION_BITS 10
640667#endif
641668
642- #ifdef ARCH_ESP32 // ESP32 needs special analog stuff
669+ #ifdef ARCH_STM32WL
670+ analogReadResolution (BATTERY_SENSE_RESOLUTION_BITS);
671+ #elif defined(ARCH_ESP32) // ESP32 needs special analog stuff
643672
644673#ifndef ADC_WIDTH // max resolution by default
645674 static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
@@ -649,7 +678,7 @@ bool Power::analogInit()
649678#ifndef BAT_MEASURE_ADC_UNIT // ADC1
650679 adc1_config_width (width);
651680 adc1_config_channel_atten (adc_channel, atten);
652- #else // ADC2
681+ #else // ADC2
653682 adc2_config_channel_atten (adc_channel, atten);
654683#ifndef CONFIG_IDF_TARGET_ESP32S3
655684 // ADC2 wifi bug workaround
@@ -679,7 +708,7 @@ bool Power::analogInit()
679708
680709 // NRF52 ADC init moved to powerHAL_init in nrf52 platform
681710
682- #ifndef ARCH_ESP32
711+ #if !defined( ARCH_ESP32) && !defined(ARCH_STM32WL)
683712 analogReadResolution (BATTERY_SENSE_RESOLUTION_BITS);
684713#endif
685714
0 commit comments