■ 简介
AD5933阻抗变换模块 是基于AD(ANALOG DEVICES)公司 的 AD5933 芯片的阻抗转换器、网络分析仪。此外,AD公司还提供了一款小型的 AD5934 。
▲ AD5933阻抗转换器
该模块在TMALL上的零售价格为¥188。
D5933是一款高精度的阻抗转换器系统解决方案,片上集成频率发生器与12位、1 MSPS的模数转换器(ADC)。用频率发生器产生的信号来激励外部复阻抗,外部阻抗的响应信号由片上ADC进行采样,然后由片上DSP进行离散傅里叶变换(DFT)处理。DFT算法在每个频率上返回一个实部®数据字和一个虚部(I)数据字。然后根据实部数据字与虚部数据字可计算出待测器件的阻抗值与相位值。
- 模块特性
- 可编程输出峰峰值激励电压,输出频率高可达100 kHz
- 可编程频率扫描功能和串行I2C®接口
- 频率分辨率:27位(<0.1 Hz)
- 阻抗测量范围:1 kΩ至10 MΩ
- 利用附加电路可测量100Ω至1 kΩ阻抗
- 内部温度传感器(±2°C)
▲ AD5933内部结构图
01模块基本分析
1.I-V测量反馈电阻
从购买的网站上并没有给出该模块以下信息:
- RFB 的选择与大小:因为在模块中只有一个VIN,并没有显示出RFB的接口大小。
这部分将模块上的金属壳顶盖打开,便可以看到其中的内部主要电路。
▲ 将模块金属屏蔽盒打开之后,内部结构
通过测量,在AD5933上边的电阻(22k欧姆)是连接在RBF(PIN4)和VIN(PIN5)之间的电阻。这说明反馈的电阻为22kΩ。
▲ RFB电阻为22kΩ
2.模块工作电源
模块供电端口的电源为+5V。内部有AS1117-3.3V线性稳压电源。AD5933工作电源为3.3V。
3.模块运放接口电路
在金属屏蔽盒中包括有一个基于 AD8606 精密运放接口电路。
▲ 内部辅助电路
这部分电路与手册中的参考辅助电路结构很相似。是在了AD5933的输出和输入部分增加了基于AD8606的运放缓冲。提高了电路对了的驱动能力。
▲ 手册中的参考辅助电路
启动这部分电路,需要将内部电路的几个焊接点进行重新调整,将这部分的电路接入测量电路中。
02测试电路
1.硬件设计1
由于AD5933使用I2C总结接口,利用STC8G1K08所提供的I2C做接口芯片,完成与PC即连接。
▲ 测试单片机STC8G1K08原理图
使用快速制版,设计实验电路板并进行焊接。集成在面包板上完成实验。
▲ 实验电路板
2.软件设计2
工作频率:35MHz
STC8G1K软件设置:
- STC8G.H: #define PACKAGE_SOP8 1, #define I2C_EN 1
▲ 斜口钳:28元人民币
03实验测试
1.AD5933基础测试
- 供应工作电压+5V,测量此时工作电流:5mA。
- 测量芯片周围的工作电压:3.296V;
- 测量内部AD8606运放的工作电压:3.296V;两个运放的静态输出为1.64V。
▲ AD5933通电
2.I2C总线测试
下图显示连接AD5933的I2C总结对8G1K的I2C总线输出波形的影响:
- 数据线的幅度在连接AD5399的时候降低到了3.3V。数据线的幅值没有改变;
- 数据线在连接AD5933的时候,被主动拉高的一些变化。
▲ I2C总线波形测试
3.建立AD5933相关的模块
-
建立AD5933.H, AD5933.C的相关模块并定义一系列的相关底层函数
相应的模块参见工程文件中的相应的文件。 -
基于串口的命令接口
这部分在serialtxt.c文件中实现。具体命令参加下面程序:
else IFARG0("setp") {sscanf(SDA(1), "%x", &nNumber);AD5933SetPointer((unsigned char)nNumber);printf("Set Pointer:%d\r\n",nNumber);
} else IFARG0("readb") {sscanf(SDA(1), "%x", &nNumber);AD5933ReadBlock((unsigned char)nNumber, ucDim);for(i = 0; i < nNumber; i ++) {printf("%02bx ", ucDim[i]);}if(STD_NUM == 2) printf("\r\n");
} else IFARG0("readt") {AD5933WriteByte(0x80, 0x90); WaitTime(10);AD5933SetPointer(0x92);AD5933ReadBlock(2, ucDim);nNumber = ucDim[0];nNumber = nNumber * 256 + ucDim[1];printf("%d\r\n", nNumber);
} else IFARG0("reada") {AD5933SetPointer(0x80);for(i = 0; i < 0x18; i ++) {printf("%0bx ", AD5933ReadByte());}if(STD_NUM == 1) printf("\r\n");
} else IFARG0("writeb") {sscanf(SDA(1), "%x", &nNumber);ucAdd = (unsigned char)nNumber;sscanf(SDA(2), "%x", &nNumber);i = (unsigned char)nNumber;AD5933WriteByte(ucAdd, i);
} else IFARG0("writei") {sscanf(SDA(1), "%x", &nNumber);ucAdd = (unsigned char)nNumber;sscanf(SDA(2), "%x", &nNumber);AD5933SetPointer(ucAdd);AD5933WriteBlock(2,(unsigned char *)&nNumber);
} else IFARG0("writel") {sscanf(SDA(1), "%x", &nNumber);sscanf(SDA(2), "%lx", &lnNumber);AD5933SetPointer((unsigned char)nNumber);AD5933WriteBlock(3, ((unsigned char *)&lnNumber) + 1);
} else IFARG0("readd") {AD5933SetPointer(0x94);AD5933ReadBlock(4, ucDim);printf("%0bx %0bx %0bx %0bx", ucDim[0], ucDim[1], ucDim[2], ucDim[3]);if(STD_NUM == 1) printf("\r\n");
} else IFARG0("reads") {AD5933SetPointer(0x8f);printf("%0bx", AD5933ReadByte());if(STD_NUM == 1) printf("\r\n");
}
04PYTHON程序测试
建立 ad5933.py,利用MCU的接口命令,完成对AD5933的操作。
1.读取温度
- ad5933temperature
Control registger(0x80) = 0x90
读取:0x92,0x93:
数值处理:将读取的数值乘以 0.03125.
▲ 温度数值与转换结果之间的关系
下面的曲线是从AD5933内部读取的数值,在此过程中,使用手指触摸芯片,可以引起芯片的温度上下波动。所以芯片内的温度传感器对于环境温度还是非常敏感的。
▲ 从AD5933内部读取的温度曲线
▲ 处于静止状态下,读取的AD5933内部温度传感器的曲线。
2.设置输出激励信号
- setsweep(startf, incf, num, oscf)
如下是设置输出频率为30kHz, 幅值为2Vp-p的波形。
实际测量的参数:频率:29.608; 电压RSM= 0.695V。
设置输出激励电压
- 频率的偏差
设置100kHz, 实际使用DM3068输出的频率为98.695kHz。原来假定的频率 f 0 o s c = 16.776 M H z f_{0osc} = 16.776\,\,MHz f0osc=16.776MHz。经过修规:
经过上述修正之后, 实际输出聘用:99.993MHz。
3. 使用模块的AD8606缓冲
将模块的运放缓冲连接上。可以增加模块对于低电阻的测量能力。相关的实验在下一次的时候继续验证。
※ 结论
通过制作基于STC8G1(SOP8)的I2C接口板,可以使用上位机通过WiFi-UART来控制和读取AD5933的内部寄存器。完成信号的输出和测量结果。
更加详细的测量和应用。需要按照使用手册的要求进行标定和测量。相关的应用在后面的实验中陆续给出。
- 相关的交叉引用文档
//==============================================================================
// PROCESS THE DEBUG BUFFER
//------------------------------------------------------------------------------
void SerialDebugProcessBuffer(void) {unsigned int nNumber;unsigned char ucDim[8], i, ucAdd;unsigned long lnNumber;SerialDebugBuffer2Argument();if(g_ucSDANumber == 0) return;if(strcmp("hello", (char *)STD_ARG[0]) == 0)printf("%s is ready !\r\n", VERSION_STRING);else IFARG0("setp") {sscanf(SDA(1), "%x", &nNumber);AD5933SetPointer((unsigned char)nNumber);printf("Set Pointer:%d\r\n",nNumber);} else IFARG0("readb") {sscanf(SDA(1), "%x", &nNumber);AD5933ReadBlock((unsigned char)nNumber, ucDim);for(i = 0; i < nNumber; i ++) {printf("%02bx ", ucDim[i]);}if(STD_NUM == 2) printf("\r\n");} else IFARG0("readt") {AD5933WriteByte(0x80, 0x90); WaitTime(10);AD5933SetPointer(0x92);AD5933ReadBlock(2, ucDim);nNumber = ucDim[0];nNumber = nNumber * 256 + ucDim[1];printf("%d\r\n", nNumber);} else IFARG0("reada") {AD5933SetPointer(0x80);for(i = 0; i < 0x18; i ++) {printf("%0bx ", AD5933ReadByte());}if(STD_NUM == 1) printf("\r\n");} else IFARG0("writeb") {sscanf(SDA(1), "%x", &nNumber);ucAdd = (unsigned char)nNumber;sscanf(SDA(2), "%x", &nNumber);i = (unsigned char)nNumber;AD5933WriteByte(ucAdd, i);g_ucTime0MS = 0;g_ucTime0MS100 = 0;if(STD_NUM > 3) {for(;;) {AD5933SetPointer(0x8F); // Set the pointer to status register address:0x8FucAdd = AD5933ReadByte();if(ucAdd & 0x2) break;}i = g_ucTime0MS;ucAdd = g_ucTime0MS100;AD5933SetPointer(0x94);AD5933ReadBlock(4, ucDim);nNumber = ucDim[0];nNumber = (nNumber << 8) + ucDim[1];printf("%d ", nNumber);nNumber = ucDim[2];nNumber = (nNumber << 8) + ucDim[3];printf("%d ", nNumber); nNumber = ucAdd;nNumber = (nNumber << 8) + i;printf("%d\r\n", nNumber);}} else IFARG0("writei") {sscanf(SDA(1), "%x", &nNumber);ucAdd = (unsigned char)nNumber;sscanf(SDA(2), "%x", &nNumber);AD5933SetPointer(ucAdd);AD5933WriteBlock(2,(unsigned char *)&nNumber);} else IFARG0("writel") {sscanf(SDA(1), "%x", &nNumber);sscanf(SDA(2), "%lx", &lnNumber);AD5933SetPointer((unsigned char)nNumber);AD5933WriteBlock(3, ((unsigned char *)&lnNumber) + 1);} else IFARG0("readd") {AD5933SetPointer(0x94);AD5933ReadBlock(4, ucDim);nNumber = ucDim[0];nNumber = (nNumber << 8) + ucDim[1];printf("%d ", nNumber);nNumber = ucDim[2];nNumber = (nNumber << 8) + ucDim[3];printf("%d", nNumber);if(STD_NUM == 1) printf("\r\n");} else IFARG0("reads") {AD5933SetPointer(0x8f);printf("%0bx", AD5933ReadByte());if(STD_NUM == 1) printf("\r\n");} else IFARG0("sweep") {i = 0x1;if(STD_NUM > 1) {sscanf(SDA(1), "%x", &nNumber);i = (unsigned char)nNumber;}for(nNumber = 0; nNumber < 10; nNumber ++) {AD5933WriteByte(0x80, i | 0x20);WaitTime(10);for(;;) {AD5933SetPointer(0x8F); // Set the pointer to status register address:0x8FucAdd = AD5933ReadByte();if(ucAdd & 0x2) break;}if((ucAdd & 0x4)) continue;}AD5933SetPointer(0x94);AD5933ReadBlock(4, ucDim);nNumber = ucDim[0];nNumber = (nNumber << 8) + ucDim[1];printf("%d ", nNumber);nNumber = ucDim[2];nNumber = (nNumber << 8) + ucDim[3];printf("%d ", nNumber); lnNumber = 0;for(;;) {AD5933SetPointer(0x8F); // Set the pointer to status register address:0x8FucAdd = AD5933ReadByte();if(ucAdd & 0x4) break;lnNumber ++;if(lnNumber >= 512) break;AD5933WriteByte(0x80, i | 0x30);for(;;) {AD5933SetPointer(0x8F); // Set the pointer to status register address:0x8FucAdd = AD5933ReadByte();if(ucAdd & 0x2) break;}AD5933SetPointer(0x94);AD5933ReadBlock(4, ucDim);nNumber = ucDim[0];nNumber = (nNumber << 8) + ucDim[1];printf("%d ", nNumber);nNumber = ucDim[2];nNumber = (nNumber << 8) + ucDim[3];printf("%d ", nNumber); }printf("\r\n");}else printf("Error command : %s !\r\n", STD_ARG[0]);
}#endif // SERIALTXT_EN
//==============================================================================
// END OF THE FILE : SERIALTXT.C
//------------------------------------------------------------------------------
#!/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
#============================================================
实验电路板AD工程文件:AD\Test\2020\AD5933\AD59338G1K.PcbDoc * ↩︎
下位机软件工程:C51\STC\Test\2020\AD5933\AD59338G1K\AD59338G1K.uvproj ↩︎