Skip to content

Add ADC internal channels #539

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

Merged
merged 5 commits into from
Jun 11, 2019
Merged

Conversation

fpistm
Copy link
Member

@fpistm fpistm commented Jun 10, 2019

This PR add support of the following internal channels (ST HAL definitions):

  • ADC_CHANNEL_TEMPSENSOR
  • ADC_CHANNEL_VREFINT
  • ADC_CHANNEL_VBAT

analogRead() can now be used with the following definitions:

  • ATEMP
  • AVREF
  • AVBAT

A minimum ADC sampling time is required when reading internal channels so default is set it to max possible value. It can be defined more precisely by defining:

  • ADC_SAMPLINGTIME_INTERNAL
    to the desired ADC sample time.

This PR also add some hardening:

  • Add some missing channels (19 to 31)
  • Fix channels 16, 17 and 18 usage
  • Better ADC_HandleTypeDef and ADC_ChannelConfTypeDef management across series
  • ADC_SAMPLINGTIME and ADC_CLOCK_DIV could be redefined by the variant or using build_opt.h.

Fix #474

Hereafter an usage example which read then convert to proper Unit the 3 internal channels + A0:

#include "stm32yyxx_ll_adc.h"

/* Values available in datasheet */
#define CALX_TEMP 25
#if defined(STM32F1xx)
#define V25       1430
#define AVG_SLOPE 4300
#define VREFINT   1200
#elif defined(STM32F2xx)
#define V25       760
#define AVG_SLOPE 2500
#define VREFINT   1210
#endif

/* Analog read resolution */
#if ADC_RESOLUTION == 10
#define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_10B
#define ADC_RANGE 1024
#else
#define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_12B
#define ADC_RANGE 4096
#endif
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  analogReadResolution(ADC_RESOLUTION);
}

static int32_t readVref()
{
#ifdef __LL_ADC_CALC_VREFANALOG_VOLTAGE
  return (__LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION));
#else
  return (VREFINT * ADC_RANGE / analogRead(AVREF)); // ADC sample to mV
#endif
}

#ifdef ATEMP
static int32_t readTempSensor(int32_t VRef)
{
#ifdef __LL_ADC_CALC_TEMPERATURE
  return (__LL_ADC_CALC_TEMPERATURE(VRef, analogRead(ATEMP), LL_ADC_RESOLUTION));
#elif defined(__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS)
  return (__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, V25, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION));
#else
  return 0;
#endif
}
#endif

static int32_t readVoltage(int32_t VRef, uint32_t pin)
{
  return (__LL_ADC_CALC_DATA_TO_VOLTAGE(VRef, analogRead(pin), LL_ADC_RESOLUTION));
}

// the loop routine runs over and over again forever:
void loop() {
  // print out the value you read:
  Serial.print("VRef(mv)= ");
  int32_t VRef = readVref();
  Serial.print(VRef);

#ifdef ATEMP
  Serial.print("\tTemp(°C)= ");
  Serial.print(readTempSensor(VRef));
#endif
#ifdef AVBAT
  Serial.print("\tVbat(mv)= ");
  Serial.print(readVoltage(VRef, AVBAT));
#endif

  Serial.print("\tA0(mv)= ");
  Serial.println(readVoltage(VRef, A0));
  delay(200);
}

fpistm added 3 commits June 7, 2019 18:17
Signed-off-by: Frederic.Pillon <[email protected]>
ADC_SAMPLINGTIME and ADC_CLOCK_DIV could be redefined by
the variant or using build_opt.h.

Signed-off-by: Frederic.Pillon <[email protected]>
Signed-off-by: Frederic.Pillon <[email protected]>
@fpistm fpistm self-assigned this Jun 10, 2019
@fpistm fpistm added enhancement New feature or request fix 🩹 Bug fix labels Jun 10, 2019
@fpistm fpistm added this to the 1.6.0 milestone Jun 10, 2019
fpistm added 2 commits June 11, 2019 09:27
Internal channels use is enabling ADC "internal path"
which needs to be disabled after measurement

Signed-off-by: Frederic Pillon <[email protected]>
@fpistm fpistm force-pushed the ADC_Internal_Channel branch from e9de3ec to ef20dc8 Compare June 11, 2019 07:30
@fpistm fpistm merged commit df4a54a into stm32duino:master Jun 11, 2019
@fpistm fpistm deleted the ADC_Internal_Channel branch June 11, 2019 08:22
@ppescher
Copy link
Contributor

Thanks for this @fpistm !

Just a minor comment on the example code... isn't VBAT internally scaled down before it is fed to the ADC? I know there is a 3x divider in the STM32L43x/L45x etc. not sure about the other families.

@fpistm
Copy link
Member Author

fpistm commented Jun 11, 2019

Welcome @ppescher
Maybe user have to adjust the example based on datasheet.
I tried to do a generic example but this could not warranty for all mcu 🤣
Thanks also for your example in the #474, as you can see I do not use the PeripheralPins as they not rely on a pin.
I've also allow some config redefinition as suggested in your commits (ADC_CLOCK_CYCLE, ADC_SAMPLINGTIME,...)

@AnHardt
Copy link
Contributor

AnHardt commented Dec 6, 2019

#ifdef AVBAT
  Serial.print("\tVbat(mv)= ");
  Serial.print(readVoltage(VRef, AVBAT));
#endif

should be

 Serial.print(2 * readVoltage(VRef, AVBAT));

MedadRufus added a commit to MedadRufus/ICT-v1-platformio that referenced this pull request Jun 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fix 🩹 Bug fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add internal ADC channels (REF, TEMP, BAT)
3 participants