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

发布时间:2026/11/3 8:24:47
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;再读器件 ID,2214 这一档是 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:13=01 表示四通道顺序扫描, bits10:8=100 表示去毛刺带宽取 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 MHz,33 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,八成是没退出休眠或者没使能驱动电流。配置寄存器里有一位是传感器激活选择,只有把它置位,驱动电流寄存器才真正生效。另外多路复用寄存器如果