lizengmao 发表于 2023-4-28 14:09:39

[已解决]求助:DIY LCR Meter时,测试电容发现测到的DUT相位角不稳定

本帖最后由 lizengmao 于 2023-4-28 17:27 编辑


想要DIY LCRMeter,临时使用以下硬件进行测试:使用STM32两路ADC对DUT的电压电流进行采样.硬件:使用运放(OPA2365,GB=50MHz,SR=25V/uS,Vos=100uV)构成电压采集和电流采集电路.激励信号暂时使用iPad配合App产生1kHz正弦波,测试时手工调整iPad的音量以防止运放的输出失真.如下图.
软件方面,使用STM32G070CBT6的两路ADC对运放的输出进行采集.ADC设定为Scan Mode.同时把TIM3设定为1kHz*128=128KHz.在TIM3中断中触发ADC采样.ADC采样数量:预计每个信号周期采样128点,至少需采样4个周期因此需采样128*4=512点,实际上我采样了128*6=762点,然后在软件中取出4个周期512点用于FFT处理. FW处理流程如下:1.    启动TIM3,在TIM3的中断中启动ADC采样,将得到2路ADC的数据.直到采集到所需的采样点数才停止TIM3.2.    搜索ADC中,电压第一个最低的点,并从这个点开始,复制512个数据到FFT处理缓冲中.记录起始的索引值.3.    进行FFT处理,得到电压的实部和虚部4.    从第二步得到的索引值,取出ADC中电流的512个数据,并进行FFT处理,得到电流的实部和虚部.5.    计算电压,电流的幅值和相位.6.    计算DUT的阻抗和相位.7.    从DUT的阻抗和相位,计算DUT的实部和虚部.8.    从DUT的阻抗计算电容器的电容值9.    从DUT的实部和虚部计算电容器的D值.当前的问题:计算DUT的相位时不稳定,进而导致电容器的D值不稳定.猜测可能是从ADC取出电压电流值给FFT缓冲时,不是真正的过零点引起.但是不知道如何计算才能得到真正的过零点.也可能是我的计算公式错误.请各位有经验的帮忙检查一下是哪里除了问题?另外我使用0.47uFCBB电容时,得到的相位角时57度左右,这是正确的吗?实际用成品电桥测试这颗电容,容量=0.480uF,阻抗=331ohm,D=0.004.
以下是计算的方法和实际结果.


//定义变量
struct {
double real;         //实部
double imag;      //虚部
double amp;               //从实部,虚部计算得到的幅值
double theta;       //计算得到的相位角
}volt,cur,Z;                         //采集到的电压和电流,及计算的阻抗Z
struct {
double R;   //Resistance
double L;   //Inductance
double Q;   //Q
double C;   //capacition
double D;   //loss ant
double Z;   //Z
double Zr;//阻抗实部
double Zx;//阻抗虚部
double Theta; //DUT相位
}DUT;

//对采样值进行FFT处理
fftAdc(adc_volt); //从ADC结果从第一个最小值开始取出4个周期的电压信号,ADC值除以HW电压增益(1.91),然后存入FFT缓冲,对采集到的电压信号进行FFT. FFT运算后,已运算了sqrt(real*real+imag*imag),并把结果存回real,每个real都进行了运算..FFT运算前,未移除DC值.
fftGetPeak();   //检索电压信号实部的峰值,得到峰值的索引值peakFrenqucyIndex,即为激励信号所在的FFT实部/虚部的位置.
volt.real = vReal ; //取出电压的实部
volt.imag = vImag ; //取出电压的虚部

fftAdc(adc_cur);//在电压信号取出的第一个位置开始,取出4个周期电流信号,ADC值除以电流采样电阻Rm(1000),然后存入FFT缓冲,对采集到的电流信号进行fft
cur.real = vReal;//取出电流的实部,索引值与电压信号一致.
cur.imag = vImag;//取出电流的虚部
volt.real -= cur.real;//HW中,电压信号并非是使用差分运放直接取出DUT的电压信号, 包含了电流的信号,因此需要减去电流的信号
volt.imag -= cur.imag;
//计算DUT电压的幅度和相位
volt.amp = sqrt(volt.real * volt.real + volt.imag * volt.imag) ;//根据实部,虚部计算电压幅值
volt.theta= (atan2(volt.imag, volt.real) / PI) * (double)180.0 ; //计算电压相位角=artan(vi/vr)*180°*PI
//计算DUT电流的幅度和相位
cur.amp = sqrt(cur.real * cur.real + cur.imag * cur.imag); //计算电流幅值
cur.theta= (atan2(cur.imag, cur.real) / PI) * (double)180.0 ; //计算电流相位角=artan(vi/vr)*180°*PI
//计算电流相位角与电压相位角的差值.
//方法1
//Z.theta = cur.theta - volt.theta; //阻抗的相位=电流相位-电压相位
//方法2,按Rx+Xs串联计算,参考bilibili的视频
//double x = cur.real * cur.real + cur.imag * cur.imag;
//double Rs = (volt.real * cur.real + volt.imag * cur.imag) / x;
//double Xs = (volt.imag * cur.real + volt.real * cur.imag) / x;
//double Q = abs(Xs) / Rs;
//Z.theta = Q * (double)180.0 / PI;
//方法3
Z.theta = (atan(volt.imag / volt.real) - atan(cur.imag / cur.real)) * (double)180.0 / PI;
//以上三种方法,得到的相位角都不稳定,DUT=0.47uF CBB电容式,在-54~-59度之间变动

