第9章 Arduino Analog Input 與 ADC 原理:analogRead、0~1023 與可變電阻實作

發布日期: |更新日期:
文章主圖:第9章 Arduino Analog Input 與 ADC 原理:analogRead、0~1023 與可變電阻實作

本章將帶你認識 Analog Input(類比輸入)與 ADC(Analog to Digital Converter,類比數位轉換器)的基本原理,並實際使用 Arduino Uno 的 analogRead() 讀取可變電阻輸出的電壓變化。

你將了解數位訊號與類比訊號的差異、Arduino Uno 為什麼回傳 0~1023、如何把 ADC 數值換算成電壓,以及類比輸入腳位的安全限制。

本章以 Arduino Uno 與 10K 可變電阻為主要實作環境。Arduino Uno 的類比輸入腳位不可直接量測超過允許範圍的電壓,量測較高電壓時必須先使用適當的分壓與保護電路。

本章學習目標

  • 了解 Analog(類比訊號)的基本概念。
  • 理解 ADC 將電壓轉換成數位數值的工作原理。
  • 學會使用 analogRead() 讀取 Arduino Uno 的類比輸入。
  • 了解 Arduino Uno 的 10-bit ADC 為什麼回傳 0~1023。
  • 使用 10K 可變電阻完成第一個 Analog Input 實驗。
  • 學會將 ADC 數值換算成近似電壓。

Digital 與 Analog 有什麼不同?

Digital(數位)訊號只有有限的離散狀態。以 Arduino Uno 的一般數位輸入輸出為例,最常見的是 HIGH 與 LOW,也就是邏輯高電位與邏輯低電位。

按鍵是否按下、LED 是否點亮,通常可以用兩種狀態表示,因此適合使用 Digital Input 或 Digital Output。

現實世界中的光線、溫度、濕度、聲音與旋鈕位置,通常不是只有開或關,而是會在一定範圍內連續變化。這類訊號稱為 Analog(類比)訊號。

Digital 與 Analog 訊號比較
比較項目 Digital(數位) Analog(類比)
訊號特性 以離散狀態表示 在範圍內連續變化
常見狀態 HIGH、LOW 不同電壓或感測值
常見元件 按鍵、開關、數位感測器 可變電阻、光敏電阻、溫度感測器
Arduino 常用函式 digitalRead()、digitalWrite() analogRead()

類比訊號的讀值範例

旋轉可變電阻時,輸出電壓會逐漸改變。Arduino 經過 ADC 轉換後,可能依序讀到 0、100、350、620、850、1023 等不同數值。

這些數值本身仍是離散的數位資料,但因為 ADC 將連續電壓切分成許多細小區間,所以可以用來近似表示類比訊號的變化。

知識卡:Analog
項目 說明
英文 Analog
中文 類比訊號
特性 在一定範圍內連續變化
Arduino 函式 analogRead()
Arduino Uno ADC 10-bit
Arduino Uno Analog Pins A0~A5

Arduino Uno 的 Analog Input 腳位

Arduino Uno 提供 A0、A1、A2、A3、A4、A5,共 6 個主要類比輸入腳位,可搭配 analogRead() 讀取外部電壓。

A4 與 A5 同時也是 I²C 通訊腳位,其中 A4 對應 SDA,A5 對應 SCL。使用時應確認程式是否同時需要 I²C 與類比輸入功能,避免腳位用途互相衝突。

ADC 是什麼?

ADC 是 Analog to Digital Converter 的縮寫,中文常稱為類比數位轉換器。

微控制器無法直接以程式處理連續電壓,因此 ADC 會先把輸入電壓轉換成一個數位數值。例如輸入電壓為 2.37V 時,Arduino Uno 可能將它轉換成約 485 的 ADC 數值。

程式透過 analogRead() 取得的是 ADC 轉換後的整數,而不是直接取得以伏特為單位的電壓。

ADC 的基本工作流程

  1. 外部元件輸出一個位於允許範圍內的電壓。
  2. Arduino Uno 的 ADC 取樣該電壓。
  3. ADC 依參考電壓與解析度,將輸入電壓量化成整數。
  4. analogRead() 將轉換結果回傳給程式。
  5. 程式可顯示、比較、換算或進一步控制其他元件。

Arduino Uno 為什麼回傳 0~1023?

Arduino Uno 的 ATmega328P 內建 10-bit ADC。10-bit 可以表示 2 的 10 次方,也就是 1024 個不同的量化階級。

因為數值從 0 開始計算,所以 analogRead() 的有效回傳範圍是 0~1023,而不是 0~1024,也不是 0~1000。

在預設參考電壓約為 5V 的情況下,數值 0 代表接近 0V,數值 1023 代表接近參考電壓。

解析度代表什麼?

解析度表示 ADC 可以把輸入範圍切分成多少個階級。Arduino Uno 的 10-bit ADC 有 1024 個階級,因此每一個階級約對應參考電壓的 1/1024。

若參考電壓以 5V 估算,每一個 ADC 階級約為 4.88mV。實際結果仍會受到供電電壓、參考電壓、雜訊與元件誤差影響。

電壓與 ADC 數值的關係

Arduino Uno 預設通常以板子的供電電壓作為 ADC 參考電壓。教學中常以 5V 作為近似值,因此可用 0~1023 表示約 0~5V 的輸入範圍。

下表為理想條件下的近似對照。實際量測值可能因 USB 供電、穩壓器、參考電壓與元件公差而略有不同。

Arduino Uno 電壓與 ADC 數值近似對照
輸入電壓 ADC 數值
0V 0
1V 約 205
2V 約 410
2.5V 約 512
3V 約 614
4V 約 819
5V 1023

使用 analogRead() 讀取類比輸入

analogRead() 用來讀取指定類比輸入腳位的 ADC 數值。以下程式每 500 毫秒讀取一次 A0,並將結果輸出到 Serial Monitor。

上傳程式後,開啟 Serial Monitor 並將鮑率設為 9600。若 A0 接收到變化中的電壓,畫面會顯示不同的整數。

int sensorValue;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  sensorValue = analogRead(A0);
  Serial.println(sensorValue);
  delay(500);
}

預期觀察結果

Serial Monitor 可能顯示 325、326、327、450、650、780 等數值。當輸入電壓改變時,讀值也會跟著改變。

即使輸入看似固定,ADC 數值仍可能在相鄰數值間小幅波動,這通常是電源、接線、環境雜訊與 ADC 本身量化造成的正常現象。

實作:使用可變電阻讀取 Analog Input

準備材料

  • Arduino Uno 開發板。
  • Breadboard(麵包板)。
  • 10K Potentiometer(10K 可變電阻)。
  • 杜邦線。
  • USB 傳輸線。

可變電阻接線方式

  1. 將可變電阻其中一側的外腳接到 Arduino Uno 的 5V。
  2. 將另一側的外腳接到 Arduino Uno 的 GND。
  3. 將可變電阻中間腳接到 Arduino Uno 的 A0。
  4. 確認 5V 與 GND 沒有短路後,再連接 USB 電源。

可變電阻的兩側外腳形成固定電阻路徑,中間腳是滑動端,也是本實驗的 Signal 輸出。旋轉旋鈕時,中間腳輸出的電壓會在接近 0V 與接近 5V 之間變化。

不同型號可變電阻的實體腳位排列可能不同,接線前應依元件標示或使用萬用電表確認,不要只依外觀猜測。

讀取可變電阻程式

const int POT_PIN = A0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int value = analogRead(POT_PIN);
  Serial.println(value);
  delay(100);
}

上傳程式並開啟 Serial Monitor 後,緩慢旋轉可變電阻。預期可以看到讀值在接近 0~1023 的範圍內變化。

若旋轉方向與數值增加方向相反,可交換可變電阻兩側外腳的 5V 與 GND 接線;中間腳仍需接到 A0。

如何把 ADC 數值換算成電壓?

當參考電壓以 5V 估算時,可將 analogRead() 的結果乘以 5.0,再除以 1023.0,得到近似電壓。

例如 ADC 數值為 512,換算結果約為 2.50V。使用浮點數 5.0 與 1023.0 可以避免整數除法造成小數部分被捨去。

