[Haptics - Haptuator Single Frequency] Calibration Using NI DAQ and Python

2025. 2. 24. 19:00·HCI/Haptics
728x90
반응형

1. 실험 개요

진동자를 활용한 가속도 측정에서는 신호의 정확한 보정이 필수적입니다. 본 실험에서는 Single Frequency Calibration을 수행하여, 특정 주파수에서 입력 전압과 출력 가속도 값의 관계를 정의하고 이를 보정하는 과정을 기록합니다. 이를 통해 측정 장비가 올바른 값을 출력하도록 교정할 수 있습니다.


2. 사용 장비 및 구성

  • DAQ (Data Acquisition Device): NI DAQ 장치
  • 가속도계: ADXL354/355
  • 진동자: HapCoil One HC121238O
  • 소프트웨어: Python (DAQ 제어 및 데이터 로깅), MATLAB (데이터 분석 및 FFT 수행)
  • 기본 설정:
    • 아날로그 인풋(AI) 0, 1, 2번 채널 사용
    • 아날로그 아웃풋(AO) 0번 채널 사용
    • 샘플링 속도 및 전압 범위 설정

+ 🔍 참고해야 할 데이터 시트

  1. HapCoil One HC121238O 데이터 시트 → 진동자의 입력 전압(V-pp)과 가속도(g-pp) 관계 확인
  2. ADXL354-Cz데이터 시트 → 가속도 센서의 측정 범위, 민감도 및 포화(Saturation) 여부 확인
    1. 8g 모델이 우리가 사용하는 C가속도계여서 100mv -> 1g 가 나온다. 즉, 0.1 V -> 1g 임


  3. DAQ 장치 데이터 시트 (NI DAQ) → 아날로그 출력(AO)의 전압 범위 확인 (일반적으로 ±10V)

실제 장치 셋업 모습 입니다.

가속도계 + 햅추에이터 가속도계 전원부 정류 회로 (3.3V) DAQ 연결
햅추에이터의 X축 방향에 평행하게 가속도계를 둡니다. 납땜해서 만듭니다. 1번, 4번, 7번에 순차적으로 X, Y, Z 축 연결해줍니다.
아날로그 인풋(AI) 0, 1, 2번 채널로 연결됨

 


3. 실험 단계

Step 0: 4G값까지의 V 값 확인하기

우리는 4G까지 출력을 할거라, 이에 맞는 V값을 확인후 최대 V를 찾아서 그 이하로만 구해야함

근데 코드 유실 이슈로 나중에 작성...

 

Step 1: 신호 출력 및 측정 설정

먼저, DAQ에서 100Hz 사인파 신호를 생성하여 진동자로 출력하고, 가속도계를 통해 응답을 측정합니다.

  1. Python 코드를 사용하여 100Hz의 사인파 신호를 생성하고 출력.
  2. 가속도계가 측정하는 데이터를 DAQ의 아날로그 인풋으로 수집.
  3. 측정된 데이터의 변위를 시각적으로 확인하여 정상적으로 동작하는지 확인.

Step 2: 출력 데이터 검증

출력된 진동이 제대로 측정되고 있는지 확인하기 위해 가속도 데이터를 분석합니다.

  1. **FFT(푸리에 변환)**를 사용하여 특정 주파수에서의 응답 확인.
  2. 가속도 값과 입력 전압 비교하여 비례 관계 분석.
  3. 만약 예상과 다른 결과가 나온다면 측정 장치의 포화(Saturation) 여부 확인.

Step 3: Calibration Factor 결정

측정된 가속도 값과 입력 전압 사이의 관계를 분석하여 보정 계수를 결정합니다.

  • 100Hz에서 입력 전압(V)과 출력 가속도(g)의 비율을 분석.
  • 예를 들어, 0.5V를 입력했을 때 4g가 측정되었다면, 1g를 얻기 위해 필요한 입력 전압을 조정.
  • Calibration Factor = 입력 전압 / 측정된 출력 가속도

이를 통해 원하는 가속도를 얻기 위해 입력 전압을 보정할 수 있습니다.

Step 4: 보정된 신호 출력 및 검증

보정 계수를 적용하여 다시 신호를 출력하고, 실제 가속도값이 원하는 값과 일치하는지 검증합니다.

  1. 보정된 입력 전압을 적용하여 진동자에 신호 출력.
  2. 다시 측정하여 FFT를 통해 원하는 주파수에서 올바른 응답이 나오는지 확인.
  3. 여러 번 반복 측정하여 평균값을 산출하고, Calibration Factor의 신뢰도를 검증.

 

Code

## Variable Definition
samplingRate = 10000
duration = 1
ReadCh = 3
now = datetime.datetime.now()

 

여기서 출력을 위해서 다음의  식을 정의해줍니다. 

`adjustment` 값이 우리가 찾아야할 보정계수입니다.

 

