로그인회원등록 내글장바구니주문조회현재접속자
 상품 검색








 게시판 검색





 
 
회원등록 비번분실


온라인 입금계좌
ㆍ기업은행
ㆍ219-043192-01-028
ㆍ이건영

      거래은행 바로가기
 
 Sensor Applications
아듀이노 응용소스
작성자 avrtools™        
작성일 2012/03/17
첨부#1 PmodIA.zip (9KB) (Down:11)
첨부#2 NewliquidCrystal.zip (6,159KB) (Down:7)
ㆍ추천: 0  ㆍ조회: 778   
  AD5933 LCR-Impedance Analyzer 제작
ADI사의 AD5933으로 만드는 LCR-교류저항 분석기(Impedance Analyzer)의 설계와 Arduino soucre code

인체 bio impedance 측정, 각종 소재의 chemical impedance 측정, pipe line 내부 impedance 측정 등,,,
전극을 절연한 용량센서로 곡물의 염분측정, 토양의 수분측정 등 비접촉으로 전극의 손실이 없는 측정 등,,,
압전소자(Piezo), 캐패시터, 리액터, 변압기, 스피커, 솔레노이드 권선 등은 교류저항(impedance)을 측정한다.

이전에는 교류저항을 측정하려면, 몇 십개 이상의 IC를 사용하는 커다란 기판에 LCR Meter를 만들어 왔다.
그러나 ADI사의 IA칩 AD5933을 사용하면 크기도 작으면서 저렴한 Arduino에서 매우 쉽게 개발할 수 있다.
 
 Multi range에서 radian shift를 제거한 완성판 AD5933 Impedance Analyzer
 
위 사진은 AD5933(사진 우측의 작은 기판)으로 만든 IA(교류저항 분석장치)는 1Kohm range에서
1K~25K의 impedance 범위를 10KHz~100KHz로 연속 sweep 하는 방법이다.
Z와 R은 phase offset이 0로 되면 |Z| =Rs 이므로 그래프에서 백색 Z와 황색 Rs 그래프가 겹친다.   
 
impedance range 1K면 1K~10K가 in-range이다. impedance range도 방법은 직류저항의 측정과 같다.
그러나 목적에 따라 1K range에서 오차를 허용하면서 1K~100K를 사용하기도 한다.
백색 Z 그래프 아래로 흩뿌리는 듯한 황색 점들은 계측값의 흔들림이 점으로 보이는 것이다.
10K 이내로 측정하면 이런 문제는 바로 없어진다. AD5933의 입력에 시험용 배선으로 잡음이 섞인것 같다.
 
AD5933의 system phase의 shift 문제는 인터넷을 검색하면 여기저기 문제는 있지만 해결방법이 없는 듯 했다.
AD5933은 IA(교류저항-분석장치)로 많은 기능이 함축된 IC로 여러모로 좋기 때문에 선택을 했다.
Application note를 보고 조각기판(break)을 구입하여 Arduino에서 간단히 처리될 줄 알았지만,
교류저항 1K~1M ohm을 주파수 10KHz~100KHz 범위에서 안정된 계측을 하려면 AD5933의 공부가 필요했다.
 
특히 impedance Z에서 유효저항 Rs와 Xc를 검출할 때 system phase 문제가 계속 걸림돌이 되었다.
sweep start 주파수에서 phase offset을 측정하여 시작 주파수의 system phase에서 감산하고,
sweep end 주파수에서도 phase offset을 측정하여 종료 주파수의 system phase에서 감산했다.
 
    rawM =sqrt((R1 *R1)+ (R2 *R2));  // raw Magnitude
    rad =atan(R2 /R1); // remain system radian
    rad =rad -abs(minRad -0.001);  // cancle offset of sweep-start radian
    rad =rad +abs((maxRad +0.008) *(stepFreq *sweep_cnt) /90000); // cancle offet of sweep-end radian
 
    // convert radian to phase of 4 quardrant 
    if ((real >0) && (img >0)) phase =(rad *180) /M_PI; // 1st quardrant
    if ((real <0) && (img >0)) phase =180 +((rad *180) /M_PI); // 2nd quardrant
    if ((real <0) && (img <0)) phase =180 +((rad *180) /M_PI); // 3rd quardrant
    if ((real >0) && (img <0)) phase =360 +((rad *180) /M_PI); // 4th quardrant
 
그리고 2.4인치 TFT-LCD인 SPFD5408에 측정값과 Frequency Sweep 결과를 그래픽으로 표시했다. 

 system phase 보상전의 system phase shift 상태 (녹색선이 측정된 raw phase)

 
sweep 주파수에 관계없이  theta가 틀어지지 않토록 code를 만들고, system theta를 보상해야 한다.
그래프에서 보상전 raw phase는 10 KHz에서 시작하여 100 KHz 까지 일정한 경사로 -72도 정도 shift 되고 있다.
 
다음 code로 주파수별 phase shift를 하나의 range에서만 보상해 보았다.
    // radian =(atan(img /real))-sysPhase      
    rad =atan(R2 /R1); // phase of current shift (imaginary /real)
    rad =rad -1.5849;  // radian -sysPhase
   
    double cFreq =startFreq +(stepFreq *sweep_cnt);  // current freq 
    rad =rad +(1.2341 *(cFreq /90000)); // compensate system shift of radian
    phase =(180 *rad) /3.141592654;  // radian to phase (deg)



 
r은 real, i는 imaginary, p는 phase, m은 magnitude, z는 impedance, R은 저항성분 Rs, X는 reactance, 
f는 sweep start 주파수 10KHz이다. 물론 시작과 마지막 주파수는 10KHz~100KHZ 범위안에서 바꿀 수있다.
 
Impedance Analyzer의 측정결과를 보면 m과 |Z|는 DUT가 일정하면 주파수와 전혀 관계가 없이 일정하다.  
그래프로 관찰하면서 theta가 틀어지는지 debugging한 결과, 그래프로 보니 개발이 매우 효율적이었다.
그리고 impedance와 주파수의 관계를 확인할 수 있으며, 측정값 Rs와 X값이 어떤 관계인지 알 수 있었다.
 
 10KHz~100KHz를 sweep 성능을 확인하는 debug 화면
 

 교류저항 분석기 Impedance Analyzer의 소스코드에 사용된 수식은 다음과 같다.
