'Individually read distinct inputs with STM32L ADC

the goal is to read multiple ADC channels by polling. It does not need to be fast - the idea is to read the voltages from different batteries which are attached. I have a STM32L071 microcontroller. The programming is a bit different compared to the STM32F0 model.

I use platformio.

I found already very helpful information here:

However, unfortunately I cannot achieve to readout multiple channels. The problems are probably related to HAL_ADC_Init and HAL_ADC_ConfigChannel.

I provide here a minimum example of code:

#include <Arduino.h>
#include <STM32IntRef.h>

uint32_t a1=0, a2=0;

#define HAL_ADC_MODULE_ENABLED
ADC_HandleTypeDef hadc1;

void displaying(){
    Serial.println("values:");
    Serial.println("-------");
    Serial.print("ch1 - ");
    Serial.println(a1);
    Serial.print("ch2 - ");
    Serial.println(a2);
    Serial.println("");
}

void config_ext_channel_ADC(uint32_t channel, bool val)
{
  hadc1.Instance = ADC1;
  hadc1.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
  HAL_ADC_Init(&hadc1);
  
  ADC_ChannelConfTypeDef sConfig;
  sConfig.Channel = channel;
  if (val == true)  {
    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  }
  else  {
    sConfig.Rank = ADC_RANK_NONE;
  }
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
      {
        Serial.println("Error ADC Config Channel");
        //Error_Handler();
  }
}

uint32_t r_single_ext_channel_ADC(uint32_t channel)
{
  /* read the ADC and output result */
  uint32_t digital_result;
  config_ext_channel_ADC(channel, true);
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 1000);
  digital_result = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  config_ext_channel_ADC(channel, false);
  return digital_result;
}


void readBat() {
  /* read voltages */
  a1 = r_single_ext_channel_ADC(1);
  a2 = r_single_ext_channel_ADC(PA2);
}


void setup() {
  // put your setup code here, to run once:
  // Serial monitor
  Serial.begin(9600);
  Serial.println(F("Starting now"));
  // initialize pins for ADC
  analogReadResolution(ADC_RESOLUTION);
  pinMode(PA1, INPUT);
  //pinMode(BATTERY_SENSE_PIN2, INPUT);
  pinMode(PA2, INPUT_ANALOG);
}

void loop() {
  // put your main code here, to run repeatedly:
  readBat();
  displaying();
  delay(2000);
}

The output is:

values:
-------
ch1 - 0
ch2 - 140

Sounds reasonable, but applying some voltages at the pins do not change the values.

Could somebody please provide me some advice, ideas?



Solution 1:[1]

Did you miss to set the io to analog in mode ? should be something lke this somewhere (uslay in your hal msp file , adc_init func )

GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

edite => you missed it for ch1

  analogReadResolution(ADC_RESOLUTION);
  pinMode(PA1, INPUT);
  //pinMode(BATTERY_SENSE_PIN2, INPUT);
  pinMode(PA2, INPUT_ANALOG);

shall be same as PA2 , input is "digital mode"

Solution 2:[2]

Okay, in the meantime I found the problem. The software is fine; I took the Arduino framework and used analogRead().

I needed to clean all the solder flux from the PCB which caused some contacts between the pins. Moreover, if one wants to use address the HAL directly, one should set the ClockDivider such that the ADC samples below 1 MHz.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 pallago