Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sampling at 16KHz using ADC prescaler? #747

Closed
Bambofy opened this issue Oct 31, 2019 · 33 comments
Closed

Sampling at 16KHz using ADC prescaler? #747

Bambofy opened this issue Oct 31, 2019 · 33 comments
Labels
question ❓ Usually converted as a discussion

Comments

@Bambofy
Copy link

Bambofy commented Oct 31, 2019

Hi, I need to sample the ADC at 16KHz to create an audio file. How can I do this using stm32duino?

Many thanks,
Richard

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Hi @Bambofy
on which board? Nucleo-L452RE-P?

ADC is limited on this core to analogRead() API which made a single conversion at a time. This is really not optimized and do not use all ADC capabilities.
You can try to play with ADC_SAMPLINGTIME and ADC_CLOCK_DIV which can be redefined thanks build_opt.h.

#ifndef ADC_SAMPLINGTIME


Else use directly HAL/LL to play with ADC.

FYI, an issue is already opened to have an advanced ADC library with convenient API to use them #5

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

ok thank you

@fpistm fpistm added the question ❓ Usually converted as a discussion label Oct 31, 2019
@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

I'm trying to use the HAL api to set the prescaler of the ADC like this:

void setup()
{
  Serial.begin(9600);
  
  // put your setup code here, to run once:
  pinMode(CONFIG_MIC_PIN, INPUT);
  lastTick = millis();

  ADC_HandleTypeDef adcConfiguration;
  adcConfiguration.Instance = ADC1;
  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_LEFT;
  adcConfiguration.Init.ScanConvMode = DISABLE;
  adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  adcConfiguration.Init.LowPowerAutoWait = ENABLE;

  Serial.println(adcConfiguration.Init.ClockPrescaler);
  
  HAL_StatusTypeDef result = HAL_ADC_Init(&adcConfiguration);

  // 0 = ok
  // 1 = error
  // 2 = busy
  // 3 = timeout
  Serial.println(result); // returns 1
}

The status code returned is 1 (HAL_StatusTypeDef).

And it still samples at 9KHz? The analog pin is A0 / PA0?

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

which board ?

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

which board ?

NUCLEO-L452RE-P

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

and how you read value ?

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

and how you read value ?

void loop()
{
  byte sample = analogRead(CONFIG_MIC_PIN); // this should be 8 bits now.
 }

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Using analogRead call again the HAL_ADC_Init so your setup is simply ignore.

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

Ok is this setup ok? i'm not sure how to actually read the ADC now though:


#include "stm32l4xx_hal_adc.h"

const int CONFIG_MIC_PIN = PA0;

ADC_HandleTypeDef adcConfiguration;

void setup()
{
  Serial.begin(9600);
  
  // put your setup code here, to run once:
  pinMode(CONFIG_MIC_PIN, INPUT);

// adcConfiguration.Instance = ADC1;
//  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
//  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
//  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_LEFT;
//  adcConfiguration.Init.ScanConvMode = DISABLE;
//  adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
//  adcConfiguration.Init.LowPowerAutoWait = ENABLE;
//  

  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
  adcConfiguration.Init.Resolution = ADC_RESOLUTION_12B;
  adcConfiguration.Init.ScanConvMode = DISABLE;
  adcConfiguration.Init.ContinuousConvMode = ENABLE;
  adcConfiguration.Init.DiscontinuousConvMode = DISABLE;
  adcConfiguration.Init.NbrOfDiscConversion = 0;
  adcConfiguration.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
  adcConfiguration.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  adcConfiguration.Init.NbrOfConversion = 1;
  adcConfiguration.Init.DMAContinuousRequests = ENABLE;
  adcConfiguration.Init.EOCSelection = DISABLE;
    
  //Serial.println(adcConfiguration.Init.ClockPrescaler);
  
  HAL_StatusTypeDef result = HAL_ADC_Init(&adcConfiguration);

  HAL_ADC_Start(&adcConfiguration);

  // 0 = ok
  // 1 = error
  // 2 = busy
  // 3 = timeout
  Serial.println(result); // returns 1
}