1. magnitude rawZ sqrt(imaginary^2 + real^2)
2. theta radian = 1 /atan(imaginary /real)
3. system phase shift = 1.5849 radian
4. compensate radian = rad -1.5849 <--- 시작 sweep frequency의 sysytem phase 보상
5. phase = (180 * rad)  /3.141592654
6. gainFactor =  1 / (calibration resistor * rawM) <--- 교정저항을 측정단자에 연결하고 rawM을 측정한다.
7. calibrated impedance |Z| = 1 / (gainFactor * rawZ)
 
교정값 보다 낮은 교류저항은 내부 증폭기가 포화하므로, 교정저항값 보다 낮은 교류저항은 측정하지 못한다.
예)  교정저항값 1Kohm보다 큰 1K~10Kohm의 교류저항을 측정할 수 있다
즉 R-feedback 저항을 range 마다 맞추어 바꾸어야 다른 range의 값을 측정을 할 수 있다.

모든 측정의 목표인 교류저항 impedance |Z|, 실효저항 R, 무효저항 X는 다음과 같다.
total  impedance |Z| = 1 / (gainFactor * rawZ) <--- |Z| = R +jX
 
추출 impedance(R 혹은 X)는 교류저항 Z 이며,  Z = |Z| *Δphase로  계산한다 
Resistance R = |Z| * cos(phase) <--- cos(pahse)이므로 cos 0도이면  |Z| = R
Reactance X = |Z| * sin(phase) <--- sin(phase)이므로 sin 0도 이면 X =0 
 
calibrated impedance |Z|에서 phase 값에 따라  R과 X는 크게 바뀔 수 있다. 
그러므로 impedance analyzer는 phase 검출과의 경쟁이라고 볼 수 있다.
다시말하면 AD5933 즉 IA-system 칩의 활용은 phase를 얼마나 안정되게 검출하는 가로 결정된다.

교정저항 1Kohm을 연결하고 rawM을 측정하는 사진, frequency sweep가 60% 정도 진행 중이다. 
시작주파수 10KHz에서 연결된 교정값 1000 ohm이 정확하게 표시되고, 100Khz 까지 impedance를 측정한다.,  

1K ohm의 교정 저항값은 아랫쪽 적색선, 입력 교류진폭 rawM은 윗쪽 황색선으로 주파수에 무관하게 일정하다.
phase shift는 교정저항이 순수저항이므로 중간의 phase 녹색선은 주파수에 따라 변하지 않고 직선을 그린다.
real 값은 보라색, imaginary는 청색선, 주파수에 따라 real값과 imaginary 값이 변화하는 것을 볼 수 있다.
 
입력단자에 100K ohm 저항을 연결하면, 아랫쪽에 있던 impedance 적색선이 크게 위로 올라간다.
입력단자에 측정하려는 물리적인 재료를 연결하면, 교류저항-주파수 특성곡선을 측정할 수 있다. 
(이때 측정진폭 rawM과 실효값 i, 무효값 r은 그래프에 표시하지 않고, 측정값만 숫자로 표시하면 된다.)
 
 만일 교정값 이하의 impedance를 측정하면?
 
 
사진은 1Kohm 저항으로 교정한 장치에 1Kohm 보다 낮은 값을 입력단자에 연결했을 때이다.
황색선 측정진폭 rawZ 즉 AD5933에 입력된 전류입력의 크기는 최대값인 20,000에서 포화되어 있다.
측정진폭 rawM은 측정 교류저항이 낮아지면 반비례하므로, 결국 장치의 아날로그 최고값 2V에 제한된다.
 
청색선  imaginary도 sweep 주파수의 상승에 따라 줄어들고 0점을 지나면 극성이 바뀐다.
검출위상도 Range가 바뀌어 측정 주파수에 따라 일정하지 않고 서서히 내려가다가 서서히 커지므로,
교정값 이하의 교류저항을 측정하면, 모든 측정값은 쓸 수 없다. phase 값도 사용할 수 없다.
 
교정값은 진폭이 큰 영역에 맞추기 때문에, 교정값 보다 낮은 교류저항은 측정진폭 rawM이 포화된다.
결국 측정 범위(range)는 1K ohm으로 교정하면 1~ 10K ohm이 측정영역이 된다.
 
 만일 교정값보다 10배 이상 높은값(over range)의 교류저항을 측정한다면?
 
 
측정값이 커져서 그래프가 윗쪽으로 이동하고 변화를 보기쉽게 된다. 하지만 측정오차는 커진다.
이 방법은 고정된 range 안에서, 교류저항의 변화를 측정하려 할 때 dynamic range가 넓으므로 유효하다.
 
입력단자에 연결된 외부의  impedance가 주파수에 따라 내려가면  |Z| 값이 변화하는 것을 볼 수 있다.
반대로 측정진폭 rawM과 real, imaginary는 반비례하여  낮아 지므로, 0 값 부근의 바닥에 몰려있다.
이 방법은 bio impedance의 측정이나, 물체의 검출, 검출값의 변화만을 감지하려고 할 때 사용한다. 
 
 입력단자를 open 시키면?
 
교류저항 |Z|는 큰값으로 올라가 화면을 위로 벗어나 안보이게 되고,
녹색선 검출위상 phase가 -90~+90deg 까지 측정주파수에 따라 크게 변화하는 것을 볼 수 있다.
rawM, real, imaginary는 역시 0 부근에 몰려서 바닥틀의 색이 바뀐것 처럼 보인다. 
 
 입력단자에 안테나를 연결하면?
 
 
입력단자에 무선안테나를 연결하면 |Z|는 값이 올라가 화면 위를 벗어나 안보이고 있지만,
phase는 각 주파수마다 매우 다양(random)하게 변하고 있다. 잡음이 띠처럼 보이는 그래프로 표시된다. 
어떤 보고서에서는, 연결된 물리적인 감지(sensor) 값인 교류저항의 변화를 이와 비슷한 화면으로 보고 있었다.
 
 AD5933의 system phase를 보상하면? 
문제는 system phase인데, 측정주파수기 고정되면 calibration 에서 system phase를 읽어서 보상하면 된다.
그러나 주파수탐색 작동에서는 주파수를 고정할 수 없고, full span인 100KHz 까지 탐색하므로 쉽지않다.
 
일단 on-fly 방법으로 relay 접점에 표준저항을 연결하고 입력단자에 접속하는 방법을 사용했다.
1. 교정저항을 on-fly 회로에 연결된 relay로 입력단자에 접속한다
2. 시작 주파수로 system phase를 측정하여 zero_Radian에 저장한다.
3. 마지막 주파수로  system phase를 측정하여 span_Radian에 저장한다.
4. 다음과 같이 system phase를 보상한다.
5. on-fly relay를 off 시킨다.
 
digitalWrite(relay, HIGH);  // on-fly relay를 on
startFreq =10000;  // 10KHz start
repeat_freq_measuare();  // measure r,i and calc radian, M, Z, R, X
zero_rad =rad;  // save zero radian
rad =0;
 
startFreq =100000;  // 100KHz start
repeat_freq_measuare();  // measure r,i and calc radian, M, Z, R, X
span_rad =rad;  // save span radian
rad =0;
digitalWrite(relay, LOW);  // on-fly relay를 off
 
이제 sweep_freq_measure()  위상처리에 아래 code를 추가한다.
rad =rad -abs(zero_radian);
rad =rad +abs((span_radian *sweep_cnt *stepFreq) /90000);
 
radian을 deg로 바꾸는 다음 방법은 real과 imaginary가 0 보다 클때만 가능하다.
 //  phase =(180 *rad) /M_PI;  // radian to phase
 
다음과 같이 1~4 상한(quardrant)의 처리를 해 주어야 한다.
if ((real >0) && (img >0)) phase =(rad *180) /M_PI; // 1st quardrant
if ((real <0) && (img >0)) phase =180 +((rad *180) /M_PI); // 2nd quardrant
if ((real <0) && (img <0)) phase =180 +((rad *180) /M_PI); // 3rd quardrant
if ((real >0) && (img <0)) phase =360 +((rad *180) /M_PI); // 4th quardrant
 
시험해 보자, 주파수가 바뀌어도 system phase를 보상하니 청색의 radian 그래프가 멋지게 펴졌다.
 
system phase가 on-fly 방식으로 교정됬다, 백색의 교류저항 Z와 황색의 Rs 그래프가 겹쳐진다.
1K range에서 입력단자에 최대값인 10K 저항을 연결하고 작동시켜 보았다. 
잡음이 조금 있지만 작동한다는 뜻이고, 10KHz ~ 1 00KHz 범위에서 system phase를 보상한 결과가 보인다. 

 TFT LCD의 표시에 사용한 arduino library
LCD는 SPFD5408_Adafruit_TFTLCD.h를 사용했다.
SPFD5408 color TFT LCD에 그래픽으로 문자와 그림을 그리는 방법은 다음번에 소개하기로 한다.
 
Arduino 라이브러리 SPFD5408_Adafruit_TFTLCD.h는 다음과 같이 추가한다.
#include <SPFD5408_Adafruit_TFTLCD.h>
#include <SPFD5408_Adafruit_GFX.h>
#include <SPFD5408_TouchScreen.h>
#include <pin_magic.h>
#include <registers.h>

 
#define LCD_RESET A4  // exchanged A4 to /reset <--- Uno의 RST 핀으로 연결을 변경.
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

TFT LCD SPFD5408은 A4핀을 reset로 사용하고 있다.
그러나 AD5933의 TWI도 A4와 A5를 SDA와 SCL로 사용한다
LCD 설명서를 보면 A4는 Uno의 reset 핀에 연결하면 A4를 TWI로 사용할 수 있다.

 Digilent 사의 Pmod-IA  
AD5933 칩은 SMD IC 이므로 빵판에 그대로 시험하기 어렵다.
그래서 Digilent 사의 Pmod-IA 기판을 인터넷에서 구입했다. 

 
AD5933 평가기판은 ADI 회사에서 개발도구로 판매하는 AD5933 impedance Analyzer 이다.
평가기판도 목표에 따라 검출회로는 추가해야 하므로 Pmod-IA 조각기판(break)를 사용했다.
 
 AD5933 IC 기본회로
  
 AD5933의 내부구조
간단히 설명하면, SPI 인터페이스로 2선식 Port를 이용하여 AD5933을 MPU로 제어할 수 있다.
AD5933은 DDS Generator와 PGA, 12 bit ADC, DSP 그리고 SPI 인터페이스를 내장하고 있다.

SPI는 Arduino 기판의 SDA 핀과  SCL 핀에 바로 연결한다.
SPI는 1개의 master MPU에서 여러개의 slave SPI 장치들을 연결할 수 있다.
예를 들면 다른 SPI 장치인 I2C-sensor나 I2C-LCD가 연결되어 있어도 된다.
 
DDS generator는 내부 32KHz clock 주파수로 분해능 27 비트 0.1Hz 이하까지 제어된다.
SPI로 설정된 주파수 1Hz~100KHz의 sine wave를 VOUT 핀에 출력한다.
VOUT의 출력은 진폭 2Vpp, 1Vpp, 0.4Vpp 혹은 0.2Vpp로 1~4의 정수를 ampVal REG에서 설정한다.
 
VOUT 핀으로 출력된 0.2Vpp~2Vpp 정현파 전압은 측정하려는 교류저항을 지나서 VIN 핀의 전류로 들어오고,
VIN 핀에 입력된 측정전류는 PGA에서 x1 혹은 x5 배로 증폭하고, 12 bit ADC로 디지털 변환된다.
DSP는 ADC로 측정한 2048개의 전류 값들을 DDS로 출력한 2048개의 전압값들과  DFT 연산한다.
DFT 연산된 실효값은 R-REG에 저장하고, 무효값은  I-REG에 저장한다.
 
DFT 처리수순(algorithm) 결과는 실수(real)와 허수(imaginary)로 각각 2 byte로 저장된다.   
측정된 교류저항(impedance)은 실수값 R과 허수값  I로  DFT 연산되어 REG에서 읽을 수 있다.
 
 AD5933 Pmod-IA 기판의 회로 
  

기판은 OPAMP AD8606를 추가하여 출력전류를 높여, 낮은 교류저항을 측정할 때 오차를 줄인다.
1선이 접지된 물리센서 측정기를 제작하려면, AD8606 A1의 +IN과 GND 사이에 측정회로를 연결한다.
측정회로는 opamp A1의 1/2 VDD의 Analog Reference 기준전압을 유지하기 위해 직류저지용 C를 추가한다.
그리고 opamp A1의 VOUT과 opamp A2의 -IN을 직결해준다.
 
 다음 실제 측정회로를 참조하라.
 
   

 AD5933 내부 DDS의 구조

 

 
 교류저항의 검출방법
 
 
청색은 AD5933의 VOUT 구동전압이며, 적색은 피측정부품(DUT)을 지나 AD5933의 VIN으로 들어가는 전류다.
AD5933의 내장 DSP에서 VOUT과 VIN의 구동전압과 검출전류를 각 cycle마다 4096개의 위상점에서 12비트 ADC로 변환하고,
구동전압과 검출전류 값들을 고속으로 DFT 연산한 결과(real, imaginary)는 2개의 16비트 register에 저장한다.
TWI 인터페이스로 status register에서 data valid를 확인하고, 읽은다음 아래의 계산식으로 처리한다. 
 
교류저항(impedance)의 진폭(magnitude)과 위상(phase)은 다음 식(equations)으로 계산한다.
double M = sqrt (R * R + I *  I);  // Magnitute
double Rad = atan(I / R);  // Radian (phase of angle)

교류저항의 측정은 일반적으로 주파수를 탐색(sweep)해서 측정한다.
주파수를 전압으로 출력하고, 측정 impedeance로 들어오는 전류를 ADC로 디지털 값으로  읽고,
다음 sweep 주파수로 출력을 바꾸고, 그동안 DFT 연산을 하고 다음 주파수를 측정한다.

교류저항은 하나의 위치(point) 마다 계산된다. 주파수-진폭 (spectrum)을 만들 수 있다.
Gain은 입력전류/구동전압의 비율이며, Gain이 커지는(유효저항 R값이 작아지는) 지역(point)은 공진점이다.
이때의 유효저항 R값이 공진 주파수에서의 내부저항(Rs)으로 교류저항값이다.

 AD5933에서 측정한 real과 imaginary로 LCR 값을 추출하는 공식은 다음과 같다.
임피던스 공식은 Z = R + jX  이나, 계산은 Z = │Z│ejθ 로 한다.

전류진폭은 Magnitude =sqrt (Real^2 + Imaginary^2) 이며
전류진폭 Maginitude로 부터 |Z| = 1 /(Magnitude * gainFactor) 를 산출한다.

위상편차는 Phase = atan (Imaginary / real)로 계산한다.
Radian =  atan (Imiginary / Real) - sysPhase 1.5849

주파수별 위상오차를 보상하려면 Radian = Radian + (1.2341 * (현재주파수 /Sweep주파수))
현재주파수가 50KHz 라면 전체 sweep 주파수는 90KHz 이므로 1.234 *(50/90)를 Radian에 더한다.
이 Phase 보상값은 range 별로 다르다, 그러나 시험할 때는 1 개로 사용해도 오차는 크지 않다. 

이 값은 radian 이며, |Z| ejθ 로 사용하려면, Phase ZØ인 -180~ +180 deg로 변환해야 한다.
Phase ZØ = (180 * Radian) / 3.141592654

ZØ를 계산했으므로 impedance Z = │Z│ejθ를 계산할 수 있다. 위상편차 ejθ = ZØ 이다.
실수 R (Zreal)과 허수 X (Zimagi)를 다음 식으로 계산한다.
R = |Zreal| = |Z| × cos (ZØ) 이것은 실제의 피측정 저항이다. 주로 내부저항 Rs값이다.
X = |Zimagi| = |Z| × sin (ZØ) 이것은 실제의 피측정 교류저항(L이나 R의 impedance값)이다,
 충전식 2차전지 성능시험기 (Battery Impedance Analyzer)
 
측정결과(Nyquist-주파수vs임피던스)에서 리튬이온 2차전지의 내부저항을 간단히 측정할 수 있다,

주파수가 높은 영역은 절연필름과 양면전극 사이의 분포용량으로 충전효과가 있어 직류측정방법은 오차가 있다.
교류저항측정은 주파수를 sweep 하고 교류저항이 낮아진 지점의 내부 저항으로 정확하게 판단할 수 있다.

2차 전지의 교류저항은 전류와 시간을 소비하지 않고, 공진점의 교류저항으로 2차전지의 내부저항이 측정된다.
 
비접촉 저농도 염도(salinity) 측정원리
 
 
위 도표는 염분의 커브를 조정하여 센서를 측정하려는 농도에 맞추고, 곡물의 염도(salinity)를 측정한다.
Impedance analyzer로 capcitance나 reactance의 측정이 가능하면 매우 다양한 센서의 개발이 가능하다.

 교류저항 분석기(Impedance Analyzer)의 계산방법 
실제로 판매되는 교류저항 분석장비는 LCR Meter 보다 고가인 Impedance Analyzer가 정확하다.
 
L, C, R의 직렬 복합회로, 병렬 복합회로 혹은 부품의 교류 임피던스를 1 ~1000 KHz 주파수로 측정한다.
대용량 부품은 1KHz, 스위칭전원의 부품은 10KHz~100KHz, 소형 고주파 부품은 1MHz로 측정한다.

전원장치의 ripple filetr에 사용하는 전해 캐패시터는 전원정류주파수 120Hz 용이므로 측정을 120Hz로 하고
캐패시터 제조사는 일반적인 캐패시터일 때, 기준주파수를 100KHz로 측정한 값을 특성표에 넣는다.

L, C의 측정에서 L 이나 C값이 크면 병렬저항 Rp는 무시되고, Rs는 직렬회로로 계산한다,
L 이나 C 값이 작으면 직렬저항 Rs는 무시되고, Rp만 산출하여 병렬회로로 계산한다.
 
 
 
 C 값을 추출하는 공식이다.
s는 직렬회로값. p는 병렬회로값, 각속도 ω는 2 * pi * freq(주파수)
직렬 임피던스 Zs = Rs – j / ω Cs = Rs (1 - j / D) 여기서 Rs는 내부 직렬저항이다.
병렬 임피던스 Zp = Rp / (1 + jω Cp Rp)
손실계수 D는 내부 병렬저항으로 발생하는 손실율이다. D = ωCsRs = 1/ωCpRp


 L 값을 추출하는 공식이다. 
s는 직렬회로값. p는 병렬회로값, 각속도 ω는 2 * pi * freq(주파수)
직렬 임피던스 Zs = Rs + jωLs = Rs (1 + jQ) 여기서 Rs는 내부 직렬저항이다.
병렬 임피던스 Zp = jω Lp Rp / (Rp + jωLp)
품질계수는 손실계수 D의 역수이다. Q = 1/D = ωLs / Rs = Rp / ωLp



 I2C 인터페이스
Arduino에서 I2C를 쉽게 연결하고 칩을 설정하거나 REG 값을 읽을 수 있는 TWI.h 라이브러리를 사용하면 된다.
 
I2C-LCD의 예
I2C library인 Wire.h를 설정하는 code는 다음 2줄 이다.
#include <LiquidCrystal_I2C.h> // 반드시 LCD에 맞는 것을 받아야 한다.   // IIC_LCD version 1.2.1
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
 
setup()에서 실행하는 I2C-LCD를 초기화하는 code는 다음 1 줄이다.
  lcd.begin(16,2);  // sixteen characters across - 2 lines
 
아래 2줄은 setup()에서 LCD의 back-light를 켜고 화면을 청소하는 code이다.
  lcd.backlight();  // back light on
  lcd.clear();      // clear LCD

 
setup()에서 LCD를 초기화한 다음, LCD 화면에 제목을 표시하는 code이다.
  lcd.setCursor(0, 0); // first character - 1st line
  lcd.print("Impedance       ");
  lcd.setCursor(2, 1); // 2nd character - 2nd line
  lcd.print(" Analyzer   v1.0");

 
I2C-AD5933의 예
#include <Wire.h>
 
setup()에서 실행하는 I2C-AD5933을 초기화하는 code는 다음 1 줄이다.
  Wire.begin(); // setup i2c for Twi of ad5933 (must inculde Wire.h)

 AD5933은 AD5933.h가 필요하다.
라이브러리에 저장된 AD5933.h를 보면 다음과 같다.
#define rControlMSB byte(0x80)
#define rControlLSB byte(0x81)
,,,,,,
 
이걸 AD5933.h에 넣어 놓고, #include <AD5933.h> 로 선언하고,
선어된 label을 rControlMSB 등등을 code나 컴파일러에서 상수로 사용한다.
문제는 AD5933 library를 보지도 않고 세세한 이름을 한자도 틀리지 않고 code를 만들려면 갑갑해진다.
그래서 coding 초기에는 AD5933.h를 선언하지 않고, AD5933.h에서 복사해서 꺼내놓고 시작한다.

/* AD5933 REGISTRY MAP */
#define rControlMSB byte(0x80)
#define rControlLSB byte(0x81)
#define rStartFreqMMSB byte(0x82)
#define rStartFreqMSB byte(0x83)
#define rStartFreqLSB byte(0x84)
#define rFreqIncrementMMSB byte(0x85)
#define rFreqIncrementMSB byte(0x86)
#define rFreqIncrementLSB byte(0x87)
#define rNumberIncrementsMSB byte(0x88)
#define rNumberIncrementsLSB byte(0x89)

/* AD5933 COMMAND*/
#define AD5933_BLOCK_WR 0xa0        //Block Write Command
#define AD5933_BLOCK_RD 0xa1        //Block Read Command
#define AD5933_ADDR_PTR 0xb0        //Address Pointer
#define AD5933_INIT 0x10          //Initialize with start Freq
#define AD5933_SWEEP 0x20         //Start Frequency Sweep
#define AD5933_INCFREQ 0x30         //Increment Frequency
#define AD5933_REPEAT_FREQ 0x40       //Repeat Frequency
#define AD5933_MEASURE_TEMP 0x90      //Measure Temperature
#define AD5933_PWR_DWN 0xa0         //Power down mode
#define AD5933_STANDBY 0xb0         //Standby mode
#define AD5933_RESET 0x10         //Reset Command
#define AD5933_VRANGE_200mV 0x02      //Output Voltage range 200mV
#define AD5933_VRANGE_400mV 0x04      //Output Voltage range 400mV
#define AD5933_VRANGE_1V 0x06       //Output Voltage range 1V
#define AD5933_VRANGE_2V 0x00       //Output Voltage range 2V
#define AD5933_PGA_1X 0x01          //PGA gain x1
#define AD5933_PGA_5X 0x00          //PGA gain x5
#define AD5933_BASE_CFG (AD5933_VRANGE_2V | AD5933_PGA_1X) //2Vpp and PGA x1
#define AD5933_INT_OSC_FREQ_RATIO 32.002319 //Internal MCLK = 16.776 MHz
#define AD5933_EXT_OSC_FREQ_RATIO 33.554432 //External MCLK = 16.000 MHz
 
/* AD5933 status definitions */
#define AD5933_STAT_TEMP_VALID 0x01
#define AD5933_STAT_DATA_VALID 0x02
#define AD5933_STAT_SWEEP_DONE 0x04
 
/* AD5933 registers definitions */
#define AD5933_CTRL_HIGH 0x80       //RW 2 bytes
#define AD5933_CTRL_LOW 0x81      //RW 2 bytes
#define AD5933_FREQ_HIGH 0x82     //RW 3 bytes     
#define AD5933_FREQ_MID 0x83
#define AD5933_FREQ_LOW 0x84
#define AD5933_FREQ_INC_HIGH 0x85   //RW 3 bytes
#define AD5933_FREQ_INC_MID 0x86
#define AD5933_FREQ_INC_LOW 0x87   
#define AD5933_NUM_INC_HIGH 0x88    //RW 2 bytes, 9 bit
#define AD5933_NUM_INC_LOW 0x89
#define AD5933_NUM_SETTLE_HIGH 0x8a   //RW 2 bytes
#define AD5933_NUM_SETTLE_LOW 0x8b
#define AD5933_STATUS 0x8f        //R 1 byte
#define AD5933_TEMP_HIGH 0x92     //R 2 bytes
#define AD5933_TEMP_LOW 0x93
#define AD5933_REAL_HIGH 0x94     //R 2 bytes
#define AD5933_REAL_LOW 0x95 
#define AD5933_IMAG_HIGH 0x96     //R 2 bytes
#define AD5933_IMAG_LOW 0x97  
#define AD5933_DATA_BUFFER_SIZE 3  // Max buffer size from AD5933 registers - 3 bytes