//计算阻抗
Z.amp = volt.real / cur.real;//这个公式对吗?阻抗=电压实部/电流实部.DUT=0.47uF电容,Z.amp=331~332ohm,理论值计算此时容抗是338.62ohm.
Z.real = Z.amp * cos(Z.theta * PI / (double)180.0);   //实部=电流幅度*cos(相位*PI/180)
Z.imag = Z.amp * sin(Z.theta * PI / (double)180.0);   //虚部=电流幅度*sin(相位*PI/180)
//复制计算结果,以便计算DUT的C,L,D,Q
DUT.Zr = Z.real;
DUT.Zx = Z.imag;
DUT.Theta = Z.theta;
DUT.Z = Z.amp;
//计算电容的参数
DUT.D = DUT.Zx / DUT.Zr;      //电容器的D=阻抗虚部/实部
DUT.C = (double)2.0 * PI * singleFrequency * DUT.Z; //电容单位为F
DUT.C = DUT.C / (double)1000000.0;            //电容单位为uF
DUT.C = (double)1000.0 / DUT.C;               //电容单位为nF
//计算电感的参数
DUT.Q = abs(DUT.Zr / DUT.Zx);      //电感器的Q=1/D=阻抗实部/虚部
DUT.L = -DUT.Z / (double)2.0 * PI * singleFrequency; //电感单位为H
DUT.L = DUT.L * (double)1000000.0;            //电感单位为uH
//使用P,S进行计算,计算得到的相位也会跳动
DUT2.P = volt.real * cur.real + volt.imag * cur.imag;//P:有功功率=Vr*Ir+Vi*Ii
DUT2.S = sqrt(volt.real * volt.real + volt.imag * volt.imag) * sqrt(cur.real * cur.real + cur.imag * cur.imag);//S:视在功率=|V|*|I|=sqrt(Vr^2+Vi^2)/sqrt(Ir^2+Ii^2)
DUT2.cosDF = DUT2.P / DUT2.S;
DUT2.Zamp = volt.real / cur.real;
DUT2.theta = acos(DUT2.cosDF) * (double)180.0 / PI;
DUT2.Rs = DUT2.Zamp * cos(DUT2.theta / PI * (double)180.0);
DUT2.Rx = DUT2.Zamp * sin(DUT2.theta / PI * (double)180.0);
DUT2.Z = DUT2.Rx + DUT2.Rs;
以下是解算出来的结果:
结果1:
解算DUT
DUT.Zr=191.93
DUT.Zx=-271.84
DUT.Theta=-54.78
DUT.Z=332.76
DUT.D=-1.42
DUT.C=478.29
按P,S方式解算DUT
DUT2.P=15754051.01
DUT2.S=27314522.46
DUT2.cosDF=0.58
DUT2.Zamp=332.76
DUT2.theta=54.78
DUT2.Rs=-332.68
DUT2.Rx=-7.43
DUT2.Z=-340.11
结果2:
解算DUT
DUT.Zr=190.90
DUT.Zx=-271.65
DUT.Theta=-54.90
DUT.Z=332.01
DUT.D=-1.42
DUT.C=479.36
按P,S方式解算DUT
DUT2.P=15701516.46
DUT2.S=27308265.47
DUT2.cosDF=0.57
DUT2.Zamp=332.01
DUT2.theta=54.90
DUT2.Rs=-197.61
DUT2.Rx=-266.80
DUT2.Z=-464.41
结果3:
解算DUT
DUT.Zr=179.86
DUT.Zx=-278.74
DUT.Theta=-57.17
DUT.Z=331.73
DUT.D=-1.55
DUT.C=479.77
按P,S方式解算DUT
DUT2.P=14873992.92
DUT2.S=27432687.24
DUT2.cosDF=0.54
DUT2.Zamp=331.73
DUT2.theta=57.17
DUT2.Rs=-94.43
DUT2.Rx=318.01
DUT2.Z=223.58
更多的测试结果请看附件TXT.
实测ADC输入波形:

电路图

测试用的PCBA,TFT中,右下角显示采样得到的的电压,电流的ADC值,绿色曲线是电压,红色曲线是电流,

实测电容的参数


测试log档

gaolf_2012 发表于 2023-4-28 16:49:08

第二步512个点电压电流值发出来看看波形是否是预计的样子

lizengmao 发表于 2023-4-28 17:26:16

本帖最后由 lizengmao 于 2023-4-28 17:38 编辑

问题已经找到.
原因在于FFT处理函数中,我已经把实部和虚部分别平方加起来再开方了.把这个计算去掉,然后更改阻抗,相位的计算公式即得到较稳定的测试结果.
fftAdc(adc_volt); //从ADC结果从第一个最小值开始取出4个周期的电压信号,ADC值除以HW电压增益(1.91),然后存入FFT缓冲,对采集到的电压信号进行FFT. FFT运算后,已运算了sqrt(real*real+imag*imag),并把结果存回real,每个real都进行了运算
计算方式更改如下:
//fftGetPeak();   //检索电压信号实部的峰值,得到峰值的索引值,即为激励信号.---删除---
peakFrenqucyIndex=singleFrequency*fftSamples/sampleRate;//从信号频率计算在实部中的索引值,例如1khz激励信号,128000采样率,512点,FFT分辨率=250Hz,1kHz在第4个点.
Z.amp = volt.amp / cur.amp;
DUT.D = -(DUT.Zr / DUT.Zx);
更改后解算结果如下:
结果1:
解算DUT
DUT.Zr=2.49
DUT.Zx=-333.49
DUT.Theta=-89.57
DUT.Z=333.50
DUT.D=0.007461
DUT.C=477.22
按P,S方式解算DUT
DUT2.P=-452709.04
DUT2.S=60675276.63
DUT2.cosDF=-0.007461
DUT2.Zamp=333.50
DUT2.theta=90.43
DUT2.Rs=-269.93
DUT2.Rx=-195.86
DUT2.Z=-465.79

结果2:
解算DUT
DUT.Zr=2.41
DUT.Zx=-334.95
DUT.Theta=-89.59
DUT.Z=334.96
DUT.D=0.007205
DUT.C=475.14
按P,S方式解算DUT
DUT2.P=-436486.40
DUT2.S=60583965.04
DUT2.cosDF=-0.007205
DUT2.Zamp=334.96
DUT2.theta=90.41
DUT2.Rs=-327.29
DUT2.Rx=71.28
DUT2.Z=-256.01

结果3:
解算DUT
DUT.Zr=2.25
DUT.Zx=-334.84
DUT.Theta=-89.61
DUT.Z=334.85
DUT.D=0.006726
DUT.C=475.30
按P,S方式解算DUT
DUT2.P=-407343.13
DUT2.S=60568123.57
DUT2.cosDF=-0.006725
DUT2.Zamp=334.85
DUT2.theta=90.39
DUT2.Rs=72.12
DUT2.Rx=326.99
DUT2.Z=399.11 可以看到
电容值 DUT.C=475.30nF
阻抗DUT.Z=DUT.Zamp=334.85
相位角 DUT.Theta=-89.61 约等于DUT2.theta=90.39.
D值 DUT.D=0.006726, 约等于 DUT2. cosDF = 0.006725
0.47uF实测值:Z=331;D=0.00437, C=480nF
当前仍有一些问题:例如电压相位角会从-178变动到+178,导致阻抗的相位角从-89变动到+90.这个只需加以判定再修正相位角即可.

qwe2231695 发表于 2023-4-29 23:51:26

期待完整开源

kitten 发表于 2023-4-30 16:24:46

开源就不用了,搞个套件就行了{:titter:}

蚁族 发表于 2023-6-21 09:47:34

最小精度是多少,有咩有测试过

lizengmao 发表于 2023-6-23 20:01:38

目前我做了一个小PCBA,加入了自动平衡电桥和PGA,使用STM32的PWM经过硬件BPF后得到正弦波,初步使用FFT进行测试,效果还可以。但是测量100Kohm以上的电阻时,由于电流太小,即使使用100k的反馈电阻,得到的电流波形也是有很大的噪音。经过低通滤波器后仍然不能准确的获取有效值。
下一步尝试不使用FFT,改为使用下IQ的方式进行计算。但是对IQ的解调方式仍不熟悉。有过相关经验的朋友可以提出好的建议。
当前激励信号0.3VRMS kHz正弦波
当前PGA:
电压通道:3x固定增益+5xPGA+10xPGA+100xPGA。电流通道反馈电阻(100,11k,10k,100k)四种+5xPGA。
页: [1]
查看完整版本: [已解决]求助:DIY LCR Meter时,测试电容发现测到的DUT相位角不稳定