Skip to content

Add internal ADC channels (REF, TEMP, BAT) #474

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

Closed
karstengit opened this issue Mar 16, 2019 · 2 comments · Fixed by #539
Closed

Add internal ADC channels (REF, TEMP, BAT) #474

karstengit opened this issue Mar 16, 2019 · 2 comments · Fixed by #539
Labels
enhancement New feature or request
Milestone

Comments

@karstengit
Copy link

It's perfect that the normal Arduino way of reading an ADC is working.

But it is not working to read the internal temperature sensor.
For example this is not working:
ADCValue = analogRead(ADC_CHANNEL_TEMPSENSOR);
but i found the value ADC_CHANNEL_TEMPSENSOR defined in stm32f1xx_hal_adc.h.

Is there an alternative way?
Thanks in advance.

@ppescher
Copy link
Contributor

Hi,
You can see my solution for my STM32L4 variant here:
fortebit@a0c9bee
fortebit@2a20f47

That allows you to call e.g. analogRead(VTEMP) to read the internal temperature sensor.

Please note that the ADC value must then be converted to Celsius degrees by using the calibration values in ROM locations (depending on the specific MCU).
You will also need to enable the internal channels before you can read them, see for example:
https://os.mbed.com/users/EricLew/code/STM32L4xx_HAL_Driver/docs/tip/group__ADC__LL__EF__Configuration__ADC__Common.html#gada4e99bea81f03d942d2f6d51b360154

I'm not sure that is the proper way to implement it on the Stm32 Arduino core or whether it can be generalized easily for other variants, but it works for me.

This is still a work in progress, but I can post a complete working example sketch if you want.

@fpistm
Copy link
Member

fpistm commented Mar 18, 2019

Hi @karstengit.
Currently no dedicated API.
But it is possible using HAL/LL directly.
@ppescher proposal is the way I will provide when I will work on ADC.

You can try also this which doesn't require core modification, only at sketch level:
(discuss here some time ago:http://www.stm32duino.com/viewtopic.php?f=48&t=3489&hilit=LL_ADC+TEMp&start=30#p44473)


uint16_t adc_read(uint32_t channel)
{
  ADC_HandleTypeDef AdcHandle = {};
  ADC_ChannelConfTypeDef  AdcChannelConf = {};
  __IO uint16_t uhADCxConvertedValue = 0;

  AdcHandle.Instance = ADC1;
  AdcHandle.State = HAL_ADC_STATE_RESET;
  AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;           /* Right-alignment for converted data */
  AdcHandle.Init.ScanConvMode          = DISABLE;                       /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
  AdcHandle.Init.ContinuousConvMode    = DISABLE;                       /* Continuous mode disabled to have only 1 conversion at each conversion trig */
  AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
  AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */
  AdcHandle.Init.NbrOfConversion       = 1;                             /* Specifies the number of ranks that will be converted within the regular group sequencer. */
  AdcHandle.Init.NbrOfDiscConversion   = 0;                             /* Parameter discarded because sequencer is disabled */

  if (HAL_ADC_Init(&AdcHandle) != HAL_OK) {
    return 0;
  }

  AdcChannelConf.Channel      = channel;             /* Specifies the channel to configure into ADC */
  AdcChannelConf.Rank         = ADC_REGULAR_RANK_1;               /* Specifies the rank in the regular group sequencer */
  AdcChannelConf.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;                     /* Sampling time value to be set for the selected channel */

  /*##-2- Configure ADC regular channel ######################################*/
  if (HAL_ADC_ConfigChannel(&AdcHandle, &AdcChannelConf) != HAL_OK)
  {
    /* Channel Configuration Error */
    return 0;
  }
  /*##-2.1- Calibrate ADC then Start the conversion process ####################*/
  if (HAL_ADCEx_Calibration_Start(&AdcHandle) !=  HAL_OK) {
    /* ADC Calibration Error */
    return 0;
  }
  /*##-3- Start the conversion process ####################*/
  if (HAL_ADC_Start(&AdcHandle) != HAL_OK) {
    /* Start Conversation Error */
    return 0;
  }
  /*##-4- Wait for the end of conversion #####################################*/
  /*  For simplicity reasons, this example is just waiting till the end of the
      conversion, but application may perform other tasks while conversion
      operation is ongoing. */
  if (HAL_ADC_PollForConversion(&AdcHandle, 10) != HAL_OK) {
    /* End Of Conversion flag not set on time */
    return 0;
  }
  /* Check if the continous conversion of regular channel is finished */
  if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC) {
    /*##-5- Get the converted value of regular channel  ########################*/
    uhADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
  }

  if (HAL_ADC_Stop(&AdcHandle) != HAL_OK) {
    /* Stop Conversation Error */
    return 0;
  }
  if(HAL_ADC_DeInit(&AdcHandle) != HAL_OK) {
    return 0;
  }
  return uhADCxConvertedValue;
}

void setup() {
  Serial.begin(115000);
  analogRead(A0); // Workaround to init g_current_pin used in HAL_ADC_MspInit
}

void loop() {
  float Vdd = readVdd();
  Serial.print("Vdd=  ");
  Serial.print(Vdd);
  Serial.print(" V Temp= ");
  Serial.print(readTempSensor(Vdd));
  Serial.println(" °C");
  delay(500);
}

static float readVdd()
{
  return (1.20 * 4096.0 / adc_read(ADC_CHANNEL_VREFINT)); // ADC sample to V
  //return (1200 * 4096 / adc_read(ADC_CHANNEL_VREFINT)); // ADC sample to mV
}

static float readTempSensor(float Vdd)
{
  return ((1.43 - (Vdd / 4096.0 * adc_read(ADC_CHANNEL_TEMPSENSOR))) / 0.0043 + 25.0);
}

@fpistm fpistm changed the title ADC_CHANNEL_TEMPSENSOR can not be read Add internal ADC channels (REF, TEMP, BAT) Mar 18, 2019
fpistm added a commit to fpistm/Arduino_Core_STM32 that referenced this issue Jun 10, 2019
@fpistm fpistm added this to the 1.6.0 milestone Jun 10, 2019
fpistm added a commit to fpistm/Arduino_Core_STM32 that referenced this issue Jun 10, 2019
fpistm added a commit to fpistm/Arduino_Core_STM32 that referenced this issue Jun 11, 2019
@fpistm fpistm added enhancement New feature or request and removed Request labels Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants