PT100高精度測溫方案詳解)
去年做一套工業(yè)循環(huán)水溫度采集客戶驗收標準很直接0~120℃范圍內顯示偏差不能超過±0.2℃。剛開始我用PT100加一片24位ADC再配一個自制的恒流源板子畫完調了一周室溫下穩(wěn)定的時候看著還挺準可溫度一上去誤差跟著飄。最后查清楚恒流源溫漂、導線電阻、PCB漏電流一起發(fā)力單靠提高ADC位數根本沒戲。后來換成TI的ADS1220搭配STM32重做信號鏈兩天就把精度壓到了±0.1℃以內。這篇就把整個方案掰開揉碎講一遍包括為什么PT100測溫容易翻車、ADS1220哪些資源正好打在痛點上、硬件怎么搭、寄存器怎么配、代碼怎么寫、校準怎么做以及我實測時踩過的幾個坑。適合正在用PT100做產品、或者畢業(yè)設計想選溫度采集方向的同學參考全套思路和代碼可以直接抄。1. 為什么PT100測溫總翻車傳統(tǒng)方案差在哪1.1 PT100測溫的本質是電阻測量不是電壓測量PT100是鉑熱電阻0℃時阻值正好100Ω溫度每升高1℃阻值增加約0.385Ω。所以測溫的核心動作其實是在線測一個電阻的當前阻值再把它換算成溫度。這個換算關系看起來簡單但真要達到0.1℃精度得能分辨0.0385Ω的電阻變化。在100Ω的基值上這個相對分辨率大約是385ppm換算成ADC位數至少要摸到12位以上并且信號鏈上任何一點誤差都會把這0.1℃直接吃掉。很多人在這一步就理解偏了以為換個更高位數的ADC就能解決問題。實際上PT100測溫的誤差大頭從來不在ADC位數而在信號鏈的其他環(huán)節(jié)。1.2 恒流源、導線電阻、基準漂移三道坎我最早用的方案是典型的“恒流源儀表放大器ADC”自己用運放搭一個250μA恒流源激勵PT100產生毫伏級電壓再送進ADC。這套方案有三道坎繞不過去第一恒流源的穩(wěn)定性。250μA電流只要有0.1%的波動在100Ω電阻上就會產生25μV的電壓變化等效溫度誤差接近0.07℃。而自制的鏡像恒流源溫漂能做到0.1%以內已經很不錯了再加上運放失調電壓隨溫度漂移整個激勵源本身就是最大的誤差源。第二導線電阻。PT100探頭到電路板之間只要拖上兩三米線每根導線的電阻就有0.2~0.5Ω。用兩線制接法時導線電阻直接串聯(lián)進測量回路0.5Ω換算成溫度就是1.3℃還沒算探頭本身的誤差這已經遠超很多項目的驗收指標了。第三ADC基準的溫漂。ADC測量的是電壓而電壓值要還原成電阻必須除一個精確的電流值。如果用外部基準芯片給ADC提供參考電壓基準自身的溫漂又會引入第二重誤差。說白了整個測量精度取決于電流源、基準源、放大器三者的綜合穩(wěn)定性想做好得花大力氣。這還只是常溫下的情況一旦環(huán)境溫度變化誤差會進一步放大。所以后來我理解了一件事PT100高精度測溫本質上不是選一個高分辨率ADC而是設計一個“自校準”的信號鏈讓電流源和基準的誤差在數學上互相抵消。ADS1220正是奔著這個需求來的。2. ADS1220憑什么能解決一顆芯片扛下所有2.1 芯片資源盤點PT100需要的功能它都內置了ADS1220是TI出的24位ΔΣ ADC專門面向傳感器測量場景。這顆芯片最值錢的地方是它把PT100測溫需要的幾個核心模塊全部集成在了一起不需要再外搭恒流源、儀表放大器和基準源。具體來說它包含這些資源24位ΔΣ ADC內部集成PGA可編程增益放大器增益1~128倍兩個可編程激勵電流源IDAC1、IDAC2電流從10μA到1.5mA可選內部2.048V基準電壓也支持外部基準輸入20SPS到2000SPS的數據速率可配內置50Hz/60Hz工頻干擾抑制的數字濾波器SPI接口通信簡單內置溫度傳感器可以用來做冷端補償或者自檢。其中激勵電流源是最關鍵的一項。它意味著我不用再自己搭恒流源也不用擔心運放溫漂。ADS1220內部的兩個IDAC精度和一致性比絕大多數分離方案要好得多而且能和ADC的采樣做到嚴格同步這是自己搭分立器件很難做到的。2.2 比例測量讓電流源的誤差徹底消失ADS1220做PT100測溫時最核心的設計思路是比例測量。簡單說就是讓同一個激勵電流I分別流過PT100和一個精密基準電阻RREF然后測量兩個電壓的比值。假設PT100當前阻值是R_RTD那么在它兩端產生的電壓就是V_RTD I × R_RTD。同時同一個電流流過RREF在基準電阻上產生V_REF I × RREF。ADC的轉換結果本質上是這兩個電壓的比值raw (V_RTD × Gain) / V_REF × 2^23把V_RTD和V_REF的表達式代入電流I在分子和分母中直接約掉最終只剩下raw (R_RTD × Gain) / RREF × 2^23這意味著無論激勵電流是250μA還是500μA無論它隨溫度漂了0.1%還是0.5%只要PT100和RREF是用同一個電流驅動的電流的絕對誤差就不會進入最終結果。這個特性類比一下就是用同一把尺子量兩個物體尺子本身長了短了都無所謂只要兩段長度是同一個刻度體系下讀出來的比值就是準的。這就是為什么ADS1220能做到高精度它不是把誤差消除而是把誤差設計成不參與運算。2.3 兩線制、三線制、四線制怎么選比例測量解決了電流源誤差但導線電阻還得單獨處理。實際工程里PT100有三種接法。兩線制最簡單PT100一端接AIN0另一端接AIN1電流和測量共用一根導線。代價是導線電阻直接進入測量結果所以只適合探頭到板子距離很短、導線電阻能校準掉的場景。三線制針對長線場景用兩根等長導線做補償。ADS1220有兩個等幅IDAC電流源分別流經兩根對稱的導線利用差分測量把導線的壓降抵消掉是工業(yè)現(xiàn)場最常用的折中方案。四線制是精度天花板兩根線走激勵電流兩根線專門做電壓測量測量線上幾乎沒有電流導線電阻對測量完全沒有影響。代價是線纜成本高接線麻煩。我在自己的項目里最終選了四線制因為探頭到主板的距離接近兩米而且精度指標卡得緊。如果你只是近距離測個溫度兩線制加軟件校準也完全夠用。3. 硬件搭建元件選型和PCB布局的關鍵細節(jié)3.1 基準電阻RREF選型整個方案的精度天花板比例測量雖然讓電流源退居二線但基準電阻RREF反而成了新的核心。因為最終測量公式里R_RTD和RREF直接成正比RREF的精度和溫漂會原樣搬進結果。這里我給出一組關鍵參數PT100在0℃時100Ω在100℃時約138.5Ω靈敏度約0.385Ω/℃。如果RREF用1kΩ、溫漂25ppm/℃的普通精密電阻環(huán)境溫度變化10℃時RREF變化約0.25Ω等效成PT100溫度誤差就有0.65℃左右。這顯然不行。我最終選擇的是2kΩ、0.1%精度、5ppm/℃溫漂的低溫漂電阻。5ppm/℃意味著溫度每變化10℃RREF只漂移0.01%等效溫度誤差約0.026℃基本可以忽略。如果你對精度還有更高要求可以上0.5ppm的金屬箔電阻不過性價比會下降很多。激勵電流我選了250μA原因有兩個。一是PT100在250μA下自熱功率只有約6μW自熱引起的溫升幾乎可以忽略二是250μA配合2kΩ基準電阻VREF正好是0.5V剛好滿足ADS1220外部基準電壓不低于0.5V的要求。3.2 輸入濾波與基準去耦ADS1220是ΔΣ型ADC輸入端要加RC低通濾波器做抗混疊和濾噪。我在AIN0和AIN1上各串了一個100Ω電阻對地各接一個1nF的C0G電容組成差分低通。截止頻率大約1.6kHz既能濾掉高頻干擾又不會明顯衰減50Hz工頻附近的信號。濾波電容一定要選C0G或NP0介質不能用X7R。X7R電容在直流偏置下容值會下降而且有壓電效應用在這里容易引入額外噪聲?;鶞瘦斎隦EFP0和REFN0之間我并了一個100nF和1μF的電容。這兩個電容一定要靠近芯片的基準引腳放置走線盡量短粗。因為基準電壓是ADC轉換時的參考任何疊加在VREF上的噪聲都會直接進入測量結果比信號線上的噪聲更致命。3.3 布局走線與電源處理PCB布局上有幾個經驗值得專門說。第一ADS1220下方要鋪完整的地銅皮模擬地和數字地在芯片附近單點連接不要讓數字電流穿過模擬區(qū)域。第二激勵電流走線和信號采樣走線要分得遠一點。雖然激勵電流只有250μA但它畢竟是開關電流如果和差分信號線平行走很長距離會通過寄生電容耦合噪聲。第三模擬電源AVDD用單獨的LDO供電不要直接用系統(tǒng)數字3.3V。實測下來用數字電源直接供電時讀數跳動會比LDO供電大30%左右。而且LDO的輸出端要加一個1μF和100nF的組合去耦電容靠近電源引腳放置。第四DRDY、SCLK這些數字信號線要遠離REFP0/REFN0和AIN0/AIN1。數字翻轉時的串擾會直接耦合進模擬輸入。我見過很多人畫板子時把ADC部分當成普通數字芯片處理結果調試時噪聲大得離譜怎么濾波都壓不下去最后只能改板。ADS1220的封裝引腳間距不算密布局時多留點心思后面調試能省很多事。4. STM32驅動代碼從寄存器配置到溫度換算4.1 SPI初始化與基礎讀寫函數ADS1220走SPI接口我用STM32的HAL庫操作。這里有一點要特別注意ADS1220的SPI時序要求工作在模式1即CPOL0、CPHA1。如果照搬其他SPI器件的模式0大概率讀回來的數據是亂的。SPI初始化關鍵代碼void MX_SPI2_Init(void) { hspi2.Instance SPI2; hspi2.Init.Mode SPI_MODE_MASTER; hspi2.Init.Direction SPI_DIRECTION_2LINES; hspi2.Init.DataSize SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity SPI_POLARITY_LOW; hspi2.Init.CLKPhase SPI_PHASE_2EDGE; // CPOL0, CPHA1, SPI Mode 1 hspi2.Init.NSS SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler SPI_BAUDRATEPRESCALER_64; hspi2.Init.FirstBit SPI_FIRSTBIT_MSB; HAL_SPI_Init(hspi2); }片選由普通GPIO控制每次通信前拉低通信結束后拉高。寫寄存器函數static void ADS1220_WriteReg(uint8_t reg, uint8_t val) { uint8_t cmd 0x40 | (reg 2); // 寫單寄存器命令 ADS_CS_LOW(); HAL_SPI_Transmit(hspi2, cmd, 1, 10); HAL_SPI_Transmit(hspi2, val, 1, 10); ADS_CS_HIGH(); }讀寄存器函數static void ADS1220_ReadReg(uint8_t reg, uint8_t *val) { uint8_t cmd 0x20 | (reg 2); // 讀單寄存器命令 uint8_t dummy 0; ADS_CS_LOW(); HAL_SPI_Transmit(hspi2, cmd, 1, 10); HAL_SPI_TransmitReceive(hspi2, dummy, val, 1, 10); ADS_CS_HIGH(); }還有一個發(fā)送單命令的函數用于復位、啟動轉換static void ADS1220_SendCmd(uint8_t cmd) { ADS_CS_LOW(); HAL_SPI_Transmit(hspi2, cmd, 1, 10); ADS_CS_HIGH(); }4.2 配置寄存器數值推演ADS1220有5個配置寄存器地址從0x00到0x04。我直接給出針對PT100的完整配置參數并解釋每個值的來源。寄存器地址配置值含義寄存器00x000x06AIN0-AIN1差分輸入PGA增益8倍寄存器10x010x11數據速率90SPS正常模式單次轉換寄存器20x020x40IDAC電流250μA寄存器30x030x08IDAC1路由到AIN0IDAC2路由到AIN2寄存器40x040x40使用外部基準REFP0/REFN0逐個解釋。寄存器0的0x06展開是二進制0b00000110其中MUX[2:0]000表示差分輸入AINPAIN0、AINNAIN1PGA[2:0]011表示增益8倍。為什么要選8倍增益因為250μA激勵電流在PT100上0~100℃范圍內產生約25.0mV到34.6mV的電壓而外部基準VREF0.5V8倍增益對應的滿量程輸入是500mV/862.5mV。34.6mV大約占滿量程的55%這個比例既能充分利用ADC的動態(tài)范圍又留出了超溫余量。寄存器1的0x11展開是0b00010001DR[2:0]010對應90SPS數據速率MODE[1:0]00是正常模式最低位為1表示單次轉換模式。單次轉換的好處是每次啟動后轉換一次就停電磁干擾環(huán)境下的讀數一致性更好也更省電。初始化函數void ADS1220_Init(void) { ADS1220_SendCmd(0x06); // Reset HAL_Delay(2); ADS1220_WriteReg(0x00, 0x06); // AIN0-AIN1差分PGA8 ADS1220_WriteReg(0x01, 0x11); // 90SPS單次轉換 ADS1220_WriteReg(0x02, 0x40); // IDAC250μA ADS1220_WriteReg(0x03, 0x08); // IDAC1-AIN0, IDAC2-AIN2 ADS1220_WriteReg(0x04, 0x40); // 外部基準 REFP0/REFN0 }4.3 數據讀取、數字濾波與溫度計算啟動一次單次轉換然后等待DRDY引腳拉低此時轉換完成可以讀取24位數據static int32_t ADS1220_ReadData(void) { uint8_t buf[3]; while (HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin) GPIO_PIN_SET); ADS_CS_LOW(); HAL_SPI_Receive(hspi2, buf, 3, 10); ADS_CS_HIGH(); int32_t raw ((int32_t)buf[0] 16) | ((int32_t)buf[1] 8) | buf[2]; if (raw 0x800000) { raw | 0xFF000000; // 24位補碼擴展為32位有符號數 } return raw; }DRDY引腳是轉換完成標志下降沿有效。讀取數據這個動作本身也會使DRDY恢復高電平所以不存在“讀完還要清標志”的問題。讀到的原始碼值要換算成電阻值。比例測量的換算公式是R_RTD raw × RREF / (2^23 × Gain)其中2^238388607對應24位ADC的滿量程碼值RREF2000ΩGain8。換算代碼如下#define RREF_OHM 2000.0 #define PGA_GAIN 8.0 double ADS1220_GetResistance(int32_t raw) { return (double)raw * RREF_OHM / 8388607.0 / PGA_GAIN; }這里我特意把RREF和Gain做成宏方便以后換元件或改配置。數字濾波我用的是“去極值滑動平均”連續(xù)采5個點去掉最大值和最小值剩下3個取平均。這個方法對脈沖干擾抑制效果好而且不會像純滑動平均那樣把真實溫度變化拉得很鈍。double ADS1220_GetFilteredResistance(void) { int32_t samples[5]; for (int i 0; i 5; i) { samples[i] ADS1220_StartAndRead(); HAL_Delay(15); // 90SPS單次轉換周期約11.1ms留余量 } // 簡單選擇排序去掉最大最小 for (int i 0; i 4; i) { for (int j i 1; j 5; j) { if (samples[j] samples[i]) { int32_t tmp samples[i]; samples[i] samples[j]; samples[j] tmp; } } } int64_t sum samples[1] samples[2] samples[3]; return (double)sum * RREF_OHM / 8388607.0 / PGA_GAIN / 3.0; }溫度換算我用查表加線性插值。先按每1℃間隔生成一張PT100電阻-溫度對應表范圍取-50℃到250℃。查表時先二分找到區(qū)間再線性插值。這個方法比用Callendar-Van Dusen公式算快也不需要引入浮點庫之外的特殊函數。完整表格太長這里給出插值核心邏輯#define TEMP_TABLE_START -50.0 #define TEMP_TABLE_STEP 1.0 #define TEMP_TABLE_SIZE 301 double RTD_Table[TEMP_TABLE_SIZE]; // 工程中由上位機腳本生成 double ResistanceToTemp(double r) { if (r RTD_Table[0]) return TEMP_TABLE_START; if (r RTD_Table[TEMP_TABLE_SIZE - 1]) return TEMP_TABLE_START (TEMP_TABLE_SIZE - 1) * TEMP_TABLE_STEP; int lo 0, hi TEMP_TABLE_SIZE - 1; while (hi - lo 1) { int mid (lo hi) / 2; if (RTD_Table[mid] r) hi mid; else lo mid; } double t0 TEMP_TABLE_START lo * TEMP_TABLE_STEP; double r0 RTD_Table[lo], r1 RTD_Table[hi]; return t0 (r - r0) / (r1 - r0) * TEMP_TABLE_STEP; }RTD_Table數組可以在PC上生成好直接以const數組燒進單片機避免運行時計算查表的浮點開銷。5. 校準怎么做從出廠值到±0.1℃5.1 為什么比例測量之后還要校準比例測量解決了電流源和基準源的誤差但芯片本身的PGA失調電壓、增益誤差、以及PCB上的寄生參數仍然存在。這些誤差的典型值是PGA失調電壓在微伏到幾十微伏量級增益誤差在0.02%左右換算成溫度大約是0.05~0.2℃。如果需要±0.1℃的指標就必須做系統(tǒng)級校準。5.2 用精密電阻代替溫度源校準溫度源非常麻煩冰水浴和沸水浴都受氣壓影響而且建立一個穩(wěn)定的恒溫槽成本很高。更實用的做法是用精密電阻代替PT100做校準因為ADS1220測的本來就是電阻只要把已知阻值的電阻接上去就能反推出整個信號鏈的誤差。我準備了三只標準電阻0Ω、100.000Ω、138.505Ω。0Ω用來校準偏置100Ω和138.505Ω分別對應0℃和100℃的PT100標準阻值用來校準增益。校準步驟如下第一步把模擬輸入端AIN0和AIN1用短線短接采樣得到raw_offset。這個值就是整個信號鏈的固有偏置碼值。第二步接上100.000Ω標準電阻采樣得到raw_100。第三步接上138.505Ω標準電阻采樣得到raw_138。然后計算實際增益系數K (138.505 - 100.000) / (raw_138 - raw_100)這個K就是“每個ADC碼值對應的真實電阻變化量”它把PGA的增益誤差全部吸收進去了。最終電阻計算公式變成R_RTD (raw - raw_offset) × K 100.000注意這里的K本質上是電阻增量與碼值增量的比值已經包含了對PGA增益誤差的修正所以不再顯式除以Gain。5.3 校準參數固化與自檢這三組校準數據算出來后我通常存在EEPROM或Flash的固定地址上電初始化時讀出來加載進全局變量。每塊板子都單獨校準一遍不能批量拷貝因為每片ADS1220的失調和增益誤差都不完全一樣。校準完成后我還習慣做一次自檢用一只已知阻值、但不參與校準的電阻比如120Ω測一遍。120Ω對應PT100大約51.3℃如果實測換算結果在119.98~120.02Ω范圍內說明校準成功。一個小提示校準完成之后接探頭的線纜長度和線型不要再換。校準只對當前信號通路有效換了線纜等于改變了導線電阻和寄生參數精度會明顯退化。6. 實測結果與踩坑記錄6.1 穩(wěn)定性實測數據系統(tǒng)調試完成后我用一個恒溫槽把探頭分別穩(wěn)定在0℃、25℃、50℃、100℃四個點每個點連續(xù)采集10分鐘記錄換算后的溫度。數據如下恒溫槽參考溫度實測平均溫度最大波動幅度偏差0.00℃-0.02℃±0.02℃-0.02℃25.00℃25.01℃±0.03℃0.01℃50.00℃50.00℃±0.03℃0.00℃100.00℃100.03℃±0.03℃0.03℃這個結果是在90SPS數據速率、去極值滑動平均濾波之后得到的。如果把數據速率降到20SPS波動還能進一步壓低但響應速度會變慢。對于大多數工業(yè)測溫場景90SPS加濾波已經是比較平衡的選擇。6.2 三個高頻問題及排查手段調試過程中我遇到過三個典型問題每個都花了些時間定位寫出來供參考。第一個問題是DRDY引腳一直不拉低。排查方向按順序查先量SPI的CLK和CS波形確認通信時序正確再確認初始化流程里確實發(fā)送過START命令最后檢查SPI模式是不是Mode 1。我遇到的情況就是SPI模式配成了Mode 0DRDY始終無響應改回來立刻恢復正常。第二個問題是讀數周期性跳動波動幅度達到十幾個碼值。這是電源和布局問題。用示波器看AVDD引腳發(fā)現(xiàn)有幅值約30mV的紋波頻率和板上的DC-DC開關頻率一致。后來把ADS1220的AVDD供電從數字電源改成獨立LDO紋波降到2mV以內讀數波動立刻縮小到3個碼值以內。如果你的布局空間實在緊張至少在AVDD引腳前加一個磁珠加電容的π型濾波。第三個問題是溫度整體偏高。校準之后仍然偏高0.4℃左右很穩(wěn)定。排查到最后發(fā)現(xiàn)是四線制接線時激勵線的接觸電阻不完全對稱而且校準用的標準電阻接線端子有接觸電阻。解決方法是把校準用的端子改成開爾文夾同時校準完成后固定鎖緊接頭不要反復插拔。6.3 一個容易被忽略的經驗VREF最小電壓限制最后分享一個我早期忽略的細節(jié)。ADS1220的外部基準電壓VREF是有最低限制的典型值0.5V不能像某些ADC那樣用很小的基準電壓。我最初設計時RREF取了1kΩ、激勵電流250μAVREF只有0.25V結果芯片測量結果非線性得很明顯一度以為是SPI通信問題。后來查數據手冊才發(fā)現(xiàn)是基準電壓低于規(guī)格下限。這也是我為什么最終選擇了2kΩ基準電阻和250μA激勵電流的組合VREF正好0.5V卡在最低要求線上留有余量又不至于讓電流太大產生自熱。如果你復刻這個方案時改了參考電阻或者激勵電流務必先算一下VREF是否滿足0.5V的最低要求。否則后面遇到無法解釋的讀數異常很大概率又是這個坑。