■ 前言
在博文 AD5933不同频率下转换结果 中分析了 AD5933阻抗变换模块 使用内部时钟(fosc=16.776MHz)时,测量结果受到采集时间窗口的影响,所能够达到的最低阻抗激励正弦信号频率。
那么,在有些应用中,对象的带宽和工作频率会很低,那么如果能够使用AD5933对这些对象进行测量呢?
虽然,AD5933内部的DSS(数字信号合成 )器可以输出很低的频率,但受到前面提到的数据采集窗口的窗口的影响,所以还是不能够使用。
一种可行的方式就是利用AD5933外部时钟,来降低内部ADC采样的频率,从而可以有效扩大数据采集时间窗口,减少因为 频谱泄漏 对于测量结果的影响。
-
通过实验验证MCLK对于AD5933的影响
-
验证AD5933究竟是否可以达到很低的分析能力?
01使用STC8G1K08的T0输出脉冲信号1,2
在 AD5933阻抗转换器、网络分析仪初步实验 中给出了基于STC8G1K081K(SOP8)的实验电路,完成对AD5933模块的I2C总线命令的控制。实验电路板还包括有T0/T1CLKO管脚输出,这部分可以用来产生AD5933的MCLK的时钟信号。
▲ 设置T1CLKO的STC8G相关寄存器
在STC8G1K08的main程序初始化子程序中,定义如下命令,设置T1CLKO为输出信号。
▲ 实验电路板 STC8G1K08
#define T1CLKO_PIN 5,4
void MainInit(void) {PM_BIDIR(LED);AD5933Init();INTCLKO |= 0x2;PM_PP(T1CLKO_PIN);}
测量P5.4(T1CLKO)管脚的波形如下。频率为: f t 1 = 921.3 k H z f_{t1} = 921.3kHz ft1=921.3kHz。
由于此时T1用于UART1的波特率(460800bps),所以它的频率为921.3Khz。
▲ STC8G1k的P5.4(T1CLKO)管脚的输出波形
02产生输出信号
1.设置输出激励正弦信号
在初始化AD5933中,选择外部CLK。在设置SetSweep的时候,设置参数oscf=0.92。输出3kHz。
ad5933.init(20, 1)
stm32cmd('reada')
startf = 2000
stepf = 100
numf = 10ad5933.setsweep(startf, stepf, numf, oscf=0.9216)
ad5933.sweep(1)
下面是采集到的输出波形。它的频率为3KHz。这说明AD5933的确是按照外部得始终产生激励信号的。
▲ 输出3KHz的正弦波形
2. 测试新的最低工作频率
内部工作频率 f i n = 16.776 M h z f_{in} = 16.776Mhz fin=16.776Mhz时,按照AD5933不同频率下转换结果 中的结果,最低工作频率大约是: f min = 2 k H z f_{\min } = 2kHz fmin=2kHz左右。现在外部时钟频率为: f e x t = 0.9216 M H z f_{ext} = 0.9216MHz fext=0.9216MHz。那么对应的最低工作频率:
下面是在不同的输出工作频率下,测量负载为无穷大时,测到所得到的电流幅度。可以看到在频率大约为110Hz的时候,输出接近于零。这与上述计算结果是相符合的。
▲ 在不同的工作频率下测量结果,此时工作电阻为无穷大
3.修改模块中的耦合电容
使用AD5933上的运放缓冲电路的时候,由于AD5933通过 0.01uF的电容耦合到AD8606运放。当输出频率很低的时候,会极大衰减输出信号。
将该耦合电容修改到20uF;这样对应的截止频率为: C 0 = 20 u F C_0 = 20uF C0=20uF,后期的分压电阻为 R 0 = 10 k Ω R_0 = 10k\Omega R0=10kΩ。后期的截止频率为:
▲ 不同频率下输出激励电压
▲ 不同频率下输出激励电压
从上图来看,输出信号的截止频率大约是10Hz左右。
为了进一步降低截止频率,将原来的分压电压的电阻从原来的22kΩ,修改成200kΩ.
▲ 修改缓冲运放
经过改造之后,重新测量输出电压与激励信号频率之间的关系。可以看到截止频率降低到1Hz左右。
▲ 不同频率输出激励电压幅值
03使用信号源产生工作频率
1.工作时钟频率
使用DS345产生AD5933的工作时钟信号。首先设置输出频率:100kHz, 幅度:Vpp=2V;偏置:1V。
▲ 信号源DS345
由于输出信号是按照负载为50Ω来设定的。带动AD5933工作时,由于负载远远大于50Ω,所以输出的幅值基本上是上述设置两倍。
下图是实际测量DS345输出的时钟信号。Vpp大约为2V,重心偏移量为2V。
▲ 工作时钟信号
通过测试,需要将时钟的幅值设置为峰峰值2V才能够满足触发AD5933的工作。
▲ 设置信号的幅值和波形
如果输入信号超过的3.3V,有可能导致电流回灌。
- 正确的设置方式:Vpp:1.5V,Vbias=1V,方波。
2.测试输出信号频率
在Vin,Vout之间连接 R l o a d = 300 k Ω R_{load} = 300k\Omega Rload=300kΩ。在不同的频率下测量的结果如下图所示。
-
工作频率:0.1MHz
▲ 不同频率下测量的结果
根据在 AD5933不同频率下的转换结果 测量结果,在 f o s c = 16.776 M H z f_{osc} = 16.776MHz fosc=16.776MHz下,频率泄露所引起的最低工作频率为2000Hz。那么工作在 f 1 = 0.1 M h z f_1 = 0.1Mhz f1=0.1Mhz下的最低工作频率为:
从前面的测量结果来看,的确最低的工作频率大约10Hz左右。
(1)工作频率0.01MHz:
下面显示了在不同的频率下的测量结果。
在工作频率为 f o s c = 16.776 M H z f_{osc} = 16.776MHz fosc=16.776MHz下,数据采样频率为1MHz。在工作频率 f 1 = 0.01 M H z f_1 = 0.01MHz f1=0.01MHz时,对应的数据采样频率为:
▲ 不同频率下测量的结果
▲ 普通频率下的测量结果
下图显示了在596MHz下,对应的采集到的数据。其中存在两个奇怪的地方:
-
测量结果中存在一个线性相位
这可能是由于转换过程存在一个特定的时间延时 t A D t_{AD} tAD。从图像中可以看到该延迟大约是2ms。也就是在1000Hz的时候,相位相差了2个 2 π 2\pi 2π。 -
当频率大于550Hz长辈,结果中存在噪声
由于采集频率为596Hz,所以当信号的频率超过500Hz之后,实际上信号已经处于欠采样过程。所以这个过程存在着比较明显的噪声。
▲ 普通频率下的测量结果
(2)工作频率:0.02MHz:
从测量结果来看:
- 存在着 一个1ms左右的延迟
可以猜测,固定的延迟大约等于两个工作时钟信号周期。
▲ 普通频率下的测量结果
下图显示了最低的工作频率大约在2.5Hz。
▲ 普通频率下的测量结果
(3)工作频率:0.05MHz
最低的工作频率大约E座5.5Hz.
▲ 普通频率下的测量结果
3. AD5933的工作频率对结果的影响
-
工作频率:0.01MHz
▲ 不同频率下的测量结果
-
工作频率:0.02MHz
▲ 不同频率下的测量结果
-
工作频率:0.05MHz
▲ 不同频率下的测量结果
※ 结论
可以使用外部加入测MCLK信号,来改变AD5933的测量信号频率范围。
输入信号的幅度需要尽可能解决0~3.3V,可以使用正弦波,或者方波信号来驱动MCLK。
- 总结上述测量结果,可以近似得到如下的结果:
- (1)AD5933存在一个固定的延迟 t d e l a y t_{delay} tdelay,这与工作频率 f M C L K f_{MCLK} fMCLK之间的关系为: t d e l a y = 20 f M C L t_{delay} = {20 \over {f_{MCL} }} tdelay=fMCL20。
(2) 数据采样频率: f s = f M C L / 16.776 × 1 0 6 H z f_s = f_{MCL} /16.776 \times 10^6 Hz fs=fMCL/16.776×106Hz。 f M C L f_{MCL} fMCL的单位MHz。 输入信号的频率需要小于fs的一半。
(3)最低工作频率: f min = f M C L / 16.776 × 2000 f_{\min } = f_{MCL} /16.776 \times 2000 fmin=fMCL/16.776×2000。 f M C L f_{MCL} fMCL的单位MHz。
(4)测量保证数据精确性,至少在采样数据中,正弦信号的周期:最小5个;最大的周期512(满足采样定理)。因此AD5933的测量信号的频率范围大约是100倍(两个数量级)。
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY -- by Dr. ZhuoQing 2020-06-25
#
# Note:
#============================================================from headm import *
import ad5933
from tsmodule.tsstm32 import *
from tsmodule.tsvisa import *#------------------------------------------------------------
printf('\a')
ad5933.init(2, 1)startf = 5
stepf = 2
numf = 200#------------------------------------------------------------
freqn = ad5933.setsweep(startf, stepf, numf, oscf=1)
#printf(freqn)#------------------------------------------------------------
ad5933.sweep(1)while True:time.sleep(.5)val = stm32val()if val[12] > 0: breakR,I = stm32memo(2)
printf(R, I)#------------------------------------------------------------#f = linspace(startf, startf + stepf * numf, len(R), endpoint=True)
f = freqnA = [sqrt(r**2+i**2) for r,i in zip(R,I)]plt.plot(f, R, label="Real")
plt.plot(f, I, label="Imaginary")
plt.plot(f, A, label='Amplitude')
plt.xlabel("Frequency(Hz)")
plt.ylabel("Value")
plt.grid(True)
plt.legend(loc="upper right")
plt.show()#------------------------------------------------------------
# END OF FILE : TEST1.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# AD5933.PY -- by Dr. ZhuoQing 2020-06-25
#
# Note:
#============================================================from head import *
from tsmodule.tsstm32 import *#------------------------------------------------------------def init(settletime=100, extclock=0):if extclock > 0:stm32cmd('writeb 81 8')else:stm32cmd('writeb 81 0')time.sleep(0.02)stm32cmd('writeb 80 b1') # Enter standby modestm32cmd('writei 8a %x'%settletime)time.sleep(0.02)def temperature():data = stm32cmdata('readt', wait=200)if len(data) > 0:return data[0] / 32else: return 0def setsweep(startf, incf, num=100, oscf=16.557):startn = int(startf * (2**27) / (oscf*1e6/4))incn = int(incf * (2**27) / (oscf*1e6/4))# printff('%x %x %x'%(startn, incn, num))stm32cmd('writel 82 %x'%startn)time.sleep(.02)stm32cmd('writel 85 %x'%incn)time.sleep(.02)stm32cmd('writei 88 %x'%num)time.sleep(.02)# stm32cmd('writeb 81 0') # D3: 0:Internal system clock 1:External
# time.sleep(.02)stm32cmd('writeb 80 b1') # Standbytime.sleep(.02)stm32cmd('writeb 80 11')time.sleep(.02)fdim = []for n in linspace(startn, startn + incn * num, num+1, endpoint=True):fdim.append(n * oscf * 1e6/4/(2**27))return fdimdef startf(resultflag = 0):if resultflag > 0:stm32cmd('writeb 80 21 1')else:stm32cmd('writeb 80 21')def incf(resultflag = 0):if resultflag > 0:stm32cmd('writeb 80 31 1')else:stm32cmd('writeb 80 31')def repeatf(resultflag = 0):if resultflag > 0:stm32cmd('writeb 80 41 1')else:stm32cmd('writeb 80 41')def readdata():return stm32cmdata('readd', wait=100)def sweep(code=0x1):stm32cmd('CLEAR')time.sleep(.02)stm32cmd('sweep %x'%code)#------------------------------------------------------------if __name__ == '__main__':tdim = []for i in range(10):data = temperature()tdim.append(data)time.sleep(.1)printf(tdim)#------------------------------------------------------------
# END OF FILE : AD5933.PY
#============================================================
实验STC8G1K08 Keil工程文件:C51\STC\Test\2020\AD5933\AD59338G1K\AD59338G1K.uvproj ↩︎
实验AD电路工程文件:AD\Test\2020\AD5933\AD59338G1K.SchDoc ↩︎