#define rNumberSettlingCyclesMSB byte(0x8A)
#define rNumberSettlingCyclesLSB byte(0x8B)
#define rStatus byte(0x8F)
#define rTemperatureMSB byte(0x92)
#define rTemperatureLSB byte(0x93)
#define rRealDataMSB byte(0x94)
#define rRealDataLSB byte(0x95)
#define rImDataMSB byte(0x96)
#define rImDataLSB byte(0x97)
 
 소스에 사용된 변수
// 여기부터는 AD5933.h를 include 하더라도 필요한 부분이다.
#define SLAVE_ADDR 0x0D // ad5933 slave address in TWI
#define ADDR_PTR 0xB0   // ad5933 address pointer
 
nt real;
int img;
 
byte val;
float R1;
float R2;
 
double rad;
double phase;
double rawM;
double z;
double aveZ;

#define freqRatio 32 // (4*(2^27)/16.776e6)
#define ADGain 3240000 // calibration and will result in kohm values
#define ADSystemPhase 1.37 // radian =atan(img /real) -1.37
 
// gainFactor =(1 /RFB) /rawMAG // RFB=10K, rawMag =20980 @1KHz
#define gainFactor (0.000000004766) // out 2Vpp, PGA x1, RFP 10K, 1KHz
unsigned int ampVal =4; // output =0.2Vpp (20%)
unsigned int setPGA =0; // ad-gain x1 =1, ad-gain x5 =0
 
// ADProgramFrequencySweep(startFreq, stepFreq, maxStep);
unsigned long startFreq =990; // start frequency 1KHz
unsigned long stepFreq =10;   // step frequency 20Hz
unsigned int maxStep =10;     // number of increament 511 max
unsigned int set_cyc =50;    // settling time max512 with multiplier 1,2,4
 
 소스코드 (main)
void setup()
{
  lcd.begin(16,2);  // sixteen characters across - 2 lines
  lcd.backlight();  // back light on
  lcd.clear();      // clear LCD
 
  lcd.setCursor(0,0); // first character - 1st line
  lcd.print("Impedance       ");
  lcd.setCursor(0,1); // 8th character - 2nd line
  lcd.print(" Analyzer   v1.0");
  
  // setup i2c for Twi of ad5933 (must inculde Wire.h)
  // TWI port : SDA =A4 and SCL =A5
  Wire.begin();  // TWI의 초기화
  
  ADInit();     // chip reset after power on
  ADStandby();  // AD5933 전원을 대기(Standby)로 설정
  
  // AD5933 시작 주파수를 초기값으로(처음 주파수로 내린다)
  ADInitializeFrequency(); 
  delay(500); //Make sure settling time has elapsed
 
  ADSweep();  // AD5933을 frequency sweep 작동으로 설정
  delay(500);
}
 
// 다음은 Arduio sketch의 main()인 loop()의 code를 만들면 된다,
void loop()
{
  // 가변저항을 A0에서 읽어서 시작주파수로 설정한다
  val =analogRead(0); 
  if (val <50) val =50;   // limit min =50 *20 = 1,000Hz
  else if (val >500) val =500; // limit max =500 *20 =10,000Hz

  startFreq =(val *20); // 시작주파수를 설정한다. 1KHz~100KHz
  stepFreq =1;  // step freq =1Hz
  maxStep =8;  // start ~ +1Hz sweep
  ADProgramFrequencySweep(startFreq, stepFreq, maxStep);
  delay(50); //Make sure settling time has elapsed
 
  // 출력진폭을 설정한다.
  // amp =1 (2Vpp), amp =2 (1Vpp), amp =3 (0.4Vpp), amp =4 (0.2Vpp)
  ampVal =2;  // 1Vpp output
  ADSetAmplitude(ampVal); // output amplitute (1,2,3,4)
  delay(50); //Make sure settling time has elapsed
    
  // 현재 주파수를 시작주파수로 내린다.
  ADInitializeFrequency(); // start 10KHz, +1Hz, 10 step
  delay(50); //Make sure settling time has elapsed
 
  // 외부 측정회로의 수렴시간을 설정한다
  // ADSettlingTime(int nCycles, byte multiplier)
  set_cyc =50; // max =512 *4 =2048 cycles delay for settling time
  int set_mul =0;   // x1
  ADSettlingTime(set_cyc, set_mul); // (multiplier (1,2,4)
  delay(50); //Make sure settling time has elapsed
 
  // 입력증폭기의 증폭도를 x1로 설정
  // setPGA =1; // 0 =PGAx5, 1 =PGA x1
  ADSetGain(setPGA);    // defaut setPGA x5 (0.2Vpp *5 =2Vpp/fs)
  delay(50); //Make sure settling time has elapsed
 
  // 주파수 변화방식으로 설정 start frequency sweep
  ADSweep();  //(0x10) => [0x80] // start frequency sweep 
  delay(10); //Make sure settling time has elapsed
     
  int i =0;
  //  sweep done 끝날 때 까지 아래 code를 실행하고 10회 측정후 측정값을 LCD에 표시한다. 
  while(!(ADReadRegister(rStatus) & 0x04)) 
  {
    // 1 회 측정이 끝날 때 까지 여기에서 대기      
    while (! (ADReadRegister(rStatus) &0x02));
    delay(10);
    
    // real 값을 읽는다
    val =ADReadRegister(rRealDataMSB);
    real =(val << 8); // high byte
    val =ADReadRegister(rRealDataLSB);
    real |=(val);    // low byte    Real 값을 저장 (2의 보수이다)

    if (real <= 0x7FFF) real =(real & 0x7FFF);    // 양수는 상위의 극성만 지운다
    else
    {
      real =(real & 0x7FFF);
      real =(real -65536);  //  음수는 양수로 변환한다
    }
 
    R1 =abs(real);
    R1 =(R1 * R1);  // real^2 임시로 저장
    
    // image 값을 읽는다
    val =ADReadRegister(rImDataMSB); 
    img =(val << 8);  // high byte
    val =ADReadRegister(rImDataLSB);     
    img |=(val);      // low byte   imaginary 값을 저장 (2의 보수이다)

    if (img <= 0x7FFF) img =(img & 0x7FFF);    // 양수는 상위의 극성만 지운다
    else
    {
      img =(img & 0x7FFF);
      img =(img -65536);  // 음수는 양수로 변환한다
    }
 
    R2 =abs(img);
    R2 =(R2 * R2);  // imaginary^2를 임시로 저장 

    // raw Magnitute 진폭을 저장 (미교정 임피던스)
    rawM =sqrt(R1 +R2);
    rad =atan(img /real);     // phase of current shift 위상차를 계산 

    // sys rad -1.37 시스템 위상편차를 보상 
    // ADSystemPhase (-1.37)
    rad =rad -(ADSystemPhase);  // radian

    // sys phase 118 deg RAD을 DEG로 전환 (주의: 2,3,4상한은 보상 필요)
    //phase =(180 *phase) /M_PI;  // make degree  
    //  phase =phase -118; 
    
   // |Z|는 평균 처리한다.
    if (i == 0) aveZ =z; // +z at 1st time 
    else aveZ =(aveZ +z) *0.5; // average * 50%

    // 교정값 계산은 측정된 미교정 rawM 값을 사용한다.
    // gainFactor =(1 /RFB) /rawMag); // RFB=10K, rawMag=27040
    // gainFactor =(0.0000000036982)  // 2Vout,Gain=X1,Ri=10K @1KHz
    z = 1 /(gainFactor *rawM);   // calibrated impedance Z=10006 OK
                
    // 이제 1cycle 측정이 끝났다. 다음 sweep frequency를 시작      
    ADIncrementFrequency(); 
    if (i++ >maxStep) return;  // 설정된 반복 CYCLE 만큼 측정한다.
  }

  // AD5933의 발열을 방지하기 위해 작동을 power down으로 설정한다
  // Power down: writeData(CTRL_REG,0xA0);
  writeData(0x80,(readData(0x80) & 0x07) | 0xA0);
 
  display_lcd();  // 측정결과를 lcd에 표시한다
  delay(5000);    // 표시를 편안히 보기위한 시간
}