const int POT_PIN = A0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int adcValue = analogRead(POT_PIN);
  float voltage = adcValue * 5.0 / 1023.0;

  Serial.print("ADC: ");
  Serial.print(adcValue);
  Serial.print("  Voltage: ");
  Serial.print(voltage, 2);
  Serial.println("V");

  delay(200);
}

參考電壓不是固定 5.00V

公式中的 5.0 是教學用近似值。實際 USB 供電或板上 5V 可能不是精確的 5.00V,因此換算結果不等同於精密電表量測值。

需要較準確結果時,可以先以萬用電表量測實際參考電壓,再把程式中的 5.0 改成量測值,並考慮電阻誤差、訊號雜訊與 ADC 校正。

Arduino Uno 能直接量測超過 5V 嗎?

不能直接量測。Arduino Uno 的類比輸入電壓不得高於其允許範圍,也不得低於 GND。將 12V 等較高電壓直接接到 A0,可能損壞 ATmega328P 或整塊開發板。

量測高於參考電壓的訊號時,必須先使用適當的分壓電路,必要時再加入限流、箝位、保險絲、隔離或其他保護措施。

設計分壓時除了計算比例,也要考慮輸入可能出現的最高電壓、電阻功率、公差與突波。接線前應先以萬用電表確認分壓輸出不會超過 Arduino 的允許範圍。

為什麼有些開發板會回傳 0~4095?

不同微控制器的 ADC 解析度不一定相同。12-bit ADC 有 2 的 12 次方,也就是 4096 個階級,因此常見回傳範圍為 0~4095。

部分 ESP32 開發環境常以 12-bit 讀值表示類比輸入,但實際有效精度、線性度、衰減設定與允許輸入範圍會受到晶片型號及設定影響,不能只依 0~4095 判斷量測品質。

比較不同開發板時,除了 bit 數,也要確認參考電壓、輸入範圍、取樣速度、線性度與雜訊表現。

10-bit 與 12-bit ADC 基本比較
比較項目 10-bit ADC 12-bit ADC
量化階級 1024 4096
常見數值範圍 0~1023 0~4095
理論解析能力 較低 較高
實際精度 仍受參考電壓、雜訊與硬體特性影響 仍受參考電壓、雜訊與硬體特性影響

Analog Input 的常見用途

  • 讀取可變電阻與旋鈕位置。
  • 讀取光敏電阻(LDR)分壓後的光線變化。
  • 讀取 LM35、TMP36 等類比溫度感測器。
  • 讀取土壤濕度感測器的類比輸出。
  • 讀取 Joystick(搖桿)的 X 軸與 Y 軸位置。
  • 讀取經適當偏壓與調理後的麥克風訊號。
  • 透過分壓與保護電路量測電池電壓。

常見錯誤與故障排除

analogRead() 一直讀到 0

先確認程式讀取的腳位與實際接線相同,例如程式使用 A0,訊號線也必須接到 A0。

確認可變電阻中間腳是否接到 A0、兩側外腳是否分別接到 5V 與 GND。若訊號端被直接接到 GND,讀值通常會接近 0。

ADC 數值一直停在 1023

A0 可能直接接到 5V、可變電阻接線錯誤,或輸入電壓已接近或超過參考電壓。

應立即確認輸入電壓是否在安全範圍內。若來源可能高於 Arduino 允許值,先斷電並檢查分壓與保護電路。

讀值大幅亂跳

常見原因包括 GND 未共地、訊號腳懸空、麵包板接觸不良、導線過長、電源雜訊或感測器輸出阻抗過高。

先檢查共地與接線,再縮短訊號線。必要時可加入適當的電容濾波、改善電源品質,或使用多次取樣平均降低波動。

讀值只有小幅變化

輸入電壓可能只在很小範圍內變動,或感測器輸出沒有涵蓋完整參考電壓範圍。

可先使用萬用電表量測輸入端的實際電壓,再確認感測器規格、分壓比例與程式所使用的參考電壓是否一致。

為什麼數值無法完全穩定?

ADC 量測出現少量波動通常是正常現象。電源雜訊、接線、周圍電磁干擾、參考電壓變動與 ADC 量化都可能影響讀值。

若應用需要穩定結果,可以使用多次取樣平均、中位數濾波、低通濾波、適當去耦電容與較穩定的參考電壓。

