【嵌入式实战】基于STM32与AD698的RVDT高精度角位移测量系统设计与验证

发布时间:2026/6/27 15:46:25

【嵌入式实战】基于STM32与AD698的RVDT高精度角位移测量系统设计与验证 1. 项目背景与核心需求为什么选择STM32AD698AD7606这套方案在工业自动化、航空航天、精密机械这些对可靠性要求极高的领域我们经常需要精确测量一个旋转部件的角度。比如飞机油门杆的推拉角度、大型阀门开度的精确控制或者机器人关节的旋转位置。这些场景下传感器不仅要准还得稳要能扛得住温度变化、电磁干扰并且长期工作不出岔子。RVDT旋转变压器式角位移传感器就是应对这类需求的“老兵”它本质上是一个微型的变压器通过原边和副边线圈的电磁耦合变化来反映角度结构坚固寿命超长特别适合恶劣环境。但是RVDT自己不会“说话”。它输出的是两路随着角度变化的正弦Sin和余弦Cos交流信号。我们得有一套电路能把这两路“交流语言”翻译成单片机比如STM32能听懂的“直流数字语言”。这个过程就是信号调理和模数转换。早年做这个电路相当复杂需要自己搭振荡器产生激励信号用精密仪表放大器处理小信号再做相敏检波……一堆分立元件调试起来头大温漂还不好控制。所以当我接到这个高精度角位移测量的项目需求时第一反应就是找高度集成的方案。ADI公司的AD698芯片进入了视线。这家伙简直就是为LVDT/RVDT量身定做的“翻译官”。它把激励信号发生、信号解调、比例计算这些功能全都塞进了一个芯片里外部只需要配几个电阻电容就能输出一个与角度成正比的、漂亮的直流电压。这大大简化了硬件设计也把温度漂移、激励幅度波动带来的误差降到了最低。而AD7606则是我心中同步采样ADC的“瑞士军刀”。8通道、16位分辨率、所有通道同时采样保持这对于需要同时捕捉Sin和Cos信号虽然本项目AD698已处理为单路但多通道优势仍在或者未来做多轴系统来说简直是神器。它的±10V输入范围正好匹配AD698的输出SPI接口和STM32又是绝配。最终我敲定了STM32F103C8T6主控 AD698信号调理 AD7606模数转换这个组合。STM32负责逻辑控制和通信AD698负责把RVDT的“交流密语”翻译成“直流电压”AD7606则负责把这个电压“数字化”送给STM32解算。这个方案在性能、成本和开发难度上取得了很好的平衡。下面我就把自己从硬件焊接、软件调试到问题排查的全过程经验毫无保留地分享出来。2. 硬件设计从原理图到PCB的实战要点硬件是系统的骨架骨架搭得正后面软件才能跑得顺。这一部分我会详细拆解几个关键芯片的电路设计以及我踩过的一些坑。2.1 电源树设计别让供电拖了后腿整个系统的供电需求有点“杂”STM32和数字逻辑部分需要3.3VAD7606需要5V而AD698这颗模拟芯片则需要±15V的双电源才能输出完整的±11V电压摆幅。电源不稳精度全毁。我的方案是外部输入一个24V的直流电源工业现场很常见。先用一颗TPS5430这样的DC-DC降压芯片把24V降到稳定的5V。这颗芯片电流能力够效率也高。得到的5V一路直接给AD7606的模拟部分供电AVCC另一路则通过一颗低压差线性稳压器LDO比如AMS1117-3.3生成纯净的3.3V给STM32和AD7606的数字部分DVCC供电。最关键是±15V的生成。这里我强烈建议使用隔离型的DC-DC模块比如B2415S-2W。直接把24V输入隔离输出15V和-15V。隔离的好处太大了它能将数字地DGND和模拟地AGND的噪声有效隔开防止数字电路开关噪声通过地线串扰到极其敏感的AD698模拟电路里导致输出直流电压上叠加毛刺。很多人在调试时发现输出跳动大问题往往就出在这里——数字地和模拟地直接连在一起了。注意即使使用了隔离电源模拟地AGND和数字地DGND也建议在PCB上通过一个0欧姆电阻或磁珠在单点连接这个连接点通常选在ADCAD7606的接地引脚附近。电源输入端和每个芯片的电源引脚附近一定要放置一个10uF的钽电容或电解电容进行储能再并联一个0.1uF的陶瓷电容进行高频去耦电容要尽可能靠近芯片引脚。2.2 AD698外围电路让“翻译官”精准工作AD698的数据手册写得非常清楚它的核心功能通过几个外部无源元件来配置。这里我以本次实验的3kHz激励频率、3V幅值、250Hz系统带宽为例。激励频率设置频率由电阻R1和电容C1决定公式是Fosc 1 / (R1 * C1)。我选择C112nF要得到3kHz计算出的R1约为27.8kΩ。但手册里提供了一个更优的表格推荐使用10.3kΩ的R1配合12nF的C1实际产生的频率非常接近3kHz且性能更佳。我就直接采用了这个推荐值。系统带宽与输出滤波带宽决定了系统响应速度和对噪声的抑制能力。带宽由C2、C3、C4这三个电容决定。我选择C2C3C4470nF这样设置的带宽约为250Hz对于大多数机械位置测量来说这个响应速度足够了而且能有效滤除高频噪声。输出比例与偏置这是将电压换算为角度的关键。输出公式是Vout (A/B - 0.5) * Iref * R2。其中A/B就是RVDT输出的Sin/Cos比值Iref是芯片内部一个500μA的精密电流源。R2的取值直接决定了输出电压的幅度范围进而决定了角度测量的量程。我最初选用的是6.6kΩ理论上配合我的RVDT能覆盖约±72度的范围。接线方式我的RVDT是四线制正余弦输出型Sin, Sin-, Cos, Cos-。因此我将AD698配置为“四线制”模式Sin接AINSin-接-AINCos接BINCos-接-BIN。注意-AIN和-BIN需要短接并连接到干净的模拟地AGND。2.3 AD7606与STM32的接口确保数据高速稳定读取AD7606有并行和串行两种接口模式。为了节省STM32的IO口我选择了SPI串行模式。接线很简单CS(片选)、SCK(时钟)、DIN(可配置本例未用)、DOUTA(数据输出) 分别接STM32的任意GPIO。BUSY(忙信号) 引脚至关重要它变高表示开始转换变低表示转换完成。我将其连接到STM32的一个外部中断引脚这样可以用中断方式高效地等待转换完成而不是傻傻地延时。CONVST A/B(转换启动) 引脚并联由STM32同一个GPIO控制。给它一个低脉冲所有通道就同时开始采样转换了。RANGE引脚接高电平选择±10V输入范围以匹配AD698的输出。OS[2:0]引脚我设置为“000”即不过采样以获得最高的吞吐率。如果需要更高的有效分辨率可以启用过采样。PCB布局时务必让AD7606靠近AD698的Vout输出引脚模拟走线要短而粗并用地线包围。数字信号线SPI、CONVST等要远离这些模拟走线。3. 软件驱动从SPI读写到角度解算硬件准备就绪后软件就是让系统“活”起来的大脑。STM32的程序主要分为三层底层SPI驱动、AD7606芯片操作、以及顶层的角度计算与通信。3.1 AD7606的SPI驱动编写时序是关键AD7606的SPI时序有它的特殊性参见数据手册时序图不是标准的SPI模式0或3。总结起来就三点CS一直保持低电平在整个读取期间。SCK空闲时为高电平。数据在SCK的上升沿从AD7606移出STM32读取在SCK的下降沿将数据移入如果向AD7606写配置寄存器本例未用。因此我们不能简单使用STM32硬件SPI的某种模式最好用GPIO模拟软件SPI来精确控制时序。下面是我读取8个通道数据的核心函数片段// 假设引脚已定义PIN_CS, PIN_SCK, PIN_DOUT, PIN_BUSY #define CHANNEL_NUM 8 uint16_t AD7606_ReadChannels(uint16_t data[CHANNEL_NUM]) { uint16_t i, j; uint16_t raw_data; // 1. 启动转换给CONVST一个低脉冲 HAL_GPIO_WritePin(PIN_CONVST_GPIO_Port, PIN_CONVST_Pin, GPIO_PIN_RESET); delay_us(1); // 保持低电平至少25ns这里1us足够 HAL_GPIO_WritePin(PIN_CONVST_GPIO_Port, PIN_CONVST_Pin, GPIO_PIN_SET); // 2. 等待转换完成BUSY变低 while(HAL_GPIO_ReadPin(PIN_BUSY_GPIO_Port, PIN_BUSY_Pin) GPIO_PIN_SET); // 3. 拉低CS开始读取 HAL_GPIO_WritePin(PIN_CS_GPIO_Port, PIN_CS_Pin, GPIO_PIN_RESET); // 4. 循环读取8个通道每个通道16位 for(i0; iCHANNEL_NUM; i) { raw_data 0; for(j0; j16; j) { HAL_GPIO_WritePin(PIN_SCK_GPIO_Port, PIN_SCK_Pin, GPIO_PIN_RESET); // SCK下降沿 delay_us(1); // 保持时间 // 在SCK低电平时数据是稳定的此时读取 if(HAL_GPIO_ReadPin(PIN_DOUT_GPIO_Port, PIN_DOUT_Pin) GPIO_PIN_SET) { raw_data | (0x8000 j); // 注意数据是MSB先出 } HAL_GPIO_WritePin(PIN_SCK_GPIO_Port, PIN_SCK_Pin, GPIO_PIN_SET); // SCK上升沿AD7606移出下一位 delay_us(1); } data[i] raw_data; // 存储原始16位数据 } // 5. 读取完成拉高CS HAL_GPIO_WritePin(PIN_CS_GPIO_Port, PIN_CS_Pin, GPIO_PIN_SET); return 0; }3.2 数据转换与角度解算从数字码到实际角度AD7606读回来的data[0]假设Vout接在通道1是一个16位的补码整数范围是-32768到32767对应着-10V到10V的模拟输入。第一步换算成电压值。float voltage; voltage (data[0] / 32768.0f) * 10.0f; // 换算为实际电压值单位V第二步利用AD698公式解算角度。根据AD698的数据手册其输出电压Vout (A/B - 0.5) * Iref * R2。其中A/B Sinθ / Cosθ tanθ。Iref是内部500μA电流源。所以我们可以反推出#define IREF (500e-6f) // 500μA #define R2 (6600.0f) // 6.6kΩ float ratio, angle_rad, angle_deg; // 计算 A/B 比值 ratio (voltage / (IREF * R2)) 0.5f; // 计算角度弧度 angle_rad atanf(ratio); // 注意这里ratio就是tanθ所以直接求arctan // 转换为度 angle_deg angle_rad * 57.2957795f;这里有个非常重要的点AD698的输出公式中(A/B - 0.5)项意味着当A/B0.5即Sin/Cos0.5θ约26.6度时Vout为0。这个0.5是芯片设计的偏置。而我们解算时ratio (Vout/(Iref*R2)) 0.5正好把这个偏置加回去得到正确的tanθ值。很多初学者直接对Vout求arctan结果当然是错的。3.3 串口输出与上位机验证为了实时观察数据我将解算出的angle_deg通过STM32的串口借助CH340芯片发送到电脑。用串口助手或者自己写个简单的Python/Matlab上位机都能接收并绘制曲线。这是调试阶段最直观的手段能立刻看到角度变化是否平滑响应是否及时。4. 调试与问题深挖理论与现实的碰撞系统搭起来代码跑起来只是第一步。真正的功夫都在调试里。我遇到了几个典型问题它们的解决方法对嵌入式模拟系统设计很有参考价值。4.1 现象角度范围只有±64度而非理论±72度这是最让我困惑的一个问题。根据公式选用R26.6kΩ在±10V输入范围内理论角度范围应该是arctan(10V / (500μA * 6.6kΩ))约等于72度。但实际测量中当RVDT旋转到大约64度时AD7606读取的电压就已经接近10V饱和了。排查过程检查硬件首先用万用表测量AD698的Vout引脚电压在极限位置时确实达到了9.8V左右接近电源轨±11V说明AD698输出正常且未饱和。检查RVDT本身查阅RVDT的数据手册发现其线性范围Linear Range一项明确标注为±65度。恍然大悟传感器本身就有物理限制超过这个范围Sin/Cos信号的变化就不再是线性的导致A/B比值失真。AD698只是忠实地放大了这个失真的比值所以输出电压在64度左右就达到了最大。调整R2验证为了匹配RVDT的±65度线性范围我反推了所需的R2值。目标是在θ65度时Vout接近10V。由tan(65°) ≈ 2.1445代入公式10V (2.1445 - 0.5) * 500μA * R2计算得R2 ≈ 10.2kΩ。我将电路中的R2换为10kΩ电阻后实测角度范围正好覆盖了RVDT的整个线性区间分辨率也得到了充分利用。关键教训传感器数据手册是圣经芯片外围电路的计算必须基于传感器自身的实际特性参数尤其是线性范围、灵敏度等。理论计算是起点但必须用实测来验证和校准。4.2 现象输出角度存在抖动或毛刺上电后角度值基本正确但会在一个很小的范围内比如0.1度频繁跳动。排查与解决电源噪声用示波器查看AD698的±15V电源和AD7606的5V电源发现上面有几十mV的高频纹波。这是开关电源的典型噪声。我在电源入口处增加了π型滤波电路电感电容并在每个芯片的电源引脚增加了0.1μF和10μF的退耦电容情况改善明显。地线噪声这是更隐蔽的噪声源。我最初为了省事将数字地和模拟地在多处连接形成了一个“地环路”。数字部分STM32、AD7606数字端快速开关的电流会在地线上产生电压波动这个波动直接叠加在了AD698的模拟地上。严格按照“单点接地”原则改造PCB所有模拟器件的地最终汇到一点所有数字器件的地汇到另一点然后用一个0欧姆电阻或磁珠将这两点在AD7606下方连接起来。改造后输出噪声降低了约70%。软件滤波硬件滤波做到位后如果还有微小跳动可以在软件里做平滑处理。我采用了一个简单但有效的一阶滞后滤波低通滤波float filtered_angle 0.9f * filtered_angle 0.1f * new_angle; // 系数可根据需要调整或者使用移动平均滤波。这样处理后显示的角度值就非常稳定了。4.3 激励信号验证用示波器看“心脏”跳动AD698产生的激励信号是驱动RVDT的“心脏”。它的频率和幅度稳定性直接影响测量精度。我用示波器钩在AD698的EXC1和EXC2引脚连接RVDT原边观察到频率为3.062kHz幅度约3Vpp与设计值3kHz 3V基本吻合。小幅偏差源于外部阻容元件的精度。如果这里频率偏差很大或者波形畸变就要回头检查C1和R1的取值、焊接以及电源是否稳定。5. 系统验证与性能评估它到底有多准一切调试完毕后需要对系统进行整体测试评估其静态和动态性能。我制作了一个简单的测试工装可以将RVDT的转轴通过联轴器连接到一个高精度的蜗轮蜗杆旋转台上旋转台的分度精度是0.1度。这样就可以输入一个已知的标准角度来检验系统的输出。静态精度测试从-60度到60度每10度取一个点记录系统输出的角度值。对比标准值计算误差。实测下来在大部分范围内绝对误差小于0.2度。在接近线性区边缘±60度附近误差会稍大达到0.3-0.4度这主要是RVDT自身非线性度增加导致的。这个精度对于多数工业控制场合如阀门开度反馈已经足够。重复性测试将转轴反复旋转到同一个物理位置比如30度记录10次测量值。计算其标准差。我的系统标准差小于0.05度说明重复性非常好这得益于AD698芯片优异的温度稳定性和AD7606的高分辨率采样。动态响应测试用手快速来回旋转RVDT通过串口高速打印数据并在上位机绘制曲线。观察系统输出是否能紧跟物理位置的变化。由于我将AD698的系统带宽设置为250HzAD7606的采样率也足够高系统能够无延迟地跟踪手动快速旋转曲线平滑无台阶。最后我将这套系统集成到一个模拟的油门杆控制台项目中STM32解算出的角度值通过CAN总线发送给主控制器形成了一个完整的闭环位置反馈。经过连续48小时的老化测试角度漂移小于0.1度系统工作稳定可靠。这个从芯片选型、电路设计、编程调试到最终验证的完整过程让我对高精度模拟信号链的设计有了更深的理解也再次体会到在嵌入式硬件开发中数据手册上的每一个参数、PCB上的每一根走线都关乎最终的成败。

相关新闻