關閉

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

本章完整介紹 Arduino Analog Input(類比輸入)與 ADC(類比數位轉換器)的基本原理,說明 Digital 與 Analog 訊號的差異、Arduino Uno 為什麼會回傳 0~1023,以及如何使用 analogRead() 讀取類比訊號。文章並透過 10K 可變電阻實作,示範 A0 接線、ADC 數值讀取、電壓換算、取樣平均與常見故障排除,適合 Arduino 初學者建立類比感測器應用基礎。

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

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

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

本章學習目標

Digital 與 Analog 有什麼不同?

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

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

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

類比訊號的讀值範例

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

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

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 的基本工作流程

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 供電、穩壓器、參考電壓與元件公差而略有不同。

使用 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

準備材料

可變電阻接線方式

可變電阻的兩側外腳形成固定電阻路徑,中間腳是滑動端,也是本實驗的 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 數,也要確認參考電壓、輸入範圍、取樣速度、線性度與雜訊表現。

Analog Input 的常見用途

常見錯誤與故障排除

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 相容時才可以直接連接。若輸出可能超過允許範圍、含負電壓或雜訊突波,必須先加入適當的訊號調理與保護電路。

本章實作練習

Challenge:製作簡易電壓顯示器

本章重點整理

下一章預告

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

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