void loop()
{
  //byte sample = analogRead(CONFIG_MIC_PIN); // this should be 8 bits now.
  if (HAL_ADC_PollForConversion(&adcConfiguration, 1000000) == HAL_OK)
  {
      uint32_t g_ADCValue = HAL_ADC_GetValue(&adcConfiguration);
      Serial.println(g_ADCValue);
  }
}

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

when i poll for conversion, it never receives HAL_OK

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

i guess i need to set up all the other pin information, see https://visualgdb.com/tutorials/arm/stm32/adc/

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Here an example:
https://github.com/STMicroelectronics/STM32CubeL4/blob/f6877af03b5c8b666b3443f5295cf95ec9c0b15d/Projects/NUCLEO-L452RE/Examples/ADC/ADC_RegularConversion_Polling/Src/main.c#L52

you have to call start and poll for conversion, I guess.
And also configure channel.

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Ah! Also call first analogRead(CONFIG_MIC_PIN) to init the g_current_pin then the HAL_ADC_MspInit
will enable the clock and properly init the pin.

So, in Setup():

void setup()
{
  Serial.begin(9600);
analogRead(CONFIG_MIC_PIN);
<your init code, do not use pinMode>

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

how do i find out what channel my analog pin is?

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

In the datasheet or in the PeripheralsPin.c

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

Ok so both ADC init functions return OK but the code get stuck polling for a value?

#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 setup()
{
  Serial.begin(9600);
  
  // put your setup code here, to run once:
  //pinMode(CONFIG_MIC_PIN, INPUT);
  analogRead(CONFIG_MIC_PIN);
  lastTick = millis();

//  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
//  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
//  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_LEFT;
//  adcConfiguration.Init.ScanConvMode = DISABLE;
//  adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
//  adcConfiguration.Init.LowPowerAutoWait = ENABLE;
//  

  // ADC peripheral
  adcConfiguration.Instance = ADC1;

  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
  adcConfiguration.Init.Resolution = ADC_RESOLUTION_12B;
  adcConfiguration.Init.ScanConvMode = DISABLE;
  adcConfiguration.Init.ContinuousConvMode = ENABLE;
  adcConfiguration.Init.DiscontinuousConvMode = DISABLE;
  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 = DISABLE;

  
  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_1;
  adcChannelConfiguration.Rank = 1;
  adcChannelConfiguration.SamplingTime = LL_ADC_SAMPLINGTIME_92CYCLES_5;
  adcChannelConfiguration.Offset = 0;


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

}

void loop()
{
  //byte sample = analogRead(CONFIG_MIC_PIN); // this should be 8 bits now.
  if (HAL_ADC_PollForConversion(&adcConfiguration, 1000000) == HAL_OK)
  {
      uint32_t g_ADCValue = HAL_ADC_GetValue(&adcConfiguration);
  //    //Serial.print("Value:");
      Serial.println(g_ADCValue);
      //Serial.println("");
  }
        
  timeNow = millis();

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

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Could you try this, I'm at home and I've not the board.

const int CONFIG_MIC_PIN = PA0;

ADC_HandleTypeDef adcConfiguration = {};
ADC_ChannelConfTypeDef  AdcChannelConf = {};

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

  // put your setup code here, to run once:
  analogRead(CONFIG_MIC_PIN);

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


  if ( HAL_ADC_Init(&adcConfiguration) != HAL_OK) {
    Serial.println("HAL_ADC_Init failed");
    while (1);
  }
  AdcChannelConf.Channel      = ADC_CHANNEL_5;                          /* Specifies the channel to configure into ADC */
  AdcChannelConf.Rank         = ADC_REGULAR_RANK_1;               /* Specifies the rank in the regular group sequencer */
  /*##-2- Configure ADC regular channel ######################################*/
  if (HAL_ADC_ConfigChannel(&adcConfiguration, &AdcChannelConf) != HAL_OK) {
    /* Channel Configuration Error */
    Serial.println("HAL_ADC_ConfigChan failed");
    while (1);
  }

  if (HAL_ADCEx_Calibration_Start(&adcConfiguration, ADC_SINGLE_ENDED) !=  HAL_OK) {
    Serial.println("HAL_ADCEx_Calibration_Start failed");
    while (1);
  }
}

void loop()
{
  if (HAL_ADC_Start(&adcConfiguration) != HAL_OK) {
    /* Start Conversation Error */
    Serial.println("HAL_ADC_Start failed");
    while (1);
  }

  if (HAL_ADC_PollForConversion(&adcConfiguration, 10) == HAL_OK)
  {
    if ((HAL_ADC_GetState(&adcConfiguration) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC) {
      Serial.println(HAL_ADC_GetValue(&adcConfiguration));
    }
  }
}

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

Could you try this, I'm at home and I've not the board.

It has "HAL_ADC_Init failed"

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

This code is working but when i do HAL_ADC_GetValue i get no value


const int CONFIG_MIC_PIN = PA0;

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

ADC_HandleTypeDef adcConfiguration;


void setup()
{
  Serial.begin(9600);
  
  // put your setup code here, to run once:
  //pinMode(CONFIG_MIC_PIN, INPUT);
  analogRead(CONFIG_MIC_PIN);
  lastTick = millis();

//  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
//  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
//  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_LEFT;
//  adcConfiguration.Init.ScanConvMode = DISABLE;
//  adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
//  adcConfiguration.Init.LowPowerAutoWait = ENABLE;
//  

  // GPIO config

  // 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 = DISABLE;
  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 = DISABLE;

  
  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 = LL_ADC_CHANNEL_5;
  adcChannelConfiguration.Rank = 1;
  adcChannelConfiguration.SamplingTime = LL_ADC_SAMPLINGTIME_92CYCLES_5;
  adcChannelConfiguration.Offset = 0;


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

  Serial.print("ADC Start: ");
  Serial.println(HAL_ADC_Start(&adcConfiguration));

}

void loop()
{
  //byte sample = analogRead(CONFIG_MIC_PIN); // this should be 8 bits now.
  if (HAL_ADC_PollForConversion(&adcConfiguration, 1) == HAL_OK)
  {
    uint32_t sample = HAL_ADC_GetValue(&adcConfiguration);
     //Serial.print("Value:");
     //Serial.println(sample);
      //Serial.println("");
  }
        
  timeNow = millis();

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

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

I use your config, so maybe something is wrong.
Please check.

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

HAL_ADC_Start(&adcConfiguration); should be call in the loop.

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

ADC_EOC_SINGLE_CONV should be set to use HAL_ADC_PollForConversion
adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* EOC flag picked-up to indicate conversion end */

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

ok i'm still testing, how do i define which pin i want to use?

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

ok heres my current code:

#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()
{
  //  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
//  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
//  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_LEFT;
//  adcConfiguration.Init.ScanConvMode = DISABLE;
//  adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
//  adcConfiguration.Init.LowPowerAutoWait = ENABLE;
//  

  // GPIO config

  // ADC peripheral
  adcConfiguration.Instance = ADC1;

  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
  adcConfiguration.Init.ScanConvMode = DISABLE;
  adcConfiguration.Init.ContinuousConvMode = ENABLE;
  adcConfiguration.Init.DiscontinuousConvMode = DISABLE;
  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_SINGLE_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_2;
  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));

  Serial.print("ADC Start: ");
  Serial.println(HAL_ADC_Start(&adcConfiguration));
}

void setup()
{
  Serial.begin(9600);
  
  // put your setup code here, to run once:
  pinMode(CONFIG_MIC_PIN, INPUT);
  lastTick = millis();
}

void loop()
{
  SetupADC();
  
  //byte sample = analogRead(CONFIG_MIC_PIN); // this should be 8 bits now.
  if (HAL_ADC_PollForConversion(&adcConfiguration, 100000) == HAL_OK)
  {
      uint8_t sample = HAL_ADC_GetValue(&adcConfiguration);
     Serial.print("Value:");
     Serial.println(sample);
      //Serial.println("");
  }
        
  timeNow = millis();

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

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Well, I will test on monday and check why it does not work.
As I said I'm at home with no board so hard to check.

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

it's alive!! you have to call Start() then Poll() then Stop() for the process to get a new value :) 👍 here's a working sketch (analog input on pin A4/PC0)


const int CONFIG_MIC_PIN = PA0;

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

ADC_HandleTypeDef adcConfiguration;

void SetupADC()
{
  //  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
//  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
//  adcConfiguration.Init.DataAlign = ADC_DATAALIGN_LEFT;
//  adcConfiguration.Init.ScanConvMode = DISABLE;
//  adcConfiguration.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
//  adcConfiguration.Init.LowPowerAutoWait = ENABLE;
//  

  // GPIO config

  // 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_1;
  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++;
}```

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Great!

@Bambofy
Copy link
Author

Bambofy commented Oct 31, 2019

Figured it out :) The answer is to change which "Channel" the channel configuration is listening to. For the NUCLEO-L452RE-P it is here https://www.st.com/content/ccc/resource/technical/document/user_manual/group0/ff/5d/51/50/db/12/47/98/DM00387966/files/DM00387966.pdf/jcr:content/translations/en.DM00387966.pdf at page 36.

Looking at a row in the table:
PA0 -> ADC1_IN5 means for ADC 1 the channel 5.

@fpistm
Copy link
Member

fpistm commented Oct 31, 2019

Right, that's why in my example code i've set ADC_CHANNEL_5 😉

@Bambofy Bambofy closed this as completed Nov 1, 2019
@Bambofy
Copy link
Author

Bambofy commented Nov 7, 2019

Hey, sorry to bring this issue up again but i'm struggling to change the pin that the data in being input to, see this code:

I set the GPIO C pin 1 to analog and the ADC_CHANNEL to 2. to match this table
PC1 -> Channel 2

firefox_vtxCcFv48s

A weird note is that if you:

  1. take off the GPIO setup
  2. put analogRead(PC0)
  3. set channel to channel 5

it correctly receives the values at the channel, and it completely ignores which pin you put into analogRead()?

#include "stm32l4xx_hal_adc.h"

const int CONFIG_MIC_PIN = PC1;

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_1; // PC1
  gpioConfiguration.Mode = GPIO_MODE_ANALOG;
  gpioConfiguration.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &gpioConfiguration);

  //pinMode(CONFIG_MIC_PIN, INPUT);
    
  // ADC peripheral
  adcConfiguration.Instance = ADC1;

  adcConfiguration.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV1;
  adcConfiguration.Init.Resolution = ADC_RESOLUTION_8B;
  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_2;
  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++;
}

@Bambofy Bambofy reopened this Nov 7, 2019
@fpistm
Copy link
Member

fpistm commented Nov 7, 2019

@Bambofy
I could not debug all code users do.
Anyway, as I said before the call of analogRead() one time allow to use the HAL_ADC_MspInit which init the ADC clock. I didn't see any __HAL_RCC_ADC_CLK_ENABLE(); in your code. I guess this could be a good track.

@fpistm fpistm closed this as completed Nov 7, 2019
@LMESTM
Copy link
Member

LMESTM commented Nov 7, 2019

@Bambofy
I agree with @fpistm that he can't debug everyone's program :-)
Issues in stm32duino repo should refer to problems found inside the stm32duino core implementation, not in program using them.
Moreover, you are not using stm32duino core / arduino APIs but rather accessing directly to HAL layer from stm32 CubeFW. This is a very valid approach, but you hopefully could find more adequate support around here: https://community.st.com/s/topic/0TO0X000000BSqSWAW/stm32-mcus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question ❓ Usually converted as a discussion
Projects
None yet
Development

No branches or pull requests

3 participants