[HELP] Configuring the ADC to run at a higher sample rate.

Post here first, or if you can't find a relevant section!
Post Reply
Bambo
Posts: 75
Joined: Wed Jan 15, 2020 8:36 pm

[HELP] Configuring the ADC to run at a higher sample rate.

Post by Bambo »

Hi,

I'm working on a project where i need to sample a microphone at a sample rate of >16,000Hz. Using the built in analogRead() i can manage a sample rate of ~9000Hz. See below is the sequence of commands i'm using to try to configure the ADC prescaler to DIV1 to increase its speed, i have used this exact same code on an STM32L452RE-P and it worked, however, i'm now trying to port this code to a STM32L452RE.

This code was VERY buggy any relied on the analogRead() function to set up the GPIO, it doesn't work at all on the L452RE. The program executes until "HAL_ADC_Init()" and then the MCU halts?

Any ideas on how to get this working again?

Note: The microphone is on PA1.

Code: Select all

#include "stm32l4xx_hal_adc.h"

const int CONFIG_MIC_PIN = PA0;

unsigned long lastTick;
unsigned long timeNow;
unsigned long numberOfLoopIterations = 0;

ADC_HandleTypeDef adcConfiguration;

void SetupADC()
{
  /*
  // GPIO config
  __GPIOC_CLK_ENABLE();
  
  GPIO_InitTypeDef gpioConfiguration;
  gpioConfiguration.Pin = GPIO_PIN_0; // PC1
  gpioConfiguration.Mode = GPIO_MODE_ANALOG;
  gpioConfiguration.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &gpioConfiguration);

  pinMode(CONFIG_MIC_PIN, INPUT);
    */

  analogRead(CONFIG_MIC_PIN);
  
  // ADC peripheral
  adcConfiguration.Instance = ADC1;

  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
  adcConfiguration.Init.Resolution = ADC_RESOLUTION_12B;
  adcConfiguration.Init.ScanConvMode = DISABLE;
  adcConfiguration.Init.ContinuousConvMode = ENABLE;
  adcConfiguration.Init.DiscontinuousConvMode = ENABLE;
  adcConfiguration.Init.NbrOfDiscConversion = 0;
  adcConfiguration.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  adcConfiguration.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  adcConfiguration.Init.NbrOfConversion = 1;
  adcConfiguration.Init.DMAContinuousRequests = ENABLE;
  adcConfiguration.Init.EOCSelection = ADC_EOC_SEQ_CONV;

  
  HAL_StatusTypeDef result = HAL_ADC_Init(&adcConfiguration);
  // 0 = ok
  // 1 = error
  // 2 = busy
  // 3 = timeout
  Serial.print("ADC Peripheral init: ");
  Serial.println(result); // returns 1

  
  
  // ADC channel
  ADC_ChannelConfTypeDef adcChannelConfiguration;
  adcChannelConfiguration.Channel = ADC_CHANNEL_6;
  adcChannelConfiguration.Rank = 1;
  adcChannelConfiguration.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  adcChannelConfiguration.Offset = 0;
  adcChannelConfiguration.SingleDiff = ADC_SINGLE_ENDED;
  adcChannelConfiguration.OffsetNumber = ADC_OFFSET_NONE;


  Serial.print("ADC Channel init: ");
  Serial.println(HAL_ADC_ConfigChannel(&adcConfiguration, &adcChannelConfiguration));
}

void setup()
{
  Serial.begin(9600);
 
  SetupADC();

  lastTick = millis();
}

void loop()
{
  // start the conversion process
  HAL_ADC_Start(&adcConfiguration);
  
  //wait for the conversion to finish
  if (HAL_ADC_PollForConversion(&adcConfiguration, 100000) == HAL_OK)
  {
    // conversion completed successfully.
    uint16_t sample = HAL_ADC_GetValue(&adcConfiguration);
    //Serial.print("Value:");
    Serial.println(sample);
  }

  HAL_ADC_Stop(&adcConfiguration);
        
  timeNow = millis();

  // every 1 second.
  if ( (timeNow - lastTick) >= 1000)
  {
    //Serial.println(numberOfLoopIterations);
    numberOfLoopIterations = 0;
    lastTick = timeNow;
  }
  
  numberOfLoopIterations++;
}

Thanks,
Richard
Bambo
Posts: 75
Joined: Wed Jan 15, 2020 8:36 pm

Re: [HELP] Configuring the ADC to run at a higher sample rate.

Post by Bambo »

Update:
Using this code, if i change the adcConfiguration.Init.ClockPrescaler it does change the sample rate, but the channel is printing the the same numbers over the serial port continuously?

Code: Select all


	// ADC configuration
	adcConfiguration.Instance = ADC1;

	adcConfiguration.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV64; // div 1 fastest it can go.
	adcConfiguration.Init.Resolution = ADC_RESOLUTION_12B; // 12 bit resolution
	adcConfiguration.Init.ScanConvMode = DISABLE;
	adcConfiguration.Init.ContinuousConvMode = ENABLE;
	adcConfiguration.Init.DiscontinuousConvMode = ENABLE;
	adcConfiguration.Init.NbrOfDiscConversion = 0;
	adcConfiguration.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
	adcConfiguration.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
	adcConfiguration.Init.DataAlign = ADC_DATAALIGN_RIGHT;
	adcConfiguration.Init.NbrOfConversion = 1;
	adcConfiguration.Init.DMAContinuousRequests = ENABLE;
	adcConfiguration.Init.EOCSelection = EOC_SEQ_CONV;

	HAL_StatusTypeDef result = HAL_ADC_Init(&adcConfiguration);
	if (result != HAL_OK)
	{
		SerialInterface.PrintLn(F("HAL NOT OK"));
		SerialInterface.Print(result);
	}
Post Reply

Return to “General discussion”