시험결과
usb2serial-2.0과 Meag328-mini 그리고 Pmod-IA를 사용했다.
  

주변장치는 I2C-LCD와 smartphone에 Audio Oscilloscope app을 설치해서 출력파형을 볼 수 있다.
AD5933은 1Hz~100KHz 까지 깨끗한 정형파를 출력하고 DFT 연산된 Impedance를 R 과 I값으로 출력한다.
AD5933은 Frequency Impedance를 측정하는 모든 기능이 하나의 칩에 내장된 훌륭한 반도체 시스템 IC이다.  

 gainFactor의 확인과 측정
고정된 측정조건 (F =1KHz, RFB =10Kohm, RIN =10Kohm, ampVol =1Vpp, PGA =1)에서
교정없이 측정되는 r =14180, i =15450 으로 계산된 rawM =20980 일때
 
gainFactor =(1 /RFB) /rawMag) 이므로 =(1 /10000) /20980) =0.000000004766
연결된 저항값을 측정한  impedance Z는 =1 /(gainFacotr * rawM) = 9999 이다.

시간에 따라 Z는 조금씩 흔들린다. 그러나 상온에서는 소숫점 아래의 흔즐림으로 오차는 적다.
R-feedback을 100Kohm, R-input을 100Kohm 으로 바꾸어 시험해도 같은 결과가 나온다.
 
 AD5933 Impedance Analyzer 시험결과 (아래에 있는마지막 줄이 평균값이다)
 
  

1K~10K를 측정하려면 ampVout을 1/10인 0.2Vpp로 낮추면 code 만으로 range를 1/5로 바꿀수 있다.
반대로 50K~500K를 측정하려면 ampVout을 2Vpp, PGA =X5로 하면 역시 range를 10/1으로 바꿀수 있다. 
즉 1개의 FRB 저항으로 5K~10K,  10K~100K, 100K~500K 까지 3개의 Range를 사용할 수 있다.

참조 : AD5933 Pmod-IA  Impedance Analyzer : 구입시 받을 수 있다, 첨부파일 #1

참조 : I2C LCD Library : 첨부파일 #2는 압축을 풀고, 
         문서 --> Arduino --> Libarary 안에 폴더로 복사해 넣는다.
참조 : Study of the Suitability of an AD5933-based Spectrometer for EBI Applications :
          Final_Degree_Thesis-AAP.pdf(2.7MB) <--- 정리가 잘 안된 소스다. (참고).

 subroutine :   ad5933-IA-sub.c(7KB)
 
 결론 :
기존 방식의 LCR Meter나 Impedance Analyzer는 DDS 출력과 Impedance current를 모두 측정한다.
DDS의 정현파 위상이 구동증폭기에서 틀어지므로 구동위상을 먼저 측정해서 기준위상으로 저장한다.
다음 측정하는 교류저항에 흐르는 전류의 진폭과 위상은 원래의 측정목적이므로 당연히 측정을 한다.
그러므로 구동증폭기나 검출증폭기의 위상차는 기준구동위상에서 보상이 되므로 system phase 문제가 없다. 
 
AD5933은 디지털방식으로 자신이 발생하는 DDS의 위상은 table에서 이미 알고 있으므로,
구동증폭기나 검출증폭기에서 system pahse가 틀어지는 것을 각 측정주파수에서 calibration으로 맞추고 있다
그래서 구동파형의 위상은 검출하지 않고, DDS 파형 table을 사용하는 관계로 system phase 보상이 필요하다.
 
AD5933은 구동하는 주파수 영역에서 system phase는 주파수, range, impedance에 전혀 따라 일치하지 않는다.
AD5933 sweep 방식은 system phase 값이 랜덤하다. sweep하면 Rs는 변동하므로 impedance Z만 사용한다.  
즉 R과 X값은 고정된 주파수와 range에서 숫자로만 표시할 수 있다, sweep하는 FFT에는 함께 표시할 수 없다.

 Frequency Sweep Impedance Analyzer의 Custom Design (개발, 설계, 기술지원, 상품) 주문 받습니다. 
 
