
前陣子接了一個需求做一個非接觸式金屬接近檢測要求隔著一層塑料外殼判斷有沒有金屬物體靠近最好還能順帶做個簡單的距離趨勢判斷。我的第一反應是用專用電感數字轉換器芯片但從選型、采購到調參折騰了兩輪問題不斷。后來我拿起手邊一片 PSoC 4200 評估板花了一個下午把 Inductive Sensing 的原理驗證跑通了再往后整個方案都遷移到了 PSoC MCU 上。借著這篇博客我把從原理到實戰的完整過程整理出來如果你也在做金屬檢測、蓋子開合判斷、液位檢測或旋鈕位置識別而且不想在 BOM 里多塞一顆專用芯片這篇內容應該能幫你節省大量調試時間。做電感感應的核心一句話讓 MCU 自己產生一個激勵信號驅動一個 LC 回路然后測量金屬靠近時這個回路品質因數Q 值的變化。PSoC 4、PSoC 6 內部自帶可編程模擬前端有比較器、DAC、SAR ADC、TCPWM 這些資源關鍵是這些模擬模塊可以通過片上布線任意互連不需要外部運放、比較器、整形電路。這顛覆了我過去對單片機做模擬測量的認知——整體思路從我要在 PCB 上加一堆模擬電路變成了我只需要畫一個 PCB 線圈加一顆電容剩下全在片內完成。1. 一開始我真沒打算用 MCU 做電感感應1.1 為什么 PSoC 被低估了我最早接觸到電感感應是在搜索金屬檢測方案的時候。主流搜索結果會引導你去用專用的電感數字轉換器方案比如 LDC1000、LDC1614 這類芯片它們確實把電感測量做到了很高的精度。但這類芯片有幾個現實問題成本不低、交期不太穩定、寄存器配置偏復雜而且一旦想改變檢測距離范圍或掃描多個通道硬件上往往要跟著調整。PSoC 被低估是因為大多數人把它當作一個普通 MCU 在評估。單看 CPU 性能PSoC 4 的 Cortex-M0 確實平平無奇但它的差異化在于內部可重構的模擬資源。PSoC 4 里集成了比較器、可編程增益放大器、跨阻放大器 TIA、電流型 DACIDAC、電壓型 DACVDAC、SAR ADC還有 UDB 數字可編程邏輯和 TCPWM 模塊。這些資源之間不是固定連接的而是像面包板一樣可以在片內重新布線。這給了電感感應一個天然的硬件土壤我不需要為了把 LC 諧振信號整形成方波而專門加一個外部比較器也不需要為了產生激勵脈沖而額外設計振蕩電路。PSoC 內部把這些路徑全打通了。在 TopDesign 圖形化編輯器里拖一個比較器組件、拖一個 TCPWM 計數器組件、用一根線連接起來硬件行為就完成了剩下的只是寫測量算法。這種開發模式對做模擬前端出身的工程師來說效率完全不同。1.2 和專用電感數字轉換器方案比差在哪我不是說專用方案一無是處。LDC 系列芯片內部有完整的激勵源、諧振電路、數字處理鏈精度和線性度確實強測微米級位移、做高分辨率旋轉編碼器這類場景用專用芯片是正道。但如果你只需要檢測金屬靠近沒靠近判斷蓋子開沒開水位到了哪個檔位用 LDC 就屬于高射炮打蚊子。我自己做了個對比三個方案放在一起看就很直觀維度專用電感數字轉換器通用 MCU 外部模擬電路PSoC MCU外部電路復雜度低線圈芯片高運放/比較器/整形很低線圈電阻電容靈活性低靠寄存器配置高但調試鏈路長高片上可重布線BOM 成本中高低但料號多低一顆芯片搞定多通道擴展部分型號支持成本高每路都要加模擬電路多路共用片內資源學習成本中等高中等但收益大從表格能看出來PSoC 是靈活性和外部復雜度之間的平衡點。它解決了我最痛的幾個問題物料少、不用為每個檢測點重復設計模擬前端、代碼里可以隨時調整測量策略。對于消費電子、汽車內飾、工業監測這類場景這個性價比優勢非常明顯。當然PSoC 的學習曲線是存在的你至少需要花一點時間理解片上布線和組件配置但一旦上了手后面做任何模擬信號檢測相關的需求都會順暢很多。2. 渦流、Q 值和振鈴這三個詞才是整件事的根基2.1 金屬目標到底改變了什么想要把 PSoC 用明白物理層面必須搞懂。電感感應的物理基礎是電磁感應中的渦流效應當 PCB 線圈上通入交變電流時線圈周圍會產生交變磁場當一塊金屬導體靠近這個磁場時金屬表面會感應出渦流。渦流的方向永遠和原磁場變化方向對抗所以它產生的磁場會抵消一部分原磁場。這個對抗最后體現在兩個物理量上等效電感 L 變化。渦流反磁場讓線圈的等效磁通量減小等效電感會下降。這也是電感數字轉換器直接測量 L 的理論依據。等效串聯電阻 R 增加。渦流在金屬的有限電阻上流動會以熱量的形式消耗能量這部分能量損耗反映到線圈側就是等效電阻升高。在諧振回路里這兩個變化最直接的體現就是品質因數 Q 值變化。Q 的經典定義是Q ωL / R其中 ω 是諧振角頻率。金屬靠近時L 變小、R 變大兩個因素同時作用Q 值快速下降。所以電感感應的本質測量對象歸根結底是 Q 值的變化而不是單純的電感量變化。我之前和很多人一樣老覺得測電感變化才是正路后來發現測 Q 值變化的抗干擾能力更好。因為 Q 值反映的是損耗這個宏觀物理量它受目標材質、距離、面積的影響非常規律而直接測電感容易受到線圈機械形變、周邊金屬靜態分布的影響。這個認知讓我后來的方案設計少走了很多彎路。2.2 為什么振鈴衰減比頻率偏移更容易測知道了測 Q 值下一個問題是怎么測。常見思路是測諧振頻率偏移金屬靠近時電感變化確實會引起 LC 諧振頻率偏移。但實測下來L 的變化率往往只有百分之幾甚至千分之幾換算成頻率偏移也就幾 kHz 到幾十 kHz很容易被溫漂和噪聲淹沒需要高分辨率計數器才能測準。所以我更推薦另一個思路振鈴衰減。給 LC 回路一個短暫的脈沖激勵然后撤掉激勵LC 回路會以自己的諧振頻率做自由衰減振蕩這就是振鈴Ring-Down。衰減的速度正好由 Q 值決定。Q 值高振鈴持續久Q 值低振鈴很快就停。從公式看振鈴電壓包絡按e^(-ωt / 2Q)衰減Q 值降低直接導致衰減指數增大。這種變化是幾何級的比頻率偏移靈敏得多——同樣是金屬靠近 2mm頻率可能只偏了 1%振鈴持續周期數可能掉了 40%。而且振鈴是時域現象用 MCU 里的比較器和計數器就能測不需要高精度頻率計。打個比方頻率法就像測一個人咳嗽聲的音調變化振鈴法就像測這個咳嗽聲能響多久。金屬靠近時咳嗽聲的音調變化很小但這個人被捂住嘴之后咳嗽立刻變短這個現象明顯得多。實際測量中振鈴衰減的時間尺度、計數周期數都和 MCU 的定時器資源完美匹配這是它能成為我首選方案的根本原因。3. 硬件簡單到只多了一顆電容3.1 從 PSoC 引腳到線圈的最小連接PSoC 做電感感應的最小硬件就是線圈、電容、限流電阻三件套外加 PSoC 的兩個引腳。我畫的連接方式是這樣線圈和并聯電容組成 LC 諧振回路一端接到 PSoC 的某個引腳這個引腳既做激勵輸出也做回波輸入另一端接地在引腳和 LC 節點之間串一顆 1kΩ 到 4.7kΩ 的電阻限制振鈴電壓擺幅同時給比較器輸入提供過流保護比較器正輸入端接到同一個 LC 節點負輸入端接一個由 VDAC 或內部基準設定的比較閾值。實際工作時序分兩步。第一步引腳配置為推挽輸出主動向 LC 回路輸出一個寬度等于諧振半周期的脈沖給回路注入能量第二步引腳立刻切換為高阻輸入LC 回路進入自由振蕩狀態振鈴信號通過同一節點進入比較器。這種單節點收發的做法外面看起來只是一根走線連著一個線圈和一個電容干凈利落。注意引腳雙向切換是 PSoC 的看家本領普通 MCU 的 GPIO 雖然也能切方向但內部模擬路徑不一定能這樣低噪聲地復用。PSoC 的 HSIOM 機制支持在運行中快速切換 GPIO 的外設連接和方向這是方案成立的關鍵之一。3.2 PSoC 內部哪些模擬資源在干活別小看這顆芯片內部協同工作的資源不少。我來拆解一下它們各自扮演的角色比較器是核心。它把 LC 節點上衰減的正弦波整形為方波這樣才能送入數字計數器。比較器閾值一般設在幾百毫伏太低容易把噪聲也整形進去太高會損失振鈴計數末端的信息。TCPWM 計數器負責數脈沖。比較器輸出的方波送到 TCPWM 的輸入在固定測量窗口內統計翻轉次數。窗口結束后通過中斷讀取計數值這個數就是 Q 值的時域化身。PWM/TCPWM用來產生激勵脈沖。我通常配置一個 PWM 輸出讓它單次輸出一個寬度可調的脈沖寬度對應諧振半周期。VDAC 或內部基準給比較器提供閾值電壓。用 VDAC 的好處是閾值可以軟件動態調整校準更方便。這些資源在 PSoC Creator 的 TopDesign 里就是幾個組件圖標用連線連起來就完成了硬件設計。我第一次用它時最大的震撼是以前要用 PCB 上幾十個元器件實現的模擬信號鏈現在變成了畫布上幾條線和幾個方框。雖然 PSoC Creator 的開發模式初看會覺得陌生但它本質上和畫原理圖是同一套思維方式。4. 三種測量手段我最后只留了兩種4.1 脈沖激勵加振鈴計數最穩我最終產品上采用的是脈沖激勵 振鈴計數。整個測量流程分成四個階段輸出一個寬度等于諧振半周期的激勵脈沖給 LC 回路注入能量激勵結束后等待一小段固定延時避開脈沖串擾帶來的錯誤計數打開計數窗口統計比較器輸出端方波的翻轉次數窗口結束讀取計數值歸一化得到檢測結果。這個方案的優點是簡單可靠、動態范圍大、功耗很低。因為激勵只持續不到 1 微秒其余時間系統只是靜默計數整個測量周期通常在幾十微秒內完成。PSoC 的 TCPWM 窗口模式天然支持這種在指定時間內對外部信號計數我只需要把 PWM 的窗口信號接到 TCPWM 的 Gate 輸入上。我實測的一組典型數據供參考諧振頻率 1.1MHz 左右無金屬靠近時30 微秒窗口內能數到 30 到 32 個完整周期金屬片貼近到 2mm 時計數會掉到 18 到 20 個貼到 1mm 時只剩 8 到 10 個。這個變化幅度非常明顯做閾值判斷幾乎是零壓力做粗略的距離趨勢判斷也有余量。調試這個方案時最有必要做的一件事是先用示波器看真實波形。把探針點在 LC 節點上觸發在激勵脈沖的下降沿你會看到一串衰減的正弦波。確認這個振鈴的形狀干凈、無雜波再去調比較器閾值和計數窗口會順利得多。4.2 持續振蕩加頻率測量適合低功耗模式另一個實踐過的是持續振蕩 頻率測量。思路是把 LC 回路接在比較器的正反饋路徑上配合偏置電阻構成一個振蕩器LC 的頻率決定振蕩頻率然后通過 TCPWM 的捕獲模式測量振蕩周期或頻率。這個方法的好處是信號是連續存在的不需要每次重新激勵測量響應速度極快而且在低功耗待機階段可以只讓比較器和計數器工作CPU 深度休眠。缺點也非常明顯持續振蕩會讓回路一直消耗能量而且振蕩器的穩定性和 PSoC 內部比較器的失調電壓、電源噪聲強相關實測頻率抖動比理論預期大。我最后沒有在量產方案里用它主要原因是因為它需要一個額外的三極管或運放來維持振蕩幅度這違背了我只加一個電容的初衷。但如果你做的是低功耗喚醒場景或者你需要的是連續高速的位置追蹤這個方向值得投入時間研究。PSoC 的優勢在于同樣的片上比較器和捕獲通道可以配置成不同模式你不必重新畫 PCB 就可以在兩種方案之間切換對比。4.3 幅度包絡這條路我為什么放棄第三種方案是幅度包絡檢測用固定頻率信號持續激勵 LC 回路金屬靠近時 Q 值下降LC 節點上的電壓幅度下降然后用 ADC 采樣幅度變化。我在實驗室試過這個方案。PSoC 的 SAR ADC 采樣率最高能做到 1 Msps 左右對 1MHz 的諧振信號做包絡提取理論邊界非常緊張。你需要要么加外部二極管包絡檢波電路要么在片內做高速采樣再配合數字濾波兩種路徑都讓方案失去片上自洽的優勢。幅度包絡對電源噪聲很敏感供電稍微有點紋波結果就抖得厲害。所以我的結論是如果目標只是判斷金屬的有無和大致距離振鈴計數法是最優解如果要做連續、高速、低功耗的檢測頻率法有潛力但工程代價大幅度包絡法對于 PSoC 這個平臺來說不是性價比高的路線我果斷放棄了。測量手段靈敏度動態范圍功耗額外硬件推薦指數振鈴計數高大極低無5/5頻率測量中中高需要振蕩維持電路2/5幅度包絡中小中需要包絡檢波1/55. 在 PSoC Creator 里把它跑起來5.1 工程骨架和組件拖拽我用的芯片型號是 PSoC 4200 系列CY8C4245 這類開發環境用 PSoC Creator雖然官方目前已經逐步轉向 ModusToolbox但這種小工程的拓撲設計思路兩者是通用的。下面是我在 TopDesign 里搭的最小工程骨架一個Pin_Pulse組件配置為輸出模式推挽輸出連接 LC 節點一個Pin_Sense組件配置為高阻輸入也連接同一個 LC 節點如果引腳資源緊張也可以合并為一個引腳靠代碼切方向但我更喜歡兩個引腳分離行為更清晰一個Analog_Comparator組件正輸入接Pin_Sense負輸入接VDAC輸出的閾值電壓一個TCPWM_Counter組件配置為外部計數模式輸入接比較器輸出Gate 接一個測量窗口信號一個PWM_Window組件用于產生可編程寬度的測量窗口信號一個PWM_Exciter組件用于產生激勵脈沖輸出接Pin_Pulse。所有這些組件之間用畫布上的連線連起來不需要寫一行硬件描述代碼。這種圖形化連線的方式對習慣傳統 MCU 開發的人一開始會覺得怪但 PSoC 的老用戶都清楚這正是它能自定義片上硬件的根本原因。每次連線都意味著內部模擬信號鏈上的一條具體路徑被激活這是真實存在的不是仿真。5.2 核心代碼與中斷細節硬件骨架搭好后固件部分的核心邏輯其實非常短。我在main.c里只做了三件事初始化組件、產生激勵脈沖、在中斷里讀取計數值。關鍵代碼大致如下#include project.h volatile uint32_t ringCount 0; volatile uint8_t measureDone 0; CY_ISR(ISR_Counter_Handler) { ringCount Counter_Ring_ReadCapture(); // 讀取計數值 Counter_Ring_ClearFIFO(); measureDone 1; Window_Stop(); // 停止窗口 } int main(void) { CyGlobalIntEnable; Counter_Ring_Start(); Counter_Ring_SetInterruptMode(Counter_Ring_INTR_MASK_CC_MATCH); isr_Counter_StartEx(ISR_Counter_Handler); for (;;) { measureDone 0; Exciter_WriteCompare(1); // 產生一個寬度為半個諧振周期的脈沖 Exciter_Start(); CyDelayUs(1); Exciter_Stop(); Window_WritePeriod(WINDOW_PERIOD); // 啟動測量窗口 Window_Start(); while (!measureDone) { CySysPmSleep(); } // 此時 ringCount 就是本次測量的原始值 ProcessData(ringCount); CyDelayMs(5); // 控制采樣速率 } }這段代碼有幾個容易踩的細節。第一激勵脈沖的產生和窗口啟動之間要留出極短的死區通常是 1 到 2 微秒讓振鈴的初始大信號先過去否則計數初值會被脈沖本身的翻轉污染。第二TCPWM 的中斷要在捕獲完成而不是溢出時觸發因為窗口結束瞬間正是計數器捕獲值的準確時刻。第三讀取Capture之后必須ClearFIFO否則下一次 Capture 會被舊數據覆蓋出現間隔性跳變。5.3 調參順序先看到波形再談算法我把調試順序放到了單獨一節是因為很多人一上來就調算法參數結果做了半天發現波形本身就不干凈后面的功夫全白費。正確的順序是先不接任何組件直接用示波器看 LC 節點的脈沖響應波形確認振鈴存在且頻率符合預期再把比較器閾值設成電源電壓的 15% 左右用示波器看比較器輸出確認方波邊沿干脆、沒有抖動最后才啟動 TCPWM 計數跑連續的測量循環觀察計數值的穩定性如果計數值跳變超過 ±2 個計數返回第一步檢查波形質量。按照這個順序我基本每次都能在半小時內把金屬檢測跑通。如果跳過第一步直接看最終計數值你會在到底是閾值問題、窗口問題還是信號噪聲之間反復猜效率極低。6. 從原始計數到能用的傳感器6.1 濾波和歸一化原始計數值需要有后處理才能變成穩定的檢測結果。最簡單的辦法是直接用一個滑動平均窗口我一般取 4 到 8 個樣本。但滑動平均有個問題如果現場有短暫的強干擾脈沖平均值會被拉偏導致一次誤觸發。我后來改用中值濾波對跳變毛刺的抑制效果明顯更好。具體做法是維護一個長度為 8 的環形緩沖區每次取中間兩個值的平均值作為濾波結果。代價只是多幾行代碼和幾個字節的 RAM換來的是現場穩定性的巨大提升。濾波之后再做歸一化便于設置通用閾值。我的歸一化公式是double ratio (baseline - count) / (double)baseline;無金屬時count接近baselineratio接近 0金屬靠近時count下降ratio快速上升。這個歸一化值的優點是排除了一部分由電源電壓、溫度引起的共模漂移因為基線和當前值同時受這些因素影響。6.2 閾值的確定和遲滯閾值設定的目標是無觸發時穩定、有觸發時快速響應。我的經驗做法是先連續采集 100 次無金屬狀態下的濾波值計算均值和標準差 σ然后設觸發閾值為mean - 3σ。3σ 意味著在無金屬狀態下超過 99.7% 的時間不會誤觸發。這里有一個容易忽略的點光有觸發閾值不夠還要加遲滯。也就是說觸發閾值設為 70恢復閾值就要設在 72 或更高。這樣當目標金屬在臨界位置輕微抖動時輸出不會在檢測到和未檢測到之間反復橫跳。遲滯量一般取觸發閾值的 5% 到 10% 就足夠。if ((!metalDetected) (ratio triggerThreshold)) { metalDetected 1; } if ((metalDetected) (ratio releaseThreshold)) { metalDetected 0; }6.3 溫漂補償和自校準電感感應對溫漂很敏感。線圈銅箔的電阻溫度系數大約是 3900 ppm/°C溫度升高會導致線圈等效電阻上升Q 值下降即使沒有金屬靠近計數值也會緩慢變小。如果不做補償夏天和冬天的基線差異可能直接把閾值淹沒。我做了兩層處理。第一層是依據 PSoC 內部溫度傳感器做線性補償上電時記錄溫度對應的基線值之后每隔一段時間讀一次溫度用線性插值修正基線。第二層是軟件上電自校準系統開機后前 100ms 不檢測專門采集一組無金屬狀態下的數據作為基線。兩層加在一起實測在 -10°C 到 60°C 范圍內基線的漂移被壓到了觸發閾值的 1/3 以下。提示如果溫度變化跨度很大或者對穩定性要求極高可以考慮雙線圈差分方案。一個線圈做感應另一個線圈放在金屬遠離的位置做參考差值輸出能同時抵消溫漂和電源波動。這是工業傳感器的常見做法付出的代價是 PCB 面積和一路通道的資源。7. PCB 線圈設計參數和幾個常見坑7.1 一圈銅箔怎么畫才不翻車線圈是整個系統里唯一的傳感器它的設計直接決定檢測距離和穩定性。我畫 PCB 平面螺旋線圈的經驗參數如下形狀方形或圓形平面螺旋均可方形布線方便圓形 Q 值略高圈數10 到 30 圈圈數越多電感量越大但寄生電容也會越大線寬/間距0.15mm 到 0.3mm6 到 12 mil過窄會增加電阻過寬會減小有效圈數外徑直接決定檢測距離經驗值是可靠檢測距離大約為線圈外徑的 0.1 到 0.5 倍。例如外徑 20mm 的線圈穩定檢測距離約 2mm 到 8mm目標電感量10μH 到 100μH配合諧振電容讓諧振頻率落在 200kHz 到 2MHz 之間諧振電容必須選 C0G/NP0 材質溫度系數小電壓特性平穩不能用 X5R/X7R。舉個例子我常用的一個線圈外徑 18mm內徑 4mm線寬 0.2mm間距 0.2mm20 圈實測電感約 40μH配一顆 1nF 的 C0G 電容諧振頻率大約在 800kHz 附近。這個配置下5mm 直徑的鐵片從 8mm 外靠近到 1mm計數值變化幅度超過 60%非常好用。電感量可以先用公式估算L ≈ μ0 * N2 * A / l其中 A 是平均半徑包圍的面積l 是線圈軸向長度平面線圈這里用平均周長替代。但 PCB 線圈由于寄生電容和臨近鋪地的影響估算值只能做參考我最后都是用 LCR 表實測校準。7.2 我踩過的坑鋪地、螺絲、外殼金屬件這一節分享幾個實踐中真正讓我頭疼過的坑每一個都是血淚教訓。第一個坑是線圈下方鋪地。我第一次畫板時習慣性把底層鋪了一大片地結果諧振頻率偏移超過 30%Q 值也大幅下降檢測距離從 6mm 縮水到 2mm。原因是鋪地銅箔會在交變磁場中感應出渦流它本身就成了一個大號金屬目標把能量都吃掉了。正確的做法是線圈正下方所有層都避開鋪地和走線至少留出和線圈一樣大小的凈空區域。第二個坑是外殼上的金屬螺絲。產品裝配后一顆離線圈 15mm 遠的金屬螺絲就能讓基線計數值下降 10%。這個問題在實驗室單獨測板子時完全發現不了直到整機測試才發現檢測距離突然變短。解決辦法有兩個要么在結構設計上讓金屬件遠離線圈 2 倍線圈外徑以上要么在軟件里提高基線學習次數把螺絲納入基線但這種做法會犧牲一部分檢測靈敏度。第三個坑是諧振電容的材質。如果你用 X7R 電容做諧振溫度每升高 20°C電容量可能漂移 5%諧振頻率跟著跑基線的溫漂會大到你懷疑人生。C0G 電容雖然貴一點但溫漂只有 ±30 ppm/°C穩定性完全不是一個檔次。我后來在項目中強制指定 C0G從根上消除了這個變量的影響。第四個坑是引腳走線太長。如果 PSoC 引腳到線圈之間走線過長、過細引入的寄生電感和電容會直接參與諧振導致你配的電容參數和實際行為對不上。我在一塊板上走線走了 15mm結果諧振頻率比計算值低了近 50%。盡量讓線圈靠近 MCU連接線短而粗。第五個坑是機械結構松動。振鈴計數法對線圈到目標之間的距離非常敏感1mm 的裝配公差就會帶來幾十個計數的偏移。所以產品結構的固定公差一定要控制好線圈本身最好用定位柱或卡扣固定不能靠膠水隨意粘貼。最后想分享一個心得上面這些坑沒有哪個是能在 FPGA 仿真或理論計算里提前看出來的全部要靠實際板子上的示波器波形和多次測量數據來暴露。所以如果你也在做一個電感感應相關的新設計別急著優化算法先把線圈畫好、噪聲控制住、波形調干凈整個方案就成功了一大半。這也是我經歷了三輪改板之后最深刻的體會。