量全攻略:從ADC原理到分壓電路與軟件濾波實(shí)踐)
1. 項(xiàng)目緣起為什么用Arduino測(cè)電壓是個(gè)“技術(shù)活”如果你玩過Arduino大概率干過點(diǎn)亮LED、讀取按鈕狀態(tài)或者驅(qū)動(dòng)舵機(jī)這類事兒。這些操作本質(zhì)上都是數(shù)字信號(hào)的處理引腳要么是高電平比如5V要么是低電平0V非黑即白簡(jiǎn)單直接。但一旦涉及到“電壓測(cè)量”事情就變得微妙起來了。這不再是簡(jiǎn)單的0或1而是一個(gè)連續(xù)的模擬量比如3.7V的鋰電池還剩多少電太陽能板的輸出電壓是多少一個(gè)電位器旋轉(zhuǎn)到了什么位置這些問題的答案都是一個(gè)具體的電壓值。Arduino Uno這類板子核心的ATmega328P單片機(jī)自帶了一個(gè)10位精度的模數(shù)轉(zhuǎn)換器ADC。這聽起來是個(gè)現(xiàn)成的解決方案但直接用它去測(cè)量電壓尤其是超出其工作范圍的電壓無異于“裸奔”——輕則讀數(shù)不準(zhǔn)重則燒毀芯片。我見過不少新手興沖沖地把12V的電源直接接到模擬引腳上然后疑惑為什么板子冒煙了。所以用Arduino進(jìn)行電壓測(cè)量核心不是寫幾行analogRead()的代碼而是如何安全、準(zhǔn)確地將外部電壓“適配”到ADC能安全讀取的范圍內(nèi)。這背后是一整套關(guān)于分壓計(jì)算、精度取舍、參考電壓選擇和噪聲處理的工程實(shí)踐。今天我就結(jié)合自己踩過的坑把這套從原理到實(shí)操從電路到代碼的完整流程拆解清楚讓你不僅能測(cè)還能測(cè)得好、測(cè)得穩(wěn)。2. 核心原理與安全邊界Arduino ADC的“規(guī)矩”與“紅線”在動(dòng)手接線之前我們必須徹底理解Arduino ADC的工作機(jī)制和絕對(duì)不可逾越的安全紅線。這是所有后續(xù)操作的基礎(chǔ)。2.1 ADC的工作機(jī)制與關(guān)鍵參數(shù)Arduino Uno的ADC是一個(gè)10位的逐次逼近型轉(zhuǎn)換器。所謂“10位”意味著它能把一個(gè)電壓范圍分成 2^10 1024 個(gè)離散的等級(jí)。analogRead()函數(shù)返回的0到1023的整數(shù)就對(duì)應(yīng)著這1024個(gè)等級(jí)。這里引出一個(gè)核心概念參考電壓AREF。ADC并不知道“伏特V”這個(gè)單位它只知道將輸入的電壓與一個(gè)基準(zhǔn)電壓進(jìn)行比較。這個(gè)基準(zhǔn)電壓就是參考電壓。默認(rèn)情況下Arduino Uno使用板載的5V穩(wěn)壓輸出作為參考電壓通過analogReference(DEFAULT)設(shè)置。這意味著當(dāng)輸入電壓 0V時(shí)analogRead()返回 0。當(dāng)輸入電壓 參考電壓默認(rèn)5V時(shí)analogRead()返回 1023。輸入電壓與返回值的關(guān)系是線性的電壓值 (讀數(shù) / 1023) * 參考電壓。因此ADC的測(cè)量范圍和精度直接受參考電壓影響測(cè)量范圍輸入電壓絕對(duì)不能超過參考電壓否則ADC可能損壞。默認(rèn)情況下就是不能超過5V。分辨率理論精度參考電壓 / 1024。默認(rèn)5V參考下分辨率約為 5V / 1024 ≈ 4.9mV。這意味著電壓變化至少要大于4.9mVADC才能察覺到變化。2.2 絕對(duì)安全紅線輸入電壓限制這是必須用加粗強(qiáng)調(diào)的鐵律Arduino模擬輸入引腳A0-A5能承受的絕對(duì)最大電壓是Vcc工作電壓 0.5V。對(duì)于使用USB供電5V的Uno這個(gè)值大約是5.5V。超過此電壓芯片內(nèi)部的保護(hù)二極管會(huì)導(dǎo)通產(chǎn)生大電流瞬間損壞單片機(jī)。所以即使你改變了參考電壓例如使用更低的1.1V內(nèi)部參考模擬引腳本身的耐壓極限依然是5.5V左右。任何測(cè)量高于5V電壓的方案第一步都必須是通過外部電路將高壓降低到安全范圍以內(nèi)而不是直接連接。2.3 精度的影響因素與常見誤區(qū)很多人以為analogRead()的返回值就是真理其實(shí)不然。除了理論分辨率還有幾個(gè)關(guān)鍵因素影響最終精度參考電壓的穩(wěn)定性板載的5V穩(wěn)壓源來自USB或外部電源本身就有波動(dòng)可能有±50mV的紋波。如果用它作為參考它的波動(dòng)會(huì)直接導(dǎo)致讀數(shù)波動(dòng)。ADC本身的非線性誤差和積分非線性誤差數(shù)據(jù)手冊(cè)會(huì)給出這些參數(shù)它們會(huì)導(dǎo)致讀數(shù)與理論值之間存在固定偏差。噪聲來自電源、數(shù)字電路開關(guān)如PWM、甚至MCU自身的噪聲都會(huì)耦合到模擬信號(hào)中。你可能發(fā)現(xiàn)讀數(shù)會(huì)在一個(gè)范圍內(nèi)無規(guī)律跳動(dòng)。一個(gè)常見的誤區(qū)是盲目追求“高分辨率”。有人想測(cè)量0-5V的電壓覺得4.9mV的分辨率不夠想換用12位4096級(jí)的ADC模塊。但在噪聲就有20mV的環(huán)境下12位ADC分辨率1.2mV只會(huì)讓你看到更劇烈的數(shù)字跳動(dòng)而不會(huì)得到更準(zhǔn)確的結(jié)果。提升信噪比例如通過濾波、優(yōu)化布線、使用穩(wěn)定參考源往往比單純?cè)黾覣DC位數(shù)更有效。3. 實(shí)戰(zhàn)方案一測(cè)量0-5V以內(nèi)的直流電壓這是最簡(jiǎn)單、最基礎(chǔ)的應(yīng)用場(chǎng)景例如測(cè)量電位器的位置、光敏電阻的分壓、或者一個(gè)穩(wěn)定的5V以內(nèi)的電源。3.1 電路連接與注意事項(xiàng)電路極其簡(jiǎn)單將被測(cè)電壓的正極連接到任意模擬引腳如A0負(fù)極連接到Arduino的GND。但這里有三個(gè)至關(guān)重要的細(xì)節(jié)共地必須確保被測(cè)電壓的GND和Arduino的GND連接在一起否則沒有共同的參考點(diǎn)測(cè)量毫無意義。輸入阻抗Arduino模擬引腳的輸入阻抗約為100MΩ對(duì)于大多數(shù)信號(hào)源來說負(fù)載效應(yīng)極小可以忽略。但如果你測(cè)量的信號(hào)源內(nèi)阻非常大例如某些高阻值的分壓網(wǎng)絡(luò)可能會(huì)因?yàn)檩斎腚娏鲗?dǎo)致測(cè)量值偏低。這時(shí)需要考慮使用運(yùn)算放大器構(gòu)成電壓跟隨器進(jìn)行緩沖。濾波在模擬引腳和GND之間并聯(lián)一個(gè)0.1uF104的瓷片電容可以有效地濾除高頻噪聲。這是一個(gè)低成本但效果顯著的技巧。3.2 基礎(chǔ)代碼與校準(zhǔn)代碼的核心就是analogRead()和換算公式。const int analogPin A0; // 被測(cè)電壓連接的引腳 void setup() { Serial.begin(9600); // 初始化串口用于輸出結(jié)果 // analogReference(DEFAULT); // 使用默認(rèn)5V參考此句可寫可不寫 } void loop() { int sensorValue analogRead(analogPin); // 讀取ADC原始值 (0-1023) float voltage sensorValue * (5.0 / 1023.0); // 換算為電壓值 Serial.print(ADC Raw: ); Serial.print(sensorValue); Serial.print( | Voltage: ); Serial.print(voltage); Serial.println( V); delay(500); // 延時(shí)半秒 }校準(zhǔn)實(shí)操理論上公式是完美的但實(shí)際中你的“5.0V”參考電壓可能只有4.95V。為了更準(zhǔn)確可以進(jìn)行一次簡(jiǎn)單校準(zhǔn)使用一個(gè)已知精確的電壓源例如用萬用表測(cè)量一個(gè)穩(wěn)定的4.5V電池接到A0。運(yùn)行上述代碼讀取穩(wěn)定的sensorValue比如是921。計(jì)算真實(shí)的參考電壓真實(shí)Vref 已知電壓 * 1023 / sensorValue。例如4.5 * 1023 / 921 ≈ 5.01V。將代碼中的5.0替換為計(jì)算出的5.01公式變?yōu)関oltage sensorValue * (5.01 / 1023.0);。3.3 軟件濾波讓讀數(shù)“穩(wěn)”下來原始讀數(shù)跳動(dòng)是常態(tài)。除了硬件上加電容軟件濾波是必做功課。這里介紹兩種最實(shí)用的方法1. 滑動(dòng)平均濾波連續(xù)采樣N次求平均值。簡(jiǎn)單有效能平滑隨機(jī)噪聲。const int numReadings 10; // 平均采樣次數(shù) int readings[numReadings]; // 采樣數(shù)組 int readIndex 0; // 當(dāng)前索引 int total 0; // 總和 int average 0; // 平均值 void setup() { Serial.begin(9600); for (int i 0; i numReadings; i) { readings[i] 0; // 初始化數(shù)組 } } void loop() { total total - readings[readIndex]; // 減去最舊的值 readings[readIndex] analogRead(A0); // 讀取新值 total total readings[readIndex]; // 加上最新值 readIndex (readIndex 1) % numReadings; // 索引循環(huán) average total / numReadings; // 計(jì)算平均值 float voltage average * (5.0 / 1023.0); Serial.print(Filtered Voltage: ); Serial.println(voltage); delay(10); // 短延時(shí)控制采樣率 }2. 中值濾波連續(xù)采樣N次通常取奇數(shù)如57然后取中間值。對(duì)于偶爾出現(xiàn)的脈沖干擾尖峰噪聲有奇效。const int sampleSize 5; int samples[sampleSize]; float medianFilterRead(int pin) { // 1. 采集一組樣本 for (int i 0; i sampleSize; i) { samples[i] analogRead(pin); delay(2); // 小延時(shí)避免采樣過于密集 } // 2. 對(duì)樣本進(jìn)行簡(jiǎn)單排序冒泡排序樣本量小夠用 for (int i 0; i sampleSize - 1; i) { for (int j i 1; j sampleSize; j) { if (samples[j] samples[i]) { int temp samples[i]; samples[i] samples[j]; samples[j] temp; } } } // 3. 返回中值 return samples[sampleSize / 2]; } void loop() { int filteredValue medianFilterRead(A0); float voltage filteredValue * (5.0 / 1023.0); Serial.println(voltage); delay(200); }在實(shí)際項(xiàng)目中我常將兩者結(jié)合先中值濾波去除尖峰再滑動(dòng)平均進(jìn)一步平滑。4. 實(shí)戰(zhàn)方案二測(cè)量高于5V的直流電壓電阻分壓法這是更常見的需求比如監(jiān)控12V的汽車電瓶、24V的工業(yè)電源或者太陽能板的電壓。核心方法是使用電阻分壓電路將高壓按比例縮小到5V以內(nèi)。4.1 分壓電路設(shè)計(jì)與計(jì)算分壓原理很簡(jiǎn)單兩個(gè)串聯(lián)電阻輸出電壓 輸入電壓 * (R2 / (R1 R2))。Vin (高壓) ---[ R1 ]--- Vout (接Arduino A0) ---[ R2 ]--- GND設(shè)計(jì)步驟確定測(cè)量范圍假設(shè)要測(cè)量0-30V的電壓Vin_max。確定安全Vout為了留有余地我們?cè)O(shè)定最大Vout為4.5V小于5V。計(jì)算分壓比分壓比 k Vout_max / Vin_max 4.5V / 30V 0.15。選擇電阻值由公式 k R2 / (R1 R2)可以推導(dǎo)出 R1 / R2 (1/k) - 1。代入k0.15得到 R1 / R2 ≈ 5.67。選擇一個(gè)常見的R2值例如10kΩ。則 R1 5.67 * 10kΩ ≈ 56.7kΩ。我們可以選用標(biāo)稱值56kΩ的電阻。驗(yàn)證與調(diào)整當(dāng)Vin30V時(shí)Vout 30V * (10k / (56k 10k)) ≈ 4.55V接近且略小于5V安全。當(dāng)Vin0V時(shí)Vout0V。計(jì)算出的電阻值最好使用E24系列中的標(biāo)稱值如56kΩ和10kΩ。電阻選型經(jīng)驗(yàn)精度選用1%精度的金屬膜電阻能顯著提升測(cè)量準(zhǔn)確性。5%的碳膜電阻誤差太大。功率計(jì)算電阻的功耗。P_R1 Vin^2 / R1。在30V時(shí)P_R1 30^2 / 56000 ≈ 0.016W普通的1/4W電阻綽綽有余。但如果測(cè)量電壓很高如上百伏或電阻值很小就必須核算功率。阻抗匹配分壓電路的輸出阻抗即R1與R2的并聯(lián)值應(yīng)遠(yuǎn)小于ADC的輸入阻抗100MΩ。本例中輸出阻抗約8.5kΩ完全滿足。4.2 電路搭建與保護(hù)措施光有分壓電阻還不夠一個(gè)健壯的電路需要多重保護(hù)鉗位保護(hù)二極管在Vout接A0的點(diǎn)和Arduino的5V之間反向并聯(lián)一個(gè)肖特基二極管如1N5817。如果Vout因意外超過5V二極管壓降約0.3V二極管導(dǎo)通將電壓鉗位在5.3V左右保護(hù)ADC。注意二極管正極接A0負(fù)極接5V。低通濾波電容在Vout和GND之間并聯(lián)一個(gè)0.1uF瓷片電容濾除噪聲。如果需要更強(qiáng)的濾波可以并聯(lián)一個(gè)更大容量的電解電容如10uF。前級(jí)保險(xiǎn)絲如果測(cè)量的是電源總線串聯(lián)一個(gè)小的自恢復(fù)保險(xiǎn)絲如100mA在Vin端防止短路故障。完整的保護(hù)電路示意圖如下Vin ---[Fuse]---[ R1 ]---x Vout (to A0) ---[C1 0.1uF]--- GND | | [R2] [D1] Cathode - 5V | | GND GND4.3 代碼實(shí)現(xiàn)與標(biāo)定代碼需要根據(jù)分壓比進(jìn)行反算。voltage (ADC讀數(shù) / 1023.0) * Vref * ( (R1 R2) / R2 )。為了提高精度強(qiáng)烈建議進(jìn)行兩點(diǎn)標(biāo)定而不是單純依賴?yán)碚撚?jì)算。const float R1 56000.0; // 高端電阻單位歐姆 const float R2 10000.0; // 低端電阻單位歐姆 const float divisionFactor (R1 R2) / R2; // 分壓系數(shù) void setup() { Serial.begin(9600); // analogReference(INTERNAL); // 如果使用更穩(wěn)定的1.1V內(nèi)部參考可以啟用 } void loop() { int raw analogRead(A0); // 方法1理論計(jì)算受電阻精度和Vref誤差影響 float voltageCalculated raw * (5.0 / 1023.0) * divisionFactor; // 方法2兩點(diǎn)標(biāo)定法推薦 // 假設(shè)我們通過實(shí)驗(yàn)已知 // 當(dāng)實(shí)際電壓為 0V 時(shí)ADC讀數(shù)為 adc0 (理論上應(yīng)為0) // 當(dāng)實(shí)際電壓為 15.0V (一個(gè)已知精確值) 時(shí)ADC讀數(shù)為 adc15 const int adc0 2; // 實(shí)測(cè)0V時(shí)的讀數(shù)可能存在零點(diǎn)偏移 const int adc15 465; // 實(shí)測(cè)15.0V時(shí)的讀數(shù) const float knownVoltage 15.0; // 計(jì)算標(biāo)定后的斜率已知電壓 / (已知點(diǎn)ADC值 - 零點(diǎn)ADC值) float calibratedSlope knownVoltage / (adc15 - adc0); float voltageCalibrated (raw - adc0) * calibratedSlope; Serial.print(Raw:); Serial.print(raw); Serial.print( | Calc:); Serial.print(voltageCalculated); Serial.print(V | Calib:); Serial.print(voltageCalibrated); Serial.println(V); delay(500); }兩點(diǎn)標(biāo)定實(shí)操將你的分壓電路輸入端Vin短接到GND讀取穩(wěn)定的ADC值記為adc0。這消除了系統(tǒng)的零點(diǎn)誤差。將一個(gè)已知精確值的電壓源比如用精度較高的數(shù)字萬用表測(cè)得的12.00V電池接到Vin讀取穩(wěn)定的ADC值記為adcKnown。將這兩個(gè)值代入上述代碼的標(biāo)定部分。這樣計(jì)算出的電壓值其精度主要取決于你已知電壓源的精度和ADC的線性度很大程度上抵消了電阻誤差和參考電壓誤差。5. 實(shí)戰(zhàn)方案三提升測(cè)量精度與穩(wěn)定性的進(jìn)階技巧當(dāng)基礎(chǔ)測(cè)量滿足不了需求比如需要監(jiān)測(cè)電池微小的電壓變化或者系統(tǒng)對(duì)噪聲非常敏感時(shí)就需要下面這些進(jìn)階技巧。5.1 使用更穩(wěn)定的參考電壓如前所述默認(rèn)的5V參考并不穩(wěn)定。Arduino提供了其他選項(xiàng)analogReference(INTERNAL)使用芯片內(nèi)部的1.1V基準(zhǔn)源。這個(gè)基準(zhǔn)源溫度穩(wěn)定性比5V好噪聲更低。但注意此時(shí)ADC的輸入范圍變?yōu)?-1.1V超過1.1V會(huì)損壞ADC必須確保你的信號(hào)電壓或分壓后的電壓在此范圍內(nèi)。analogReference(EXTERNAL)使用連接到AREF引腳的外部基準(zhǔn)電壓。你可以接入一個(gè)高精度、低溫漂的基準(zhǔn)電壓芯片如LM4040或REF30303.0V。這是獲得高精度測(cè)量的終極方案。使用內(nèi)部1.1V參考測(cè)量小電壓假設(shè)你想測(cè)量一個(gè)0-1V的傳感器信號(hào)。void setup() { Serial.begin(9600); analogReference(INTERNAL); // 切換到1.1V內(nèi)部參考 // 警告此后A0引腳輸入電壓絕對(duì)不能超過1.1V } void loop() { int raw analogRead(A0); // 分辨率提升至 1.1V / 1024 ≈ 1.07mV float voltage raw * (1.1 / 1023.0); Serial.println(voltage, 3); // 輸出3位小數(shù) delay(200); }重要提示切換analogReference()后需要丟棄前幾次analogRead()的結(jié)果通常1-2次因?yàn)锳DC內(nèi)部電容需要時(shí)間切換到新的參考源。5.2 過采樣與動(dòng)態(tài)范圍擴(kuò)展這是一個(gè)軟件技巧用于在噪聲環(huán)境中“擠出”額外的分辨率。原理是對(duì)信號(hào)進(jìn)行多次采樣遠(yuǎn)高于奈奎斯特頻率利用噪聲的隨機(jī)性通過數(shù)字平均來增加有效位數(shù)。例如進(jìn)行16倍過采樣可以將10位ADC的有效分辨率提升約2位達(dá)到12位左右。long oversampleAnalogRead(int pin, byte oversampling) { long sum 0; // oversampling應(yīng)為4, 16, 64, 256等4的冪次 int numSamples 1 (2 * oversampling); // 4^oversampling for (long i 0; i numSamples; i) { sum analogRead(pin); } // 將求和結(jié)果右移oversampling位相當(dāng)于除以2^oversampling return sum oversampling; } void loop() { // 進(jìn)行4倍過采樣 (2^416次采樣) long filteredRaw oversampleAnalogRead(A0, 2); // 參數(shù)2代表4倍過采樣 float voltage filteredRaw * (5.0 / 1023.0); // 此時(shí)filteredRaw的值范圍看似還是0-1023但其最小變化單位更精細(xì)了 Serial.println(voltage, 4); // 可以輸出更多小數(shù)位 delay(100); }注意過采樣只有在信號(hào)本身含有噪聲白噪聲且ADC量化噪聲是主要限制時(shí)才有效。如果信號(hào)本身很干凈過采樣沒用。5.3 多通道測(cè)量與通道間串?dāng)_Arduino Uno有6個(gè)模擬通道A0-A5但只有一個(gè)ADC。通過一個(gè)多路復(fù)用器MUX來切換通道。切換通道后ADC內(nèi)部采樣保持電容上的電荷需要時(shí)間穩(wěn)定如果立即讀取會(huì)讀到上一個(gè)通道的殘留電壓。正確做法是切換通道后丟棄第一次讀數(shù)。int readAnalogChannel(int pin) { int dummy analogRead(pin); // 第一次讀取丟棄 delay(1); // 短暫延時(shí)確保穩(wěn)定 return analogRead(pin); // 第二次讀取作為有效值 } void loop() { int valA0 readAnalogChannel(A0); int valA1 readAnalogChannel(A1); // ... 處理讀數(shù) }對(duì)于高精度應(yīng)用這個(gè)延時(shí)可能需要根據(jù)信號(hào)源阻抗調(diào)整可以通過實(shí)驗(yàn)確定。6. 常見問題排查與實(shí)戰(zhàn)心得理論終歸要落到實(shí)踐實(shí)踐中總會(huì)遇到各種奇怪的問題。下面是我總結(jié)的幾個(gè)典型坑位和排查思路。6.1 讀數(shù)跳動(dòng)大噪聲問題現(xiàn)象即使輸入電壓穩(wěn)定analogRead()的返回值也在上下跳動(dòng)范圍可能達(dá)到10-20個(gè)數(shù)值。排查與解決檢查電源這是最常見的噪聲源。使用電池供電的Arduino通常比USB供電更干凈。如果使用開關(guān)電源噪聲可能很大。嘗試用線性穩(wěn)壓電源或高質(zhì)量的USB充電器。檢查共地確保被測(cè)信號(hào)源、分壓電阻、Arduino的GND都連接在同一點(diǎn)上避免形成“地環(huán)路”引入干擾。添加濾波電容在模擬輸入引腳對(duì)GND加0.1uF瓷片電容。在Arduino的5V和GND之間靠近芯片的位置并聯(lián)一個(gè)10uF電解電容和一個(gè)0.1uF瓷片電容。如果使用分壓電路在分壓點(diǎn)Vout對(duì)GND加電容。遠(yuǎn)離噪聲源讓模擬走線遠(yuǎn)離數(shù)字走線特別是PWM引腳、時(shí)鐘線、高速數(shù)據(jù)線。如果可能將模擬傳感器用屏蔽線連接。啟用噪聲抑制在analogRead()前短暫關(guān)閉中斷但這對(duì)大多數(shù)Arduino應(yīng)用影響不大。軟件濾波如前所述必須使用滑動(dòng)平均或中值濾波。6.2 測(cè)量值不準(zhǔn)或存在固定偏差現(xiàn)象測(cè)量一個(gè)已知的3.3V讀出來總是3.5V或3.1V。排查與解決參考電壓不準(zhǔn)用萬用表測(cè)量Arduino的5V引腳實(shí)際電壓。如果偏差大如4.8V或5.2V在代碼中使用測(cè)量值進(jìn)行校準(zhǔn)或改用更穩(wěn)定的參考源INTERNAL或EXTERNAL。電阻精度問題分壓電路中使用的若是5%精度的電阻其實(shí)際阻值可能與標(biāo)稱值相差甚遠(yuǎn)。使用1%精度的金屬膜電阻并進(jìn)行兩點(diǎn)標(biāo)定。代碼計(jì)算錯(cuò)誤檢查換算公式。特別注意整數(shù)除法問題。(5 / 1023)在整數(shù)運(yùn)算中結(jié)果為0必須使用浮點(diǎn)數(shù)(5.0 / 1023.0)。輸入阻抗影響如果信號(hào)源內(nèi)阻很大如兆歐級(jí)Arduino ADC的輸入阻抗約100MΩ會(huì)形成并聯(lián)導(dǎo)致測(cè)量值偏低。需要使用運(yùn)放緩沖。6.3 測(cè)量交流電壓或負(fù)電壓注意測(cè)量市電220V AC極其危險(xiǎn)需要隔離和專業(yè)設(shè)備此處僅討論低壓交流信號(hào)如音頻信號(hào)。對(duì)于交流信號(hào)ADC無法直接測(cè)量負(fù)電壓。需要將信號(hào)“抬升”到0V以上。直流偏置電路使用兩個(gè)電阻創(chuàng)建一個(gè)Vcc/22.5V的虛地。交流信號(hào)通過一個(gè)電容耦合到這個(gè)2.5V的偏置點(diǎn)上這樣信號(hào)就以2.5V為中心上下波動(dòng)全部處于0-5V范圍內(nèi)。Vcc (5V) ---[R_a]--- Vbias (2.5V) ---[C]--- 信號(hào)輸入 | | [R_b] [到A0] | | GND GND其中 R_a R_b 例如10kΩ。電容C用于隔直通交容值根據(jù)信號(hào)頻率選擇如1uF用于音頻。運(yùn)算放大器電路使用單電源運(yùn)放如LM358搭建一個(gè)加法器電路將交流信號(hào)與一個(gè)直流偏置電壓相加更為靈活精準(zhǔn)。代碼處理讀取到的ADC值會(huì)圍繞512對(duì)應(yīng)2.5V上下變化。需要先減去512再換算成電壓才能得到交流信號(hào)的瞬時(shí)值。要還原波形需要高速采樣。關(guān)于負(fù)電壓同樣需要先用運(yùn)放電路將負(fù)電壓平移加一個(gè)正電壓到正范圍或者使用絕對(duì)值電路整流后再測(cè)量。6.4 選擇外部ADC模塊當(dāng)項(xiàng)目對(duì)精度、速度或多通道同步有更高要求時(shí)就需要外部ADC模塊如ADS111516位I2C接口。為什么選它高精度16位分辨率在±4.096V量程下分辨率低至0.125mV遠(yuǎn)高于內(nèi)置ADC的4.9mV。差分輸入可以測(cè)量?jī)蓚€(gè)引腳之間的電壓差能有效抑制共模噪聲。可編程增益放大器PGA可以放大微小信號(hào)直接測(cè)量mV級(jí)電壓。I2C接口節(jié)省引腳易于連接。使用心得雖然精度高但對(duì)噪聲也更敏感。必須做好PCB布局和濾波。其參考電壓是內(nèi)部的非常穩(wěn)定。庫函數(shù)如Adafruit_ADS1X15很好用但要注意設(shè)置正確的量程setGain。量程設(shè)得太小輸入超限會(huì)飽和設(shè)得太大會(huì)損失精度。對(duì)于慢變信號(hào)如溫度、電池電壓ADS1115的連續(xù)轉(zhuǎn)換模式可能有點(diǎn)“殺雞用牛刀”單次轉(zhuǎn)換模式更省電。從內(nèi)置ADC到外部高精度ADC是電壓測(cè)量從“能用”到“好用”的關(guān)鍵一步。理解每一層原理背后的“為什么”才能在各種實(shí)際場(chǎng)景中靈活運(yùn)用做出穩(wěn)定可靠的數(shù)據(jù)采集系統(tǒng)。