cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with STM32L0 Basic ADC Operation

RSoen.1
Associate II

I am having trouble getting the ADC to work right in basic polled operation. I am polling two channels which provide voltages via resistor dividers. I have measured the voltages at the ADC inputs and they are correct so I do not believe the divider impedances are too high.

I get an ADC result that does not vary much. For example I get around 420 counts (out of 4096) with 0.9V at the input. With that voltage I should see ~1100 counts. And the result does not seem to vary with voltage...

Here is my setup, I would appreciate any advice.

static void MX_ADC_Init(void)
{
 
  /* USER CODE BEGIN ADC_Init 0 */
 
  /* USER CODE END ADC_Init 0 */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC_Init 1 */
 
  /* USER CODE END ADC_Init 1 */
  /** 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_SYNC_PCLK_DIV4;
  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_SINGLE_CONV;
  hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc.Init.LowPowerAutoWait = ENABLE;
  hadc.Init.LowPowerFrequencyMode = ENABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_0;
  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_2;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC_Init 2 */
 
 
 
  /* USER CODE END ADC_Init 2 */
 
}

This is called periodically:

uint16_t adcGetVolt(void)
{
  volatile float V = 0;
 
  // Get ADC value
  adcConfig.Channel = ADC_CHANNEL_2;
  HAL_ADC_ConfigChannel(&hadc, &adcConfig);
  HAL_ADC_Start(&hadc);
  HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
  sampleValue = HAL_ADC_GetValue(&hadc);
 
  V = ((((float)sampleValue/4096.0f) * 3.30f) / VOLT_DIVIDER_MULTIPLIER);//.0697
 
  volts_average = V;
  return((uint16_t)((volts_average*10.0f) + 0.5f));
 
}

Alway returns ~420 counts

and also:

int16_t read_temperature(void)
{
		float v, i, r, temperature_low, temperature_high, temperature, delta;
		int char_index;
		int16_t temp, temp_single;
//		bool no_thermistor = false;
 
		  adcConfig.Channel = ADC_CHANNEL_0;
		  HAL_ADC_ConfigChannel(&hadc, &adcConfig);
		  HAL_ADC_Start(&hadc);
		  HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
		  sampleValue2 = HAL_ADC_GetValue(&hadc);

Also always returns ~420 counts

4 REPLIES 4
RSoen.1
Associate II

I have VDDA tied to 3.3V so that is the reference for the ADC correct?

Anyone know of an ADC (simple polling) for the L0 series? I cannot find any in the import examples in STM32CUBE ide...

Javier1
Principal

my aracnosense tells me the problem is here:

  V = ((((float)sampleValue/4096.0f) * 3.30f) / VOLT_DIVIDER_MULTIPLIER);//.0697

you can start your debugg session and screen your sampleValue variable and see if its good.

we dont need to firmware by ourselves, lets talk
Ozone
Lead

I would attach a potentiometer to the ADC input and vary the input between 0...3.3V.

Take care to keep the input impedance low enough, I would not exceed 10k Ohm.

> my aracnosense tells me the problem is here: ...

That could be true.

The C type promotion rules are confusing at times.

And there are floats and integers involved.

I would split up the combined calculation in multiple expressions first, and check the proper result of each operation.

Which pin and which STM32 exactly?

Read out and check/post content of ADC and relevant GPIO registers content, at the moment when you read out the converted result.

JW