cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F410 Bat voltage measurement consumption

RSchl.2
Associate II

Hi everyone,

I was just wondering if measuring VBat in continuous will drain the battery faster ? And how fast ?

Unfortunately, I don't have tools that should be able to measure such a low current.

I use the STM32F410CB in my project. I use the adc1 (the only available) with channel 0 and 1. I use DMA continuous requests.

I have added a battery and measure it with the same ADC. Works

perfectly. But I'm afraid that the continuous measurement of vbat will really drain my battery.

1 ACCEPTED SOLUTION

Accepted Solutions
RSchl.2
Associate II

Thank you for your answers.

Everything is working fine. This is how I managed to do it

 
while(1)
{
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*) s_analog_data,
		SAMPLE_SIZE * ANALOG_IN_INDEX_max);
	
	osDelay(pdMS_TO_TICKS(2));
	HAL_ADC_Stop_DMA(&hadc1);
	
	// suspend the scheduler to prevent race condition of variable
	// s_ai_encoder_val, s_ai_second_val and s_ai_bat_voltage_val
	vTaskSuspendAll();
	
	s_ai_encoder_val = get_average(s_analog_data, ANALOG_IN_INDEX_encoder,
			SAMPLE_SIZE);
	s_ai_second_val = get_average(s_analog_data, ANALOG_IN_INDEX_second,
			SAMPLE_SIZE);
	
	if ((xTaskGetTickCount() - last_updated_tick > VBAT_PERIOD_TICK)
			|| (0 == s_ai_bat_voltage_val))
	{
		last_updated_tick = xTaskGetTickCount();
 
		ADC_InitTypeDef last_def;
		mAnalogIn_configure_vbat(&last_def);
	
		HAL_ADC_Start(&hadc1);
		s_ai_bat_voltage_val = HAL_ADC_GetValue(&hadc1);
	
		// Protect against an over and over reading of an
		// not connected battery
		if (0 == s_ai_bat_voltage_val)
		{
			s_ai_bat_voltage_val = 1;
		}
	
		mAnalogIn_configure_2_channels(&last_def);
	}
	
	// re-enable scheduler
	xTaskResumeAll();
}

It miss some function definitions but I think it speeks for itself.

View solution in original post

6 REPLIES 6
TDK
Guru

Each time you take a measurement, it has to charge up an internal capacitor. So yes, it will drain faster than if you didn't measure it at all. How much faster is hard to estimate. A series resistor may shed some light. There is no reason you should be continuously measuring the battery. It shouldn't be changing that quickly.

If you feel a post has answered your question, please click "Accept as Solution".

This is what you should be concerned about:

0693W000003OwEQQA0.png

As TDK said, there's no reason to measure VBAT continuously. Measure it only as rarely as it is feasible and don't forget to switch off ADC_CCR.VBATE between measurements.

Also observe the stabilization time in that table.

JW

RSchl.2
Associate II

Thank's for the quick replies and the given table.

"don't forget to switch off ADC_CCR.VBATE" -> If I use HAL drivers, it should be configured automatically and correctly ?

I was searching information in the "RM0401- Reference manual - STM32F410 advanced Arm®-based 32-bit MCUs". I see that it's not the good datasheet for this kind of things.

Before going deeper, let me tell you that I use HAL drivers because I'm not concerned about performance. It is really painfull to work with but it is faster than writing the driver by myself.

The only reason to measure it continuously it's just because it's easier. I've setup DMA to store all the 3 channels in a circular buffer declared like this :

#define MY_BUFFER_SIZE ((8) * (TASK_DELAY_MS))
#define MAX_CHANNEL (3)
static uint16_t s_analog_buf[MY_BUFFER_SIZE][MAX_CHANNEL]

So I will change my code like this:

  1. Configure ADC to only work with 2 channels
  2. Set the dma array accordingly
  3. Then, in the ADC_task :
  4. If (xTaskGetTickCount() - last_refresh_tick > VBAT_SAMPLING_PERIOD_TICK) // all values are unsigned here
    1. Stop ADC_DMA
    2. configure ADC to sample only VBAT
    3. start a conversion in blocking mode (since 5us is enough to measure vbat correctly)
    4. read the value
    5. configure ADC as before
    6. restart ADC_DMA

I think it will do the job. If you have a better idea, let me know 😊 👍

> If I use HAL drivers, it should be configured automatically and correctly ?

I don't know, I don't use Cube/HAL. But it's open source, you can find out yourself.

> I think it will do the job.

Sounds feasible.

JW

TDK
Guru

If you're using an RTOS, you'll run into issues if the ADC is being accessed from two different tasks.

If you feel a post has answered your question, please click "Accept as Solution".
RSchl.2
Associate II

Thank you for your answers.

Everything is working fine. This is how I managed to do it

 
while(1)
{
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*) s_analog_data,
		SAMPLE_SIZE * ANALOG_IN_INDEX_max);
	
	osDelay(pdMS_TO_TICKS(2));
	HAL_ADC_Stop_DMA(&hadc1);
	
	// suspend the scheduler to prevent race condition of variable
	// s_ai_encoder_val, s_ai_second_val and s_ai_bat_voltage_val
	vTaskSuspendAll();
	
	s_ai_encoder_val = get_average(s_analog_data, ANALOG_IN_INDEX_encoder,
			SAMPLE_SIZE);
	s_ai_second_val = get_average(s_analog_data, ANALOG_IN_INDEX_second,
			SAMPLE_SIZE);
	
	if ((xTaskGetTickCount() - last_updated_tick > VBAT_PERIOD_TICK)
			|| (0 == s_ai_bat_voltage_val))
	{
		last_updated_tick = xTaskGetTickCount();
 
		ADC_InitTypeDef last_def;
		mAnalogIn_configure_vbat(&last_def);
	
		HAL_ADC_Start(&hadc1);
		s_ai_bat_voltage_val = HAL_ADC_GetValue(&hadc1);
	
		// Protect against an over and over reading of an
		// not connected battery
		if (0 == s_ai_bat_voltage_val)
		{
			s_ai_bat_voltage_val = 1;
		}
	
		mAnalogIn_configure_2_channels(&last_def);
	}
	
	// re-enable scheduler
	xTaskResumeAll();
}

It miss some function definitions but I think it speeks for itself.