8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ADCのキャリブレーション

Posted at

#キャリブレーションとは

理想的なADCはGNDを入力したときに0、Vddを入力したときに最大値になります。しかし、実際のADCには誤差があります。
0にならない誤差をオフセット誤差、最大値にならない誤差をゲイン誤差といいます。
詳細は以下のホームページをご覧ください。
https://ednjapan.com/edn/articles/1810/02/news018_4.html

これを補正するには、GNDを接続したときのADC値と、Vddを接続したときのADC値を保存して、そこが0VとVddになるように、一次関数で修正するようにします。

校正後電圧 = \frac{Vdd*(ADC値 - GNDを接続したときのADC値)}{Vddを接続したときのADC値-GNDを接続したときのADC値}

#Nulceo-F401REでの実例

Nucleo-F401を使って実際にやってみます。

STM32CubeIDEで、PA0をGND、PA1をVdd、PA4を可変抵抗器の出力につなぎます。可変抵抗器の両端はVddとGNDにつないで、出力範囲が0から3.3Vになるようにします。
image.png
image.png

コードを以下のように入力します。

/* USER CODE BEGIN 0 */
uint32_t OffsetAcc = 0;
uint32_t GainAcc = 0;
uint32_t ADCValue;
float V;
/* USER CODE END 0 */
  /* USER CODE BEGIN 1 */
	ADC_ChannelConfTypeDef sConfig = {0};
  /* USER CODE END 1 */
  /* USER CODE BEGIN 2 */

  // Get Offset Accuracy
  // GND connect with ADC_IN0
  // Init sConfig for ADC_IN0 is in MX_ADC1_Init
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1,1000);
  OffsetAcc = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  hadc1.Instance->SQR1 = 0;

  // Get Gain Accuracy
  // Vdd connect with ADC_IN1
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1,1000);
  GainAcc = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  hadc1.Instance->SQR1 = 0;

  // Get ADC and convert to calibrated value
  // I connect the ADC port with ADC_IN4
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

  /* USER CODE END 2 */
    /* USER CODE BEGIN 3 */
	  // Get ADC Value
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1,1000);
	  ADCValue = HAL_ADC_GetValue(&hadc1);
	  HAL_ADC_Stop(&hadc1);

	  // Get calibrated Voltage
	  V = 3.3F*((float)ADCValue - (float)OffsetAcc)/((float)GainAcc - (float)OffsetAcc);
	  __NOP();

__NOP()にbreakpointを設定します。
image.png

関係する変数をExpressionに表示します。
image.png

実行すると以下のようになります。
image.png

このキャリブレーションは電源投入時に毎回行うのが望ましいですが、一度測定して、その値を使いまわしても構いません。
各ボードおよびSTM32に依存しますので、ボードごとに行ったほうがいいでしょう。

いくつかのSTM32シリーズにはオートキャリブレーションというレジスタに1bit立てるだけで、この機能を行うものもあります。STM32F401にはその機能がないので、自分で行う必要があります。

ソースコードはGitHubに置きました。
https://github.com/kotetsuy/STM32forWindowsDemos/tree/master/ADCCalibration

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?