sig = np.zeros((1, samplingRate))  
Frequency = 100  # 100Hz 신호
Voltage = 0.2  # 입력 전압 값
# adjustment = (0.5 / 0.4)  # 보정 계수 (Calibration Factor)
adjustment = 1 # 보정 안된 버전-> 우리가 구해야하는 값
for i in range(samplingRate):
    sig[0][i] = adjustment * Voltage * np.sin(Frequency * 2 * np.pi * i / samplingRate)  # 100Hz 사인파 생성

# 마지막 값 0으로 설정
sig[0][samplingRate-1] = 0

 

생성된 파형

 

 

다음으로 이 시그널을 바탕으로 실제 가속도계로 측정한 결과, 우리는 100Hz에서 0.2 Voltage 를 주었을때 다음과 같은 파형을 얻었습니다.

x y z

 

 

그럼 이제 이거를 10번 해줘서 평균을 구해줍니다.

for i in range(10):

    readtask = nidaqmx.Task()
    writetask = nidaqmx.Task()

    readtask.ai_channels.add_ai_voltage_chan("Dev1/ai0:2", terminal_config=nidaqmx.constants.TerminalConfiguration.RSE, min_val=-10, max_val=10)
    readtask.timing.cfg_samp_clk_timing(samplingRate, sample_mode=nidaqmx.constants.AcquisitionType.FINITE, samps_per_chan=samplingRate * duration)
    writetask.ao_channels.add_ao_voltage_chan("Dev1/ao0")
    writetask.timing.cfg_samp_clk_timing(samplingRate, sample_mode=nidaqmx.constants.AcquisitionType.FINITE, samps_per_chan=samplingRate * duration)

    writetask.write(sig[0])
    writetask.start()

    data = readtask.read(samplingRate * duration)

    writetask.wait_until_done()
    writetask.close()
    readtask.close()


    f = open("Accels_"+str(i)+".txt" , "a")
    for j in range(samplingRate * duration):
        f.write(f"{data[0][j]}\n") ## X 데이터만 저장장
    f.close()


    time.sleep(2)

 

 

그러면 다음과 같이 데이터들이 저장됩니다. 이제 이 데이터를 평균내서 변위를 살펴볼 것입니다.

 

num_measurements = 10  # 반복 횟수
frequency = 100  # Hz
target_length = frequency * 1000  # 목표 샘플 길이

all_measurements = []

for i in range(num_measurements):
    data = np.loadtxt(f"Accels_{i}.txt", delimiter=",")  # 데이터 파일 불러오기
    
    # 데이터 길이 조정 (Zero Padding 또는 Truncation)
    if len(data) > target_length:
        data = data[:target_length]  # 길이가 길 경우 자름
    # else:
    #     padded_data = np.pad(data, (0, target_length - len(data)), 'constant', constant_values=0)
    
    all_measurements.append(data)

# NumPy 배열 변환 후 평균 계산
all_measurements = np.array(all_measurements)
average_data = np.mean(all_measurements, axis=0)

plt.figure(figsize=(10, 5))
plt.plot(average_data, label="Mean Acceleration")
plt.xlabel("Samples")
plt.ylabel("Acceleration (g)")
plt.legend()
plt.grid()
plt.title(f"Mean Acceleration Data ({frequency}Hz, {target_length} samples)")
plt.show()

y축 amplitude

 

앞서 측정한 평균 가속도 값이 0.9G, 최대 가속도 값이 1G이므로, 진폭(Amplitude)은 약 0.1G입니다.


1️⃣ 이론적으로 기대되는 값 vs 실제 측정값

ADXL354-CZ의 감도는 `100 mV/g(=0.1V/g)`입니다.
따라서 0.2V 입력 시 2G가 나와야 하지만, 실제 측정된 값은 1G였습니다.

💡 여기서 "왜 10이 곱해지는지?"에 대한 의문이 있을 수 있습니다.
이는 전압(V) → 가속도(G) 변환 과정에서 감도(Sensitivity)의 역수를 적용한 결과입니다.

  • 감도(Sensitivity) = 100 mV/g (= 0.1 V/g)
  • 즉, 가속도(G) = 전압(V) ÷ 0.1V/g
  • 0.2V ÷ 0.1V/g = 2G (이론값)
  • 하지만 실제 측정값은 1G → 손실 발생

⚠ 즉, 이론적으로 2G가 나와야 하는데, 실제로는 1G만 나왔으므로, 신호 크기가 절반으로 감소한 상태입니다.


2️⃣ 신호 크기가 절반으로 감소한 이유

이러한 차이는 측정 과정에서 발생하는 여러 가지 손실 요인 때문일 수 있습니다.

  1. 진동자의 응답 특성
    • 진동자가 입력한 전압(0.2V)을 완벽하게 2G로 변환하지 못했을 가능성이 있음.
  2. DAQ 장치의 설정 문제
    • 샘플링 속도, 필터링 영향 등으로 인해 실제 출력 신호가 예상보다 작게 측정되었을 가능성이 있음.
  3. 센서 감도의 변화
    • ADXL354-CZ의 감도(100 mV/g)가 온도나 환경 변화로 인해 오차가 생겼을 가능성이 있음.

