FDC2214谐振式电容测量:非接触液位与厚面板检测实践

发布时间:2026/11/3 8:24:48
FDC2214谐振式电容测量:非接触液位与厚面板检测实践 我在做非接触式液位和接近检测这类项目时绕不开一个选择要么用专门的电容触摸芯片参数固定、穿透能力有限稍微厚一点的面板就罢工要么自己搭 RC 充放电电路便宜是便宜可温漂和噪声能把人折腾到怀疑人生。后来把目光投向了FDC2214这颗基于 LC 谐振原理的电容数字转换芯片——28 位输出、四通道、窄带测量天生就是为“隔着几毫米甚至十几毫米的材料测微小电容变化”这种活儿准备的。这篇笔记就是我这段时间从选型、画板、调寄存器到现场标定踩出来的完整记录重点讲清楚它为什么这么设计、参数怎么算、坑在哪。不管你是刚拿到评估板的新手还是已经在画第二版板子的老手里面关于谐振回路取值、驱动电流整定和基线跟踪的部分应该都能直接抄去用。1. 需求拆解为什么最后落到这颗芯片上1.1 四类电容测量方案的横向对比做电容测量市面上的路子其实就那么几条选择哪条基本由三个指标决定要测的电容变化量有多大、传感器离芯片有多远、现场电磁环境有多脏。我把自己实际用过或者评估过的方案列了个表方便你直接对号入座。方案典型分辨率穿透厚度抗干扰成本适用场景MCU 自带 RC 充放电几十 fF 到几 pF1~3 mm差极低按键、低成本水位开关专用电容触摸芯片亚 fF带算法3~8 mm中低面板按键、滑条高精度 ΣΔ 电容转换亚 fF取决于前端好高精密位移、压力FDC2214 谐振式几 fF有效值5~20 mm很好中等液位、厚面板接近、材料检测这张表里最关键的差别不在分辨率而在测量带宽。RC 充放电和普通触摸芯片是宽带测量环境里的开关电源噪声、变频器干扰、甚至人手靠近带来的工频耦合全都会进到结果里。FDC2214 把传感器做成一个 LC 谐振回路只有落在谐振频率附近极窄带宽内的信号才被放大和计数带外干扰被电感电容本身滤掉了。这就是它能穿透厚材料还保持稳定的根本原因也是我愿意为它多画几颗外围器件的原因。1.2 谐振式测量的底层逻辑很多人第一次看手册会懵明明是测电容为什么输出的是频率其实这就是个很朴素的物理事实——电感和电容组成并联谐振回路谐振频率由 f 1/(2π√(LC)) 决定。电容变了频率就跟着变而且这个关系是单调的、可解析的。芯片做的事情就是用一个高稳定度的参考时钟去数这个振荡频率数出来的计数值正比于频率再换算回电容就完事了。这个思路的巧妙之处在于它把“测一个几皮法的微小电容”这个难题转换成了“测一个几兆赫兹的频率”这个相对容易的活。频率测量天生抗幅度噪声干扰让波形幅度抖一抖没关系只要过零点还在计数就不受影响。相比之下RC 充放电方案测的是电压到达阈值的时间任何叠加在电压上的噪声都会直接反映到结果里。代价也很明显你得在板子上放一个电感而且这个电感的品质直接决定了整个系统的噪声地板。这一点后面会细说是新手最容易忽略、也最容易翻车的地方。1.3 适用边界哪些活它干得漂亮哪些别硬上先说它擅长的。第一类是非接触液位尤其是那种容器不能开孔、传感器只能贴在外壁的场景塑料桶、亚克力箱、玻璃罐都行。第二类是厚面板接近检测比如设备外壳上隔着一层 8 mm 的 ABS 做手势唤醒普通触摸芯片早就不响应了它还能稳定输出。第三类是材料与形变检测比如薄膜厚度、板材含水率、结构件受力后的微小形变这些本质上都是介电常数或极板间距的微小变化。再说它不适合的。如果你只是想做几个面板按键那用 FDC2214 属于杀鸡用牛刀成本、布板面积、调试时间都不划算专用触摸芯片带现成的阈值算法和防水处理省事得多。如果你要测的电容变化量本身就有几百皮法那也不需要 28 位分辨率普通的电容数字转换芯片足够。还有一个容易被忽略的边界传感器电极必须能形成一个相对明确的参考地。悬浮的、周围全是绝缘材料的电极电荷没有回流路径信号会弱到几乎测不出来这种情况得额外做一块参考电极后面液位案例里会讲。选型时先问自己一句我的电容变化量能不能做到 1 pF 以上能就别纠结分辨率不能再来谈 FDC2214 的 fF 级本事。2. 硬件设计谐振回路是整个方案的地基2.1 电感选型的三个硬指标外围元件里电感是绝对的主角它的三个参数决定了系统的上限我按重要性排个序。第一是自谐振频率SRF。电感不是理想元件它自己带着寄生电容频率高到一定程度就变成电容性了Q 值急剧下降。你的工作频率必须显著低于 SRF我一般要求 SRF 至少是工作频率的 3 倍。举个例子工作频率 5 MHz那选 SRF 在 15 MHz 以上的电感别图便宜拿个 SRF 只有 8 MHz 的装上去振荡幅度怎么调都上不来。第二是Q 值。Q 值决定了谐振峰的尖锐程度也就决定了选择性。Q 值高谐振曲线窄抗干扰强但同时对外部寄生电容也更敏感需要更仔细地做标定。工程上我一般选 Q 在 30 到 60 之间的功率电感太低的选不到好的信噪比太高的对温漂和机械振动过于敏感。第三是直流电阻DCR。DCR 大了会拉低振荡幅度还会带来额外的热噪声。我习惯控制在 0.5 Ω 以内。综合下来18 µH 是个很省心的取值市面上 Q 值和 SRF 都合适的型号多凑谐振频率也方便。10 µH 和 33 µH 也能用具体看你的传感器电容落在什么区间。2.2 谐振频率与传感器电容的取值计算这里要把公式掰开揉碎讲因为取值取错了后面寄存器怎么调都是白费劲。谐振频率 f 1 / (2π√(L × C_total))其中 C_total 是传感器电容加上走线寄生电容加上芯片引脚电容的总和不是你以为的那个传感器电容。这一点极其重要很多人的板子焊好之后频率对不上计算值就是漏了寄生部分。以 L 18 µH 为例我算了几个典型值总电容 C_total谐振频率 f说明10 pF11.86 MHz接近上限寄生影响被放大22 pF7.99 MHz走线短时的常用档33 pF6.53 MHz综合最稳的一档47 pF5.47 MHz长走线、大电极常用100 pF3.75 MHz频率低抗干扰稍弱但更稳我的建议是把工作频率落在 3 MHz 到 8 MHz 之间。低于 3 MHz同样的电容变化引起的频率变化量变小换算回电容时噪声被放大高于 8 MHz走线电感和引脚电容开始显著影响结果标定重复性变差。算完频率还得反推一下灵敏度。频率和电容是平方根关系微分一下得到 dC -2C × (df / f)。这句话翻译成人话就是电容越大、频率越低同样大小的频率波动对应的电容误差就越大。所以在保证振荡稳定的前提下电容取值偏小一点对分辨率有利但太小了振荡能量不足容易受外界扰动停振。这个平衡点33 pF 到 47 pF 之间比较好找。举个具体例子C 47 pF、f 5.47 MHz 时如果读数频率抖动 ±100 Hz换算成电容误差是 2 × 47 pF × 100 / 5.47e6 ≈ 1.7 fF。这个量级已经足够分辨出人手在 10 cm 外的靠近了。2.3 驱动电流的整定别拍脑袋拿波形说话FDC2214 每个通道都有一个驱动电流寄存器取值 0 到 31对应从几十微安到 1.5 mA 左右的激励电流。这个参数设小了振荡幅度不够信噪比差甚至停振设大了辐射增强、功耗上升还可能把芯片自己的输入级推到非线性区。手册给的目标是让传感器引脚上的振荡幅度落在1.2 V 到 1.8 V 峰峰值之间。整定方法很土但很有效先用一个较大的值比如 20让回路起振然后用低电容探头10:1 档探头电容越小越好量 INxA 对地的波形峰峰值再逐步往下调直到幅度落到目标区间。这里有个必须提醒的点探头本身的电容会改变谐振状态。一根普通 10:1 探头的输入电容在 10 pF 量级跟你传感器电容是同一个数量级一碰上去频率就往下掉。所以量幅度可以信量频率千万别信探头读数频率要靠芯片自己读出来的数据算。还有一点经验驱动电流不要卡在临界值上。我一般会在刚好达到 1.5 V 峰峰值的基础上再往上加一档留出余量。因为温度变化、传感器老化、装配公差都会让回路参数漂一点卡太紧的话冬天在室外可能就停振了。2.4 走线、接地与屏蔽层的处理这部分是纯经验手册上写得比较原则实际布板时全是细节。走线要短、要粗从芯片引脚到电感的这一段最好控制在 10 mm 以内。传感器到电感的连线可以长一些但这段线本身就是个电容会算进 C_total 里所以长度要固定不能这批板子 20 mm、那批板子 50 mm否则标定参数没法复用。这段线也不要和任何数字信号线并行尤其是 I2C 的时钟线和开关电源的走线平行超过 5 mm 就该考虑加地线隔开了。接地要分清模拟地和数字地。芯片的电源引脚旁边必须有 0.1 µF 加 10 µF 的组合去耦0.1 µF 越靠近引脚越好。地平面不要被分割得七零八落但传感器正下方那块地要挖空否则传感器对地的电容会把你想要的信号淹没掉——这就是所谓的 keep-out 区一般要求传感器电极投影范围内不留铜。屏蔽层是进阶玩法。当传感器必须贴近干扰源或者需要做很长的引线时可以在传感器背面加一层屏蔽铜箔接到一个“护环驱动”信号上。FDC2214 本身没有内置的屏蔽驱动器得自己用一颗高带宽运放搭电压跟随器输入取自传感器信号的衰减分压输出驱动屏蔽层让屏蔽层和传感器同电位这样屏蔽层对传感器的电容就被“中和”掉了。这个方案有效但对运放的带宽要求高至少要覆盖工作频率的几倍布板不好还容易自激。预算有限、干扰不极端的场合我更推荐老老实实做好 keep-out 和局部接地环别一上来就上运放。一句大实话谐振回路的布板质量比后面写的所有软件算法都重要。硬件底子差算法只能救回来一点点。3. 固件实现从寄存器到可用数据3.1 上电初始化与身份校验上电第一件事不是急着写配置而是先确认通信通、芯片对不对。FDC2214 的 I2C 从机地址由 ADDR 引脚决定接地是 0x2A接电源是 0x2B均为 7 位地址。上电后先读制造商 ID 寄存器正常应读到 0x5449再读器件 ID2214 这一档是 0x3055。这两个值对不上后面的活全是白搭所以务必先卡这一关。确认身份之后发一次软复位往复位寄存器写 0x8000然后至少等 1 ms 让内部逻辑稳定。这一步很多人省掉结果从上一轮掉电残留的状态里启动出现各种莫名其妙的现象。#define FDC_ADDR 0x2A #define REG_MANUF_ID 0x16 #define REG_DEVICE_ID 0x17 #define REG_RESET 0x11 int fdc_init(void) { uint16_t id; if (i2c_read16(FDC_ADDR, REG_MANUF_ID, id) ! 0) return -1; if (id ! 0x5449) return -2; /* 制造商 ID 不对先查接线 */ if (i2c_read16(FDC_ADDR, REG_DEVICE_ID, id) ! 0) return -1; if (id ! 0x3055) return -3; /* 器件型号不对 */ i2c_write16(FDC_ADDR, REG_RESET, 0x8000); delay_ms(2); /* 复位后留足稳定时间 */ return 0; }3.2 时钟分频、转换时间与采样率芯片内部有一个高频主时钟通过每个通道的分频寄存器得到参考频率 f_REF再用它去数传感器频率。分频寄存器里有两个字段传感器频率分频和参考频率分频。绝大多数场景下传感器分频取 1参考分频也取 1此时换算关系最干净f_sensor f_REF × DATA / 2^28如果你改动了分频系数记得按手册把系数乘回去这一步错了会导致算出来的电容差一个固定倍数而且看起来“挺稳定”特别容易骗过人。转换时间决定了采样率公式是t_conv (SETTLECOUNT × 16 RCOUNT × 16 4) / f_REF其中 SETTLECOUNT 是建立时间计数RCOUNT 是转换计数。以 f_REF 40 MHz、两者都取 1024 为例算下来 t_conv (16384 16384 4) / 40e6 ≈ 819 µs单通道约 1220 次每秒四通道轮询就是 305 次每秒。这个速率对液位检测绰绰有余对快速手势识别就偏慢了需要把计数值降下来。这里有个坑建立时间计数不能无限压小。手册对它有下限约束跟分频系数和谐振频率都有关系低于下限读数会明显不稳。我一般直接给 0x0400除非明确要拉高采样率才去算最小值。/* 四通道轮询每通道建立与转换计数都取 1024 */ static void fdc_config_channels(void) { for (int ch 0; ch 4; ch) { i2c_write16(FDC_ADDR, 0x04 ch, 0x0400); /* SETTLECOUNT */ i2c_write16(FDC_ADDR, 0x00 ch, 0x0400); /* RCOUNT */ i2c_write16(FDC_ADDR, 0x08 ch, 0x1001); /* 分频都为 1 */ } }3.3 自动扫描配置与数据读取多路复用寄存器决定扫哪些通道、按什么顺序扫、去毛刺滤波器的带宽取多少。自动扫描打开后芯片会按顺序依次转换每个通道转换完成都会在状态寄存器里置位同时可以通过中断引脚通知主控。#define REG_CONFIG 0x0E #define REG_MUX_CONFIG 0x10 #define REG_STATUS 0x0C #define REG_DATA_CH0 0x18 static void fdc_start_scan(void) { /* 唤醒并使能驱动电流寄存器生效 */ i2c_write16(FDC_ADDR, REG_CONFIG, 0x0100); /* bit15 自动扫描使能bits14:1301 表示四通道顺序扫描 bits10:8100 表示去毛刺带宽取 10 MHz 档 */ i2c_write16(FDC_ADDR, REG_MUX_CONFIG, 0xA400); } /* 读某个通道的 28 位结果低地址存高 16 位高地址存低 12 位 */ uint32_t fdc_read_channel(uint8_t ch) { uint16_t msb, lsb; uint16_t base REG_DATA_CH0 ch * 2; i2c_read16(FDC_ADDR, base, msb); i2c_read16(FDC_ADDR, base 1, lsb); return ((uint32_t)msb 12) | (lsb 0x0FFF); }去毛刺带宽的选择要跟你的谐振频率匹配3 MHz 档适合 1 MHz 以下的传感器频率10 MHz 档适合 3 到 8 MHz33 MHz 档留给更高频率的场景。选低了会把有效信号滤掉选高了噪声进来别嫌麻烦按实际频率挑。3.4 DATA 到电容值的换算链路这一步是整个固件里最容易出错的地方我把它拆成三级。第一级计数值转频率。f_sensor f_REF × DATA / 2^28。2^28 就是 268435456用整型算要小心溢出用浮点或者 64 位整型。第二级频率转总电容。C_total 1 / (L × (2πf)²)。这一步注意单位电感用亨利频率用赫兹算出来是法拉。第三级总电容转传感器电容。C_sensor C_total − C_parasitic。那个寄生值不是算出来的是标定出来的让传感器处于已知的“空载”状态读一组数据算出总电容然后再放一个已知电容比如并一只 10 pF 的 NP0 电容读一组两者的差值就是灵敏度系数据此反推空载时的寄生量。#define L_HENRY 18e-6f #define F_REF_HZ 40e6f float fdc_data_to_cap(uint32_t data) { float f F_REF_HZ * (float)data / 268435456.0f; float w 2.0f * 3.14159265f * f; return 1.0f / (L_HENRY * w * w); /* 单位法拉 */ }这里顺便说个实测经验算出来的总电容往往比你用手持电容表量的传感器电容大好几皮法这个差值就是走线、引脚、焊盘的贡献属于正常别急着怀疑公式。真正要警惕的是同一个传感器在不同板子上算出来的寄生量差很多那说明布板一致性有问题量产会很难受。3.5 基线跟踪与温漂抑制任何一个电容测量系统只要环境温度变了几个摄氏度基线就会漂。漂移来源包括电感的温度系数、板材介电常数的温度系数、传感器电极的热胀冷缩。指望硬件完全消除不现实软件上必须做基线跟踪。我用的是一种非对称的指数加权跟踪正常情况下基线缓慢跟随当前值防止长期漂移把检测点带偏一旦检测到明显的目标事件值突变超过阈值就冻结基线避免把目标信号吸进基线里。系数设置上上升沿跟得快一点响应温度上升下降沿跟得慢一点实测能兼顾抗漂移和抗误触发。/* 基线跟踪a_slow 用于平稳期a_fast 用于快速跟随 */ static float baseline 0.0f; static const float a_slow 0.001f; static const float a_fast 0.02f; void baseline_update(float raw, float event_threshold) { float diff raw - baseline; if (diff event_threshold || diff -event_threshold) { return; /* 判定为目标事件冻结基线 */ } float a (diff 0) ? a_fast : a_slow; baseline a * diff; }如果传感器工作在温度跨度很大的环境还可以用第二通道接一个参考电极这个电极只感受环境温湿度、不感受目标用它的变化量去补偿主通道。这是差分思路的软件版效果比纯算法好代价是多一路通道和一块电极。4. 实测案例塑料桶外贴式液位检测4.1 电极设计与电容变化量估算场景是一个壁厚 3 mm 的塑料桶桶身不能开孔要求从外侧测液位量程 200 mm精度目标是 2 mm。做法是在桶外壁贴一片铜箔作为传感器电极高度覆盖整个量程宽度 50 mm同时在铜箔下方、贴着桶底的位置贴一圈接地铜箔作为参考地。先估算电容变化量。电极面积按 0.01 m² 算介质是 3 mm 厚的塑料相对介电常数取 2.3水相当于一个移动的接地极板。满液位时电极正对水的部分形成一个平行板电容C ε₀ × ε_r × A / d 8.854e-12 × 2.3 × 0.01 / 0.003 ≈ 68 pF空液位时电极对地只有边缘场耦合实测在 3 pF 到 5 pF 之间。也就是说满量程的电容变化有 60 pF 以上平均每毫米液位对应约 0.34 pF。相比之下前面算的系统噪声在 1 fF 量级理论上分辨率能到零点几毫米实际受基线漂移限制稳定在 1 mm 左右满足要求。有一点必须强调水必须有一个接地回路。如果桶放在木桌上、周围全绝缘那水的电位是浮动的电容变化会小很多信号可能只有几百飞法测起来非常吃力。解决办法就是在桶底或者桶侧下方贴一圈接地铜箔人为造一个参考地。这一步做了和没做实测信号幅度差 5 倍以上。4.2 实测噪声与实际分辨率空桶静止状态下连续采 500 个点观察频率读数。实测峰峰值抖动约 180 Hz标准差 42 Hz。当前工作频率 5.1 MHz换算成电容是 2 × 47 pF × 42 / 5.1e6 ≈ 0.77 fF标准差。这个数值跟理论估算基本吻合。再灌水做动态测试以 10 mm/s 匀速上升采样率 300 Hz记录整个上升过程。曲线整体线性度不错两端接近空和接近满略有弯曲原因是边缘场效应——液面接近电极端部时电场分布不再是理想的平行板。这段非线性可以用分段线性拟合修正我用三个折点做插值全量程误差压到 1.5 mm 以内。顺便记录一下不同驱动电流下的噪声表现驱动电流设在 12 档时峰峰值抖动 300 Hz加到 18 档降到 180 Hz再加到 24 档噪声不再明显下降反而因为幅度过大引入了轻微的非线性。所以最终定在 18 档这个“噪声曲线拐点”是找驱动电流的实用判据比死记手册的目标幅度更好用。4.3 标定与上线前的自检清单标定流程我固化成四步每次改板或者换传感器都走一遍。第一步空载采集。容器清空静置 30 秒采集 1000 点取均值和标准差均值作为零点三倍标准差作为噪声门限。第二步满量程采集。灌满到标称最高液位同样采集 1000 点得到满量程对应的计数值。第三步中间点校验。灌到 25%、50%、75%分别采集检查线性度非线性超过 2% 就要考虑加折点。第四步温漂测试。这个最容易被跳过也最容易出问题。把设备放到高温环境里跑两小时再拿回常温看基线回到什么位置。如果回不去说明基线跟踪参数需要调整或者电感的温度系数太大该换料了。上线前我还会过一个清单通信是否稳定连续跑 24 小时无 I2C 错误、中断是否可靠不能靠轮询兜底、断电重启后零点是否一致、传感器线缆长度变化后是否需要重新标定、防护涂层会不会影响介电常数。这几条挨个过一遍能挡掉大部分现场问题。5. 常见问题与排查实录5.1 通信与初始化阶段的坑I2C 完全无应答先量三样东西供电是不是 3.3 V这颗芯片不支持 5 V、上拉电阻装了没有4.7 kΩ 起步、ADDR 引脚电平对不对。这三样都对还不行就换一块板子试排除焊接问题。我遇到过一次是 ADDR 引脚虚焊电平悬空时好时坏折腾了半天。能读到 ID 但读出来全是 0八成是没退出休眠或者没使能驱动电流。配置寄存器里有一位是传感器激活选择只有把它置位驱动电流寄存器才真正生效。另外多路复用寄存器如果