多次取樣平均範例

以下範例連續讀取 A0 十次,再計算平均值。這種方法可以降低部分隨機波動,但也會增加讀取時間,並不代表可以消除所有誤差。

const int SENSOR_PIN = A0;
const int SAMPLE_COUNT = 10;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  long total = 0;

  for (int i = 0; i < SAMPLE_COUNT; i++)
  {
    total += analogRead(SENSOR_PIN);
    delay(2);
  }

  float averageValue = total / (float)SAMPLE_COUNT;
  float voltage = averageValue * 5.0 / 1023.0;

  Serial.print("Average ADC: ");
  Serial.print(averageValue, 1);
  Serial.print("  Voltage: ");
  Serial.print(voltage, 2);
  Serial.println("V");

  delay(200);
}

Q&A

A0 可以當成數位腳位使用嗎?

在 Arduino Uno 上,A0~A5 通常也可以作為數位輸入輸出腳位使用,但使用方式與腳位編號應依 Arduino 核心定義與程式需求確認。本章重點仍是使用 analogRead() 進行類比輸入。

analogRead() 讀到的是電壓嗎?

不是。analogRead() 回傳的是 ADC 整數值。需要以參考電壓與 ADC 最大值進行換算,才能得到近似電壓。

為什麼換算後的電壓和萬用電表不同?

常見原因是程式假設參考電壓為 5.00V,但實際供電不是精確的 5.00V。另外,ADC、元件與萬用電表本身也都有誤差。

可先量測實際參考電壓,再修正換算常數;需要更高準確度時,還要進行校正並改善電源與訊號品質。

可以直接把感測器的 Analog Output 接到 A0 嗎?

只有在確認感測器輸出電壓範圍、GND 參考與 Arduino Uno 相容時才可以直接連接。若輸出可能超過允許範圍、含負電壓或雜訊突波,必須先加入適當的訊號調理與保護電路。

本章實作練習

  1. 使用可變電阻接到 A0,觀察旋轉時 ADC 數值的變化。
  2. 修改程式,同時顯示 ADC 數值與換算後的電壓。
  3. 記錄可變電阻轉到最小、中間與最大位置時的讀值。
  4. 比較單次讀取與十次取樣平均的穩定程度。
  5. 嘗試設定門檻值,例如 ADC 大於 700 時點亮 LED,低於 650 時熄滅 LED。

Challenge:製作簡易電壓顯示器

  • 使用可變電阻作為輸入。
  • 在 Serial Monitor 同時顯示 ADC 數值與換算後的電壓。
  • 輸出格式可設計為 ADC: 512 Voltage: 2.50V。
  • 觀察旋轉旋鈕時,ADC 數值與電壓如何同步變化。
  • 記錄實際 5V 電源電壓,並比較修正前後的換算結果。

本章重點整理

  • Digital 訊號以離散狀態表示,Analog 訊號會在一定範圍內連續變化。
  • ADC 負責將輸入電壓轉換成微控制器可以處理的數位數值。
  • Arduino Uno 使用 10-bit ADC,因此 analogRead() 常回傳 0~1023。
  • A0~A5 是 Arduino Uno 的主要類比輸入腳位,其中 A4 與 A5 也用於 I²C。
  • ADC 數值可依參考電壓換算成近似電壓,但實際精度受多種因素影響。
  • Arduino Uno 不可直接量測超過允許範圍的電壓,量測高電壓必須先分壓並加入保護。
  • 可變電阻是學習 Analog Input、ADC 與電壓換算最適合的入門元件之一。

下一章預告

下一章將介紹 PWM(Pulse Width Modulation)與 analogWrite(),說明 Arduino Uno 為什麼沒有一般用途的真正類比電壓輸出,以及如何利用 Duty Cycle(占空比)控制 LED 亮度與直流馬達速度。

完成 Analog Input 與 ADC 的學習後,你可以在下一章把可變電阻讀值映射成 PWM 輸出,製作旋鈕控制 LED 亮度的完整實驗。

相關資源與文章匯出
下載 Arduino 入門基礎教材 下載 DOCX PDF/列印

← 回文章列表