자료의 무단복제 및 무단배포를 금지합니다.
이 프로그램은 무료 소프트웨어로, 신체와 재산 상의 어떤 위험과 손해를 보상하지 않습니다.
이 프로그램은 GNU 무료 소프트웨어 배포규정을 따릅니다.

 
AVRTOOLS™
   
윗글 DUE SAM3X8E Audio FFT Analyzer 제작
아래글 ESP-01 펌웨어 업그레이드와 WiFi 2 Relay Control
    N         제목    글쓴이 작성일 조회 추천
아듀이노 응용소스 게시판 avrtools™ 2016/02/05 (금) 515 0
41 STM32F103C 12비트 정현파 DDS V2 avrtools™ 2018/03/08 (목) 198 0
40 STM32F103C ILI9341 TFTLCD Scope V2 avrtools™ 2018/03/05 (월) 254 0
39 STM32F103C 32비트 ARM-CPU 2채널 Scope avrtools™ 2018/02/25 (일) 230 0
38 STM32F103C의 ILI9341 ILI9163 TFT-LCD 연결방법 avrtools™ 2018/02/19 (월) 229 0
37 STM32F103C+MCP4725 DDS 1KHz 정현파 발생기 avrtools™ 2018/02/18 (일) 256 0
36 STM32F103C 기판의 1~8CH ADC DMA 전송 avrtools™ 2018/02/17 (토) 279 0
35 STM32F103C 기판의 SSD1306 OLED 구동 avrtools™ 2018/02/16 (금) 217 0
34 STM32F103C ARM32 기판의 독립 IDE 소개 avrtools™ 2018/02/14 (수) 309 0
33 STM32F103C ARM32 기판의 Bootloader 개조 avrtools™ 2018/02/14 (수) 312 0
32 ESP32+OLED 기판과 PWM generator avrtools™ 2018/02/11 (일) 225 0
31 Wemos-Lolin32 Audio FFT Analyzer 제작 avrtools™ 2018/02/07 (수) 229 0
30 DUE SAM3X8E Audio FFT Analyzer 제작 avrtools™ 2018/01/30 (화) 245 0
29 AD5933 LCR-Impedance Analyzer 제작 avrtools™ 2012/03/17 (토) 778 0
28 ESP-01 펌웨어 업그레이드와 WiFi 2 Relay Control avrtools™ 2017/12/24 (일) 216 0
27 ESP12E-devKit로 만드는 WiFi 4 Relay 제어장치 avrtools™ 2017/12/23 (토) 243 0
26 M328-mini로 만드는 Touch 용량검출센서 avrtools™ 2017/12/19 (화) 229 0
25 ESP8266 MQTT Relay Control avrtools™ 2016/03/03 (목) 748 0
24 2 채널 ESP8266 WiFi Switch의 제작 avrtools™ 2016/02/25 (목) 974 0
23 ESP-12E SDK 0.9.5 사용방법 avrtools™ 2016/02/18 (목) 803 0
22 ESP8266 ESP-12E WiFi 센서 서버의 제작 avrtools™ 2016/02/17 (수) 760 0
21 Arduino DS3231 RTC to 5110 LCD avrtools™ 2016/02/16 (화) 765 0
20 ESP8266 Weather Server의 제작 avrtools™ 2016/02/15 (월) 838 0
19 Arduino 온습도 센서 DHT-22 avrtools™ 2016/02/12 (금) 629 0
18 ESP8266 WiFi 펌웨어 업그레이드 avrtools™ 2016/02/11 (목) 1053 0
17 Arduion ESP8266 WiFi 설정 방법 avrtools™ 2016/02/10 (수) 1022 0
16 Arduino 정전용량식 수분센서의 분석과 제작 avrtools™ 2016/02/07 (일) 574 0
15 Arduino 전극식 수분센서의 분석과 제작 avrtools™ 2016/02/07 (일) 720 0
14 Arduino 정밀 전력계의 ADC avrtools™ 2016/02/02 (화) 1180 0
13 Arduino 정밀 전력계의 LPF avrtools™ 2016/02/02 (화) 707 0
12 Ardunio 16비트 ADC Data Logger avrtools™ 2016/01/31 (일) 618 0
11 Arduino AC/DC Power Meter의 제작 avrtools™ 2016/01/29 (금) 1255 0
10 Arduino 교류 역율계(power factor)의 제작 avrtools™ 2016/01/29 (금) 766 0
9 Arduino DUE Pezo-SPeaker LCQ Meter 소스 avrtools™ 2016/01/24 (일) 481 0
8 QTouch ADC 근접검출 스위치 avrtools™ 2016/01/21 (목) 783 0
7 Arduino 음성인식 Speech/Voice Recognition avrtools™ 2013/09/14 (토) 1947 0
6 Arduino Uno로 만드는 3축 CNC avrtools™ 2013/09/10 (화) 2917 0
5 Arduino로 만드는 mySpectral 분광기 avrtools™ 2013/09/04 (수) 2424 0
4 8채널 12비트 ADC MCP3208 오실로스코프 avrtools™ 2012/03/29 (목) 809 0
3 교류저항 (impedance) 측정 AD5933 avrtools™ 2012/03/17 (토) 757 0
2 Arduino DMX512 수신기 제작 avrtools™ 2012/03/15 (목) 4067 0
1 TSL2561 조도 측정기의 제작 avrtools™ 2011/09/11 (일) 2954 0
1

바구니 : 0
 보관함 : 0
오늘뷰 : 0
HOME   |   회사소개   |   제휴안내   |   회사위치   |   서비스이용 약관   |   개인정보 보호정책   |   사이트맵
17015 경기도 용인시 기흥구 동백중앙로16번길 16-25, 508호. 전화 : 031-282-3310
사업자 등록번호 : 697-47-00075 / 대표 : 이건영 / 업태 : 제조업 / 종목 : LED조명, LED전원, 제어장치.
개인정보 관리책임자 : 홈페이지 관리자 . Copyright ⓒ2016 아크레즈 (ACLEDS INC.)
HOME TOP PREVNEXT 0 0 0