AnsweredAssumed Answered

Stop mode power draw increases after configuring ADC

Question asked by Stefan Dzisiewski-Smith on Jan 23, 2017
Latest reply on Nov 28, 2017 by musskopf

Moving on from this question (now resolved) I am having difficulty in minimising STOP mode power consumption. To recap - I have a very simple setup really - long periods of minimal current consumption (15 minutes to 24 hours sleep duration) with short periods of activity in between. In my particular case, this is mostly ADC and GPIO manipulation (which explains some of the extra initialisation in my code which is unused) but for this example, I am just trying to achieve the following:

 

  1. Turn LED on
  2. Delay 1000ms (using HAL delay - don't care about efficiency here)
  3. Turn LED off
  4. Enter Stop mode
  5. Have RTC Wakeup Timer return me to Step 1. after 5 seconds

This now works well. However, when I compile and upload the code without the ADC enabled I get a STOP mode current draw of 2.8uA at 2.8V - this is acceptable for my application. Once I enable the ADC, however, I get a massive increase in STOP mode current consumption - up to 16.7uA.

Code is below - line 25 is the line where I choose to either enable or disable ADC config.

I have tried several things to get the power consumption back where it was (which should be achievable I guess because I am not using the ADC at all in STOP mode). These include:

  • de-initing the ADC with  HAL_ADC_DeInit(&hadc);
  • disabling VREFINT with HAL_ADCEx_DisableVREFINT();
  • disabling the internal temperature sensor with HAL_ADCEx_DisableVREFINTTempSensor();
  • disabling ADC1's clock (and disabling it in sleep) with __HAL_RCC_ADC1_CLK_DISABLE(); and __HAL_RCC_ADC1_CLK_SLEEP_DISABLE();

Frankly, at this point I have no idea what's pulling this extra current. Any ideas? Even if it's just a good debug strategy, it would be a great start!

 

 

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32l0xx_hal.h"
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc;
RTC_HandleTypeDef hrtc;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_ADC_Init(void);
static void MX_RTC_Init(void);
static void SystemPower_Config(void);
static void GPIO_to_analog_in(void);

int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
// MX_ADC_Init();
MX_RTC_Init();
SystemPower_Config();
while (1)
{
HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_RESET);
/* Disable Wakeup Counter */
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
/* Configure and enable Wakeup Counter */
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS) != HAL_OK)
{
Error_Handler();
}
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
}
/** System Clock Configuration
*/

void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/**Configure the main internal regulator output voltage
*/

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/**Initializes the CPU, AHB and APB busses clocks
*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI
|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV4;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/**Configure the Systick interrupt time
*/

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* ADC init function */
static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/

hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = ENABLE;
hadc.Init.LowPowerAutoPowerOff = ENABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/

sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/

sConfig.Channel = ADC_CHANNEL_4;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/

sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/

sConfig.Channel = ADC_CHANNEL_VREFINT;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
/* RTC init function */
static void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/**Initialize RTC Only
*/

hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/**Initialize RTC and set the Time and Date
*/

sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(SENSOR_EN_GPIO_Port, SENSOR_EN_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, LED_2_Pin|LED_1_Pin|LED_0_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : SELF_TEST_Pin */
GPIO_InitStruct.Pin = SELF_TEST_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SELF_TEST_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : SENSOR_EN_Pin */
GPIO_InitStruct.Pin = SENSOR_EN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SENSOR_EN_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : LED_2_Pin LED_1_Pin LED_0_Pin */
GPIO_InitStruct.Pin = LED_2_Pin|LED_1_Pin|LED_0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc){
}
static void SystemPower_Config(void)
{
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* Enable Ultra low power mode */
HAL_PWREx_EnableUltraLowPower();
HAL_PWREx_DisableFastWakeUp();
}
static void GPIO_to_analog_in(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : SELF_TEST_Pin SENSOR_EN_Pin */
GPIO_InitStruct.Pin = SELF_TEST_Pin | SENSOR_EN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG ;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : LED_2_Pin LED_1_Pin LED_0_Pin */
GPIO_InitStruct.Pin = LED_2_Pin|LED_1_Pin|LED_0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG ;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Error_Handler(void)
{
while(1)
{
}
}

Outcomes