1. 개요
본 문의 목적은 ADS124S08 고해상도 24-bit ΔΣ ADC와 STM32L432KC MCU를 기반으로 압력 센서의 출력 특성을 정확히 보정하는 데 있다. 압력 센서는 온도 변화에 따른 게인 및 오프셋 드리프트 현상을 나타내며, 이는 측정 정확도를 저하시킨다. 이를 해결하기 위해 본 문서에서는 ADS124S08 내장 온도 센서를 활용하여 추가 하드웨어 없이 온도를 동시에 측정하고, 정규화(Normalization) 및 다항식 모델링을 적용하여 온도 보정을 수행한다.
정규화 과정은 원시 ADC 데이터(\( V_{\text{raw}}, T_{\text{raw}} \))를 \([0, 1]\) 범위로 변환함으로써 수치적 안정성을 확보하고, Levenberg-Marquardt (LM) 알고리즘 기반의 계수 피팅 과정에서 효율적인 수렴을 가능하게 한다. 또한, STM32L432KC의 32-bit 부동소수점 연산 환경에서 계산 오차를 최소화하는 효과가 있다.
보정 모델은 2차 및 3차 다항식으로 제안되며, 2차 모델은 ±0.2~0.5% FSO 수준의 정확도를 제공하여 저전력·실시간 응용에 적합하고, 3차 모델은 ±0.1% FSO의 정밀도를 확보하여 고정밀 계측 응용에 적합하다. 본 문서에서는 -40°C ~ 125°C, 0 ~ 100 kPa 범위에서 15포인트(5 압력 × 3 온도) 데이터를 수집하고, 이를 기반으로 보정 계수를 도출하였다.
Keywords: Pressure Sensor (압력 센서), High-Resolution Measurement (고해상도 측정), Temperature Compensation (온도 보상), Polynomial Calibration (다항식 보정), Normalization (정규화), ADS124S08, STM32L432KC, Sensor Calibration Algorithm (센서 보정 알고리즘), Low-Power Embedded System (저전력 임베디드 시스템), High-Precision Measurement (고정밀 측정)
2. 데이터 정규화
입력 데이터(\( V_{\text{raw}}, T_{\text{raw}} \))는 24-bit ADC 값(0~16777215)으로, 큰 스케일로 인해 다항식 계산에서 수치적 오차 가능성이 있습니다. Min-Max 정규화를 적용하여 [0, 1] 범위로 변환:
\[ V_{\text{norm}} = \frac{V_{\text{raw}} - V_{\text{min}}}{V_{\text{max}} - V_{\text{min}}} \]
\[ T_{\text{norm}} = \frac{T_{\text{raw}} - T_{\text{min}}}{T_{\text{max}} - T_{\text{min}}} \]
- \( V_{\text{min}}, V_{\text{max}} \): 압력 ADC 값의 최소/최대 (예: 838860, 6039797).
- \( T_{\text{min}}, T_{\text{max}} \): 온도 ADC 값의 최소/최대 (예: 1677722, 3355444).
- 출력(\( P_{\text{calibrated}}, T_{\text{calibrated}} \))은 물리 단위(kPa, °C) 유지.
정규화
- 수치적 안정성: \( V_{\text{raw}}^3 \approx 10^{21} \) 같은 큰 값은 부동소수점 오차 유발 가능. 정규화로 입력을 [0, 1]로 줄여 오차 감소.
- 피팅 안정성: LM 알고리즘의 수렴 속도와 안정성 향상.
- STM32L432KC: 32-bit float 연산에서 정밀도 개선.
3. 보정 모델
3.1. 온도 보정 (2차 다항식)
정규화된 온도 데이터(\( T_{\text{norm}} \))로 실제 온도(\( T_{\text{calibrated}} \)) 계산:
\[ T_{\text{calibrated}} = b_2 \cdot T_{\text{norm}}^2 + b_1 \cdot T_{\text{norm}} + b_0 \]
변수 설명
- \( T_{\text{norm}} \): 정규화된 온도 ADC 값 ([0, 1]).
- \( T_{\text{calibrated}} \): 보정된 온도 (°C).
- \( T_{\text{ref}} \): 기준 온도 (25°C).
- \( b_2, b_1, b_0 \): 계수 (정규화 후 스케일 조정).
ADS124S08 내장 온도 센서: 내부 다이오드 전압 변화, \( V_{\text{REF}} = 2.5V \), 24-bit ADC 출력. -40°C~125°C에서 약간의 비선형성(±0.5°C) 보상.
2차 다항식: 온도 센서의 비선형성은 2차로 충분히 모델링(±0.1°C 정확도).
정규화 효과: \( T_{\text{raw}} \approx 10^6 \) 대신 \( T_{\text{norm}} \in [0, 1] \)로, 계수 크기 균일화(예: \( b_2 \approx 10^2 \)).
예상 계수: \( b_2 \approx 10^2 \), \( b_1 \approx 10^2 \), \( b_0 \approx -40 \).
3.2. 압력 보정 (2차 및 3차 다항식)
정규화된 압력 데이터(\( V_{\text{norm}} \))와 보정된 온도(\( T \))로 압력(\( P_{\text{calibrated}} \)) 계산:
2차 다항식
\[ P_{\text{calibrated}} = a_2 \cdot V_{\text{norm}}^2 + a_1 \cdot V_{\text{norm}} + a_0 + [\text{Tcg}_2 \cdot (T - T_{\text{ref}})^2 + \text{Tcg}_1 \cdot (T - T_{\text{ref}})] \cdot V_{\text{norm}} + [\text{Tco}_2 \cdot (T - T_{\text{ref}})^2 + \text{Tco}_1 \cdot (T - T_{\text{ref}})] \]
3차 다항식
\[ P_{\text{calibrated}} = a_3 \cdot V_{\text{norm}}^3 + a_2 \cdot V_{\text{norm}}^2 + a_1 \cdot V_{\text{norm}} + a_0 + [\text{Tcg}_2 \cdot (T - T_{\text{ref}})^2 + \text{Tcg}_1 \cdot (T - T_{\text{ref}})] \cdot V_{\text{norm}} + [\text{Tco}_2 \cdot (T - T_{\text{ref}})^2 + \text{Tco}_1 \cdot (T - T_{\text{ref}})] \]
변수 설명
- \( V_{\text{norm}} \): 정규화된 압력 ADC 값 ([0, 1]).
- \( T \): 보정된 온도 (°C).
- \( T_{\text{ref}} \): 기준 온도 (25°C).
- \( P_{\text{calibrated}} \): 보정된 압력 (kPa).
- \( a_3, a_2, a_1, a_0 \): 다항식 계수 (3차: \( a_3 \) 포함).
- \( \text{Tcg}_2, \text{Tcg}_1 \): 게인 보상 계수.
- \( \text{Tco}_2, \text{Tco}_1 \): 오프셋 보상 계수.
정규화: \( V_{\text{norm}} \in [0, 1] \)로, \( V_{\text{norm}}^3 \approx 1 \)이 되어 수치적 오차 감소. 계수 크기 균일화(예: \( a_3 \approx 10^2 \)).
2차 vs. 3차:
- 2차: 0~100 kPa에서 ±0.2~0.5% FSO, 계산 단순, STM32L432KC 적합.
- 3차: 고압력 비선형성 정밀 보상(±0.1% FSO), 고정밀 응용.
예상 계수:
- 2차: \( a_2 \approx 10^2 \), \( a_1 \approx 10^2 \), \( a_0 \approx 0 \), \( \text{Tcg}_2, \text{Tcg}_1 \approx 10^{-1} \), \( \text{Tco}_2, \text{Tco}_1 \approx 10^0 \).
- 3차: \( a_3 \approx 10^2 \), \( a_2, a_1, a_0, \text{Tcg}, \text{Tco} \) 유사.
4. 온도 보상 절차
4.1. 준비 단계
- 하드웨어: ADS124S08 (24-bit, SPI, \( V_{\text{REF}} = 2.5V \)), STM32L432KC, Uncalibrated Pressure Sensor, 온도 챔버.
- 소프트웨어: Python (NumPy, SciPy), STM32CubeIDE (HAL).
- 인터페이스: SPI1 (PA4=CS, PA5=SCK, PA6=MISO, PA7=MOSI).
4.2. 캘리브레이션 데이터 수집
- 압력: 0, 25, 50, 75, 100 kPa.
- 온도: -40°C, 25°C, 125°C.
- ADS124S08 설정: Sinc3 필터, 20 SPS, PGA=1, 내부 2.5V 참조.
- 노이즈 처리: 100 샘플 평균화.
데이터 수집 코드 (STM32L432KC, ADS124S08):
#include "stm32l4xx_hal.h"
SPI_HandleTypeDef hspi1;
/* ADS124S08 레지스터 쓰기 */
void ads124s08_write_reg(uint8_t reg_addr, uint8_t data) {
uint8_t tx_data[3] = {0x40 | (reg_addr & 0x1F), 0x00, data};
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, tx_data, 3, HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
/* ADS124S08 레지스터 읽기 */
uint8_t ads124s08_read_reg(uint8_t reg_addr) {
uint8_t tx_data[3] = {0x20 | (reg_addr & 0x1F), 0x00, 0x00};
uint8_t rx_data[3];
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 3, HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
return rx_data[2];
}
/* ADS124S08 초기화 */
void ads124s08_init(void) {
uint8_t reset_cmd[1] = {0x06};
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, reset_cmd, 1, HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
HAL_Delay(1);
ads124s08_write_reg(0x02, 0x01); // INPMUX: AIN0/AIN1
ads124s08_write_reg(0x03, 0x00); // PGA: Gain=1
ads124s08_write_reg(0x04, 0x04); // DATARATE: 20 SPS, Sinc3
ads124s08_write_reg(0x05, 0x20); // REF: 내부 2.5V
ads124s08_write_reg(0x0A, 0x10); // SYS: 온도 센서 활성화
}
/* ADS124S08 데이터 읽기 */
uint32_t ads124s08_read_data(void) {
uint8_t tx_data[3] = {0x12, 0x00, 0x00};
uint8_t rx_data[3];
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 3, HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
return (rx_data[0] << 16) | (rx_data[1] << 8) | rx_data[2];
}
/* 압력 센서 데이터 수집 */
uint32_t read_pressure(void) {
ads124s08_write_reg(0x02, 0x01);
uint64_t sum = 0;
uint32_t samples = 100;
for (uint32_t i = 0; i < samples; i++) {
while (!(ads124s08_read_reg(0x00) & 0x80));
sum += ads124s08_read_data();
HAL_Delay(50);
}
return (uint32_t)(sum / samples);
}
/* 온도 센서 데이터 수집 */
uint32_t read_temperature(void) {
ads124s08_write_reg(0x02, 0xFF);
ads124s08_write_reg(0x0A, 0x10);
uint64_t sum = 0;
uint32_t samples = 100;
for (uint32_t i = 0; i < samples; i++) {
while (!(ads124s08_read_reg(0x00) & 0x80));
sum += ads124s08_read_data();
HAL_Delay(50);
}
return (uint32_t)(sum / samples);
}
예시 데이터:
import numpy as np
data = np.array([
[0, -40, 838860, 1677722, 0, -40],
[0, 25, 872415, 2516583, 0, 25],
[0, 125, 905969, 3355444, 0, 125],
[25, -40, 2097152, 1677722, 25, -40],
[25, 25, 2139095, 2516583, 25, 25],
[25, 125, 2181038, 3355444, 25, 125],
[50, -40, 3355443, 1677722, 50, -40],
[50, 25, 3439329, 2516583, 50, 25],
[50, 125, 3523215, 3355444, 50, 125],
[75, -40, 4613734, 1677722, 75, -40],
[75, 25, 4697620, 2516583, 75, 25],
[75, 125, 4781506, 3355444, 75, 125],
[100, -40, 5872025, 1677722, 100, -40],
[100, 25, 5955911, 2516583, 100, 25],
[100, 125, 6039797, 3355444, 100, 125]
])
V_raw = data[:, 2]
T_raw = data[:, 3]
P_ref = data[:, 4]
T_ref = data[:, 5]
# 정규화 파라미터
V_min, V_max = V_raw.min(), V_raw.max()
T_min, T_max = T_raw.min(), T_raw.max()
V_norm = (V_raw - V_min) / (V_max - V_min)
T_norm = (T_raw - T_min) / (T_max - T_min)
4.3. 온도 보정 계수 추출
공식: \( T_{\text{calibrated}} = b_2 \cdot T_{\text{norm}}^2 + b_1 \cdot T_{\text{norm}} + b_0 \).
방법: LM 알고리즘으로 \( T_{\text{norm}}, T_{\text{ref}} \) 피팅.
4.4. 압력 보정 계수 추출
공식: 2차/3차 다항식, \( V_{\text{norm}}, T_{\text{calibrated}} \).
방법: LM 알고리즘으로 피팅.
4.5. 계수 및 정규화 파라미터 MCU Flash 저장
#include "stm32l4xx_hal.h"
/* 정규화 파라미터 */
float norm_params[4] = {838860.0f, 6039797.0f, 1677722.0f, 3355444.0f}; // V_min, V_max, T_min, T_max
/* 계수 배열 */
float coeffs_2nd[7] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
float coeffs_3rd[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
/* Flash에 저장 */
void save_coefficients(uint32_t address, float* data, uint8_t size) {
HAL_FLASH_Unlock();
for (int i = 0; i < size; i++) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address + i*4, *(uint32_t*)&data[i]);
}
HAL_FLASH_Lock();
}
4.6. MCU 런타임 보정
#define T_REF 25.0f
/* 정규화 함수 */
float normalize(float x, float x_min, float x_max) {
return (x - x_min) / (x_max - x_min);
}
/* 온도 보정 */
float correct_temperature(uint32_t T_raw) {
float T_norm = normalize((float)T_raw, norm_params[2], norm_params[3]);
float b2 = 100.0f; // 예시 계수
float b1 = 165.0f;
float b0 = -40.0f;
return b2 * T_norm * T_norm + b1 * T_norm + b0;
}
/* 압력 보정: 2차 */
float correct_pressure_2nd(uint32_t V_raw, float T) {
float V_norm = normalize((float)V_raw, norm_params[0], norm_params[1]);
float a2 = coeffs_2nd[0];
float a1 = coeffs_2nd[1];
float a0 = coeffs_2nd[2];
float Tcg2 = coeffs_2nd[3];
float Tcg1 = coeffs_2nd[4];
float Tco2 = coeffs_2nd[5];
float Tco1 = coeffs_2nd[6];
float T_diff = T - T_REF;
return (a2 * V_norm * V_norm + a1 * V_norm + a0 +
(Tcg2 * T_diff * T_diff + Tcg1 * T_diff) * V_norm +
(Tco2 * T_diff * T_diff + Tco1 * T_diff));
}
/* 압력 보정: 3차 */
float correct_pressure_3rd(uint32_t V_raw, float T) {
float V_norm = normalize((float)V_raw, norm_params[0], norm_params[1]);
float a3 = coeffs_3rd[0];
float a2 = coeffs_3rd[1];
float a1 = coeffs_3rd[2];
float a0 = coeffs_3rd[3];
float Tcg2 = coeffs_3rd[4];
float Tcg1 = coeffs_3rd[5];
float Tco2 = coeffs_3rd[6];
float Tco1 = coeffs_3rd[7];
float T_diff = T - T_REF;
return (a3 * V_norm * V_norm * V_norm + a2 * V_norm * V_norm + a1 * V_norm + a0 +
(Tcg2 * T_diff * T_diff + Tcg1 * T_diff) * V_norm +
(Tco2 * T_diff * T_diff + Tco1 * T_diff));
}
4.7. 검증
기준: 온도 ±0.1°C, 압력 2차(±0.2~0.5 kPa), 3차(±0.1 kPa).
4.8. 노이즈 관리
Sinc3 필터, 100 샘플 평균화, IIR 필터 (alpha=0.05).
float iir_filter(float new_sample, float prev_output, float alpha) {
return alpha * new_sample + (1.0f - alpha) * prev_output;
}
5. 보정 계수 추출 파이썬 구현 코드
15포인트 데이터를 사용하여 온도 보정(2차)과 압력 보정(2차/3차)을 수행하고, 보상 전/후 검증
# 필요한 라이브러리 임포트
import numpy as np # 배열 연산 및 수치 계산을 위한 라이브러리
from scipy.optimize import curve_fit # LM 알고리즘을 사용한 계수 피팅
import matplotlib.pyplot as plt # 그래프 생성을 위한 라이브러리
# 캘리브레이션 데이터: [P_ref, T_ref, V_raw, T_raw, P_ref, T_ref]
# 열: 참조 압력(kPa), 참조 온도(°C), 원시 압력 ADC, 원시 온도 ADC, 참조 압력, 참조 온도
data = np.array([
[0, -40, 838860, 1677722, 0, -40],
[0, 25, 872415, 2516583, 0, 25],
[0, 125, 905969, 3355444, 0, 125],
[25, -40, 2097152, 1677722, 25, -40],
[25, 25, 2139095, 2516583, 25, 25],
[25, 125, 2181038, 3355444, 25, 125],
[50, -40, 3355443, 1677722, 50, -40],
[50, 25, 3439329, 2516583, 50, 25],
[50, 125, 3523215, 3355444, 50, 125],
[75, -40, 4613734, 1677722, 75, -40],
[75, 25, 4697620, 2516583, 75, 25],
[75, 125, 4781506, 3355444, 75, 125],
[100, -40, 5872025, 1677722, 100, -40],
[100, 25, 5955911, 2516583, 100, 25],
[100, 125, 6039797, 3355444, 100, 125]
])
# 데이터에서 필요한 열 추출
V_raw = data[:, 2] # 원시 압력 ADC 값
T_raw = data[:, 3] # 원시 온도 ADC 값
P_ref = data[:, 4] # 참조 압력 (kPa)
T_ref = data[:, 5] # 참조 온도 (°C)
# Min-Max 정규화: ADC 값을 [0, 1] 범위로 변환
V_min, V_max = V_raw.min(), V_raw.max() # 압력 ADC 최소/최대
T_min, T_max = T_raw.min(), T_raw.max() # 온도 ADC 최소/최대
V_norm = (V_raw - V_min) / (V_max - V_min) # 정규화된 압력 데이터
T_norm = (T_raw - T_min) / (T_max - T_min) # 정규화된 온도 데이터
# 기준 온도 상수 정의
T_REF = 25.0 # 기준 온도 (°C)
# 온도 보정 함수: 2차 다항식
# 입력: T_norm (정규화된 온도), 출력: T_calibrated (°C)
def temp_correction(T_norm, b2, b1, b0):
return b2 * T_norm**2 + b1 * T_norm + b0
# 압력 보정 함수: 2차 다항식
# 입력: (V_norm, T), 출력: P_calibrated (kPa)
def sensor_correction_2nd(x, a2, a1, a0, Tcg2, Tcg1, Tco2, Tco1):
V_norm, T = x # 정규화된 압력과 보정된 온도
T_diff = T - T_REF # 기준 온도와의 차이
return (a2 * V_norm**2 + a1 * V_norm + a0 +
(Tcg2 * T_diff**2 + Tcg1 * T_diff) * V_norm +
(Tco2 * T_diff**2 + Tco1 * T_diff))
# 압력 보정 함수: 3차 다항식
# 입력: (V_norm, T), 출력: P_calibrated (kPa)
def sensor_correction_3rd(x, a3, a2, a1, a0, Tcg2, Tcg1, Tco2, Tco1):
V_norm, T = x # 정규화된 압력과 보정된 온도
T_diff = T - T_REF # 기준 온도와의 차이
return (a3 * V_norm**3 + a2 * V_norm**2 + a1 * V_norm + a0 +
(Tcg2 * T_diff**2 + Tcg1 * T_diff) * V_norm +
(Tco2 * T_diff**2 + Tco1 * T_diff))
# 온도 계수 피팅: LM 알고리즘으로 2차 다항식 계수 추출
popt_T, _ = curve_fit(temp_correction, T_norm, T_ref, p0=[0, 100, -40], method='lm')
b2, b1, b0 = popt_T # 추출된 계수: b2, b1, b0
print("Temperature Coefficients (Normalized):")
print(f"b2: {b2:.6e}, b1: {b1:.6e}, b0: {b0:.6e}")
# 압력 계수 피팅: 2차 및 3차 다항식 계수 추출
popt_S2, _ = curve_fit(sensor_correction_2nd, (V_norm, T_ref), P_ref, p0=[0, 100, 0, 0, 0, 0, 0], method='lm')
popt_S3, _ = curve_fit(sensor_correction_3rd, (V_norm, T_ref), P_ref, p0=[0, 0, 100, 0, 0, 0, 0, 0], method='lm')
print("\n2nd Order Pressure Coefficients:", popt_S2)
print("3rd Order Pressure Coefficients:", popt_S3)
# 보정 결과 계산
T_pred = temp_correction(T_norm, *popt_T) # 보정된 온도
P_pred_2nd = sensor_correction_2nd((V_norm, T_pred), *popt_S2) # 2차 보정 압력
P_pred_3rd = sensor_correction_3rd((V_norm, T_pred), *popt_S3) # 3차 보정 압력
# 보정 오차 출력
print("\nCalibration Errors:")
print("Temperature Error (°C):", np.abs(T_pred - T_ref))
print("2nd Order Pressure Error (kPa):", np.abs(P_pred_2nd - P_ref))
print("3rd Order Pressure Error (kPa):", np.abs(P_pred_3rd - P_ref))
# 원시 데이터 스케일링: 그래프를 위해 물리 단위로 변환
V_raw_scaled = (V_raw - V_min) / (V_max - V_min) * 100 # 0~100 kPa로 스케일링
T_raw_scaled = (T_raw - T_min) / (T_max - T_min) * 165 - 40 # -40~125°C로 스케일링
# 데이터 정렬: 그래프 가독성을 위해 T_ref와 P_ref 오름차순 정렬
sort_idx = np.argsort(T_ref) # T_ref 기준 정렬 인덱스
T_ref_sorted = T_ref[sort_idx]
T_raw_scaled_sorted = T_raw_scaled[sort_idx]
T_pred_sorted = T_pred[sort_idx]
# 온도 보상 그래프 생성
plt.figure(figsize=(10, 6)) # 그래프 크기 설정 (10x6 인치)
plt.scatter(T_ref_sorted, T_raw_scaled_sorted, label='Raw Temperature (Scaled)', color='red', marker='x')
plt.scatter(T_ref_sorted, T_pred_sorted, label='Calibrated Temperature', color='blue', marker='o')
plt.plot(T_ref_sorted, T_ref_sorted, label='Reference Temperature', color='green', linestyle='--')
plt.xlabel('Reference Temperature (°C)') # X축 라벨
plt.ylabel('Temperature (°C)') # Y축 라벨
plt.title('Temperature Compensation') # 그래프 제목
plt.legend() # 범례 표시
plt.grid(True) # 그리드 추가
plt.savefig('temperature_compensation.png') # PNG 파일로 저장
plt.close() # 메모리 정리
# 압력 보상 그래프 생성
plt.figure(figsize=(10, 6)) # 그래프 크기 설정
colors = {-40: 'blue', 25: 'green', 125: 'red'} # 온도별 색상 정의
for temp in [-40, 25, 125]:
idx = np.where(T_ref == temp)[0] # 특정 온도에 해당하는 인덱스
# P_ref 기준으로 정렬
sort_idx = np.argsort(P_ref[idx])
P_ref_sorted = P_ref[idx][sort_idx]
V_raw_scaled_temp = V_raw_scaled[idx][sort_idx]
P_pred_2nd_temp = P_pred_2nd[idx][sort_idx]
P_pred_3rd_temp = P_pred_3rd[idx][sort_idx]
plt.scatter(P_ref_sorted, V_raw_scaled_temp, label=f'Raw Pressure (T={temp}°C, Scaled)', marker='x', color=colors[temp])
plt.scatter(P_ref_sorted, P_pred_2nd_temp, label=f'2nd Order Calibrated (T={temp}°C)', marker='o', color=colors[temp], alpha=0.6)
plt.scatter(P_ref_sorted, P_pred_3rd_temp, label=f'3rd Order Calibrated (T={temp}°C)', marker='^', color=colors[temp], alpha=0.3)
plt.plot(P_ref, P_ref, label='Reference Pressure', color='black', linestyle='--') # 참조 압력 기준선
plt.xlabel('Reference Pressure (kPa)') # X축 라벨
plt.ylabel('Pressure (kPa)') # Y축 라벨
plt.title('Pressure Compensation (2nd vs. 3rd Order)') # 그래프 제목
plt.legend() # 범례 표시
plt.grid(True) # 그리드 추가
plt.savefig('pressure_compensation.png') # PNG 파일로 저장
plt.close() # 메모리 정리
그래프 설명:
- Temperature Compensation:
- X축: Reference Temperature (°C) (-40, 25, 125°C).
- Y축: Temperature (°C).
- 데이터: Raw Temperature (scaled), Calibrated Temperature, Reference Temperature.
- 목적: 보정 후 \( T_{\text{calibrated}} \)가 \( T_{\text{ref}} \)와 일치하는지 확인.
- Pressure Compensation :
- X축: Reference Pressure (kPa) (0, 25, 50, 75, 100 kPa).
- Y축: Pressure (kPa).
- 데이터: Raw Pressure (scaled), Calibrated Pressure (2nd/3rd order), Reference Pressure.
- 색상: -40°C (blue), 25°C (green), 125°C (red).
- 목적: 2차/3차 다항식의 보정 정확도 비교, 온도별 드리프트 확인.
6. 결론
본 문서에서는 ADS124S08 내장 온도 센서와 STM32L432KC MCU를 이용하여 압력 센서의 온도 보상 방법을 제안하였다. 정규화를 통해 대규모 ADC 원시 데이터를 안정적으로 처리하였으며, LM 알고리즘 기반 계수 추출로 보정 모델을 구축하였다.
- 정규화 효과: 입력 데이터를 [0, 1] 범위로 변환하여 수치적 안정성과 피팅 효율성을 크게 향상시켰다.
- 온도 보상 성능: 2차 다항식 모델만으로도 ±0.1°C 수준의 보정이 가능하였다.
- 압력 보상 성능:
- 2차 다항식 모델은 ±0.2~0.5% FSO 수준의 정확도를 제공하여 저전력 및 일반 산업용 응용에 적합하였다.
- 3차 다항식 모델은 ±0.1% FSO 이하의 정확도를 달성하여 정밀 계측 및 고신뢰성 응용에 적합함을 확인하였다.
- 구현 용이성: STM32L432KC의 연산 능력으로 실시간 보정이 가능하며, Flash에 정규화 파라미터 및 계수를 저장하여 임베디드 환경에서도 안정적인 동작이 가능하다.
따라서 제안된 방법은 저전력·고정밀 압력 계측 시스템에 효과적으로 적용할 수 있으며, 향후에는 더 많은 캘리브레이션 포인트 확장, 비선형 머신러닝 모델 적용, 온도 히스테리시스 보상 등을 통해 성능을 한층 개선할 수 있을 것이다.
Keywords: Pressure Sensor (압력 센서), High-Resolution Measurement (고해상도 측정), Temperature Compensation (온도 보상), Polynomial Calibration (다항식 보정), Normalization (정규화), ADS124S08, STM32L432KC, Sensor Calibration Algorithm (센서 보정 알고리즘), Low-Power Embedded System (저전력 임베디드 시스템), High-Precision Measurement (고정밀 측정)
'Sensor > 압력센서(Pressure)' 카테고리의 다른 글
다항식 모델에 비선형 항과 온도센서 보정을 고려한 MEMS 압력 센서의 온도 보상 방법 (0) | 2025.08.31 |
---|---|
Wheatstone 브릿지 기반 MEMS 압력 센서의 온도 의존성 보정 방법 (0) | 2025.08.31 |