#キャリブレーションとは
理想的な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になるようにします。
コードを以下のように入力します。
/* 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();
このキャリブレーションは電源投入時に毎回行うのが望ましいですが、一度測定して、その値を使いまわしても構いません。
各ボードおよびSTM32に依存しますので、ボードごとに行ったほうがいいでしょう。
いくつかのSTM32シリーズにはオートキャリブレーションというレジスタに1bit立てるだけで、この機能を行うものもあります。STM32F401にはその機能がないので、自分で行う必要があります。
ソースコードはGitHubに置きました。
https://github.com/kotetsuy/STM32forWindowsDemos/tree/master/ADCCalibration