이러한 이유로 보정 계수(adjustment)를 적용하여 신호 크기를 조정할 필요가 있습니다.


3️⃣ 보정 계수(adjustment) 값 결정

우리는 FFT 분석 결과를 함께 참고하여 보정 계수를 결정해야 합니다.
👉 FFT 이미지에서 100Hz 피크 값이 얼마나 나왔는지 확인해보겠습니다.

🔍 아래 FFT 이미지 분석:

  • x축(주파수)에서 100Hz에서 뚜렷한 피크가 보입니다.


4️⃣ 결론: adjustment 값 조정

✅ 보정 계수(adjustment) 설정 방법:

adjustment = 2 # 측정된 값과 이론값을 맞추기 위한 보정 계수
 

이 값을 적용하면 출력 신호의 크기가 2배 증가하여 이론값과 맞아지게 됩니다.
즉, 보정을 통해 측정된 가속도 데이터가 원래 의도한 사인파처럼 나오도록 조정됩니다. 


✅ 최종 정리

  1. 이론적으로 0.2V 입력 → 2G 출력이 되어야 하지만, 실제 측정값은 1G
    • 감도(Sensitivity) = 100 mV/g (= 0.1 V/g)
    • 즉, 가속도(G) = 전압(V) ÷ 0.1V/g
    • 0.2V ÷ 0.1V/g = 2G (이론값)
    • 하지만 실제 측정값은 1G → 손실 발생
  2. 보정 계수 adjustment = 2 적용 → 이론값과 실제 측정값 일치하도록 조정
  3. 이제 다시 보정된 신호를 측정하여 FFT를 확인하고 최종 결과를 검증해야 함

 

 

 

아래는 주피터노트북 코드입니다.

DAQ_calibration.ipynb
0.97MB


+ ) HighPassfilter 를 10Hz 주파수에서 해야하는데, 적용이 안되어있습니다. 다른 분들은 DC성분 제거를 위해 해당 부분을 하고 캘리브레이션하시길 바랍니다

728x90
반응형

'HCI > Haptics' 카테고리의 다른 글

[Haptics] .wav 파일을 DAQ 에서 실행하기 / Python 파이썬  (0) 2025.02.25
[Haptics - Dynamic compensation] Calibration Using NI DAQ, Python and Matlab  (0) 2025.02.25
[Haptics - Dynamic compensation] Matlab에서 Chirp Signal 출력하기  (1) 2025.02.25
[Haptics] 진동 측정 캘리브레이션 이론 정리  (0) 2025.02.18
[Haptics] Macaron 햅틱 디자인 툴  (0) 2025.02.17
'HCI/Haptics' 카테고리의 다른 글
  • [Haptics - Dynamic compensation] Calibration Using NI DAQ, Python and Matlab
  • [Haptics - Dynamic compensation] Matlab에서 Chirp Signal 출력하기
  • [Haptics] 진동 측정 캘리브레이션 이론 정리
  • [Haptics] Macaron 햅틱 디자인 툴
sillon
sillon
꾸준해지려고 합니다..
    반응형
  • sillon
    sillon coding
    sillon
  • 전체
    오늘
    어제
    • menu (614)
      • notice (2)
      • python (68)
        • 자료구조 & 알고리즘 (23)
        • 라이브러리 (19)
        • 기초 (8)
        • 자동화 (14)
        • 보안 (1)
      • coding test - python (301)
        • Programmers (166)
        • 백준 (76)
        • Code Tree (22)
        • 기본기 문제 (37)
      • coding test - C++ (5)
        • Programmers (4)
        • 백준 (1)
        • 기본기문제 (0)
      • 공부정리 (5)
        • 신호처리 시스템 (0)
        • Deep learnig & Machine lear.. (41)
        • Data Science (18)
        • Computer Vision (17)
        • NLP (40)
        • Dacon (2)
        • 모두를 위한 딥러닝 (강의 정리) (4)
        • 모두의 딥러닝 (교재 정리) (9)
        • 통계 (2)
      • HCI (23)
        • Haptics (7)
        • Graphics (11)
        • Arduino (4)
      • Project (21)
        • Web Project (1)
        • App Project (1)
        • Paper Project (1)
        • 캡스톤디자인2 (17)
        • etc (1)
      • OS (10)
        • Ubuntu (9)
        • Rasberry pi (1)
      • App & Web (9)
        • Android (7)
        • javascript (2)
      • C++ (5)
        • 기초 (5)
      • Cloud & SERVER (8)
        • Git (2)
        • Docker (1)
        • DB (4)
      • Paper (7)
        • NLP Paper review (6)
      • 데이터 분석 (0)
        • GIS (0)
      • daily (2)
        • 대학원 준비 (0)
      • 영어공부 (6)
        • job interview (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    programmers
    소수
    Python
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
sillon
[Haptics - Haptuator Single Frequency] Calibration Using NI DAQ and Python
상단으로

티스토리툴바