Learning Objectives
- 分辨數位訊號與類比訊號,說明微控制器怎麼判斷高電位與低電位
- 說明輸入腳為什麼不能浮接,用上拉或下拉電阻讓按鈕的讀值穩定
- 用 ADC 讀取類比電壓,把讀值換算成電壓,說出解析度的意義
微控制器怎麼「看」電壓
前幾課都在算電壓與電流。微控制器的輸入腳也是在「看」電壓,只是看的方式有兩種:
| 數位(digital) | 類比(analog) | |
|---|---|---|
| 讀到的值 | 只有 0 或 1 | 一個範圍內的數字,例如 0~4095 |
| 適合 | 按鈕、開關、人體感測器的「有/沒有」 | 可變電阻、光敏電阻、溫度這種連續變化的量 |
| MicroPython | Pin(…, Pin.IN).value() |
ADC(…).read_u16() |
高電位與低電位的門檻
數位輸入並不是「3.3V 才算 1、0V 才算 0」,而是有門檻。以 ESP32 為例(官方規格書,電源 3.3V 時):
- 高於約 0.75 × 3.3V ≈ 2.5V 一定讀成 1(高電位)
- 低於約 0.25 × 3.3V ≈ 0.8V 一定讀成 0(低電位)
- 中間的電壓是灰色地帶,可能讀成 0 也可能讀成 1
所以接到數位輸入的訊號,要確實落在高或低的範圍裡。上一課的分壓電路把 5V 降到約 3.3V,就是為了讓它落在高電位的範圍、又不超過腳位能承受的電壓。
浮接:沒接東西的腳位會亂跳
按鈕最直覺的接法:一端接 GPIO,另一端接 GND,按下時 GPIO 被接到 0V。那放開的時候呢? 放開時 GPIO 什麼都沒接,這叫浮接(floating)。輸入腳幾乎不吃電流,周圍一點點的電場干擾(手靠近、旁邊的導線有訊號) 就能讓它的電壓忽高忽低,讀值在 0 與 1 之間亂跳,程式會以為按鈕被按了好多次。
解法是加一顆電阻,讓腳位在「沒有被按」時有一個確定的電壓:
上拉(pull-up) 下拉(pull-down)
3.3V 3.3V
│ │
[10kΩ] [按鈕]
├──── GPIO 放開=1,按下=0 ├──── GPIO 放開=0,按下=1
[按鈕] [10kΩ]
│ │
GND GND
- 上拉:電阻把腳位「拉」到 3.3V;按下按鈕時腳位直接接到 GND,變成 0。按下=0,程式要反過來判斷。
- 下拉:電阻把腳位拉到 GND;按下時接到 3.3V,變成 1。
- 電阻的作用是限制電流:按下按鈕時 3.3V 經過電阻接到 GND,10 kΩ 只讓 0.33 mA 流過;如果沒有電阻,按下就是短路。
內建的上拉、下拉
多數微控制器的腳位內建上拉、下拉電阻,用程式打開就好,不必另外接。ESP32 規格書寫的內建上拉、下拉約 45 kΩ:
btn = Pin(4, Pin.IN, Pin.PULL_UP) # 開啟內建上拉
btn = Pin(4, Pin.IN, Pin.PULL_DOWN) # 開啟內建下拉
例外:ESP32 的 GPIO34~39 只能當輸入,也沒有內建的上拉、下拉,接按鈕時要自己加電阻。
逐步看:開啟上拉電阻讀按鈕
按鈕接在 GPIO4 與 GND 之間,模擬時在 0.7~1.4 秒被按住(看上方電路畫面的按鈕)。 每 0.3 秒讀一次:放開時讀到 1、按住時讀到 0。
類比轉數位(ADC)
要知道「電壓有多高」,就要用類比數位轉換器(analog-to-digital converter,ADC)。它把 0~參考電壓之間的電壓,切成 2ⁿ 個等級,n 是位元數(解析度):
| 位元數 | 等級數 | 每一級約(3.3V 參考電壓) |
|---|---|---|
| 8 位元 | 256 | 12.9 mV |
| 10 位元 | 1024 | 3.2 mV |
| 12 位元 | 4096 | 0.81 mV |
- Raspberry Pi Pico(RP2040)的 ADC 是 12 位元,有 3 個可用的類比輸入腳;MicroPython 的
read_u16()一律把結果換算成 0~65535,不同板子可以用同一種算法。 - 換算電壓:電壓 ≈ 讀值 ÷ 65535 × 3.3(read_u16 的情況)。
- 再小的變化也只能落在某一級,這個誤差叫量化誤差。實際上還有雜訊與非線性,精確量測要校正,第 11 課會談感測器的校正。
- 可變電阻的兩端接 3.3V 與 GND、中間腳接 ADC,就是上一課的分壓電路:轉動旋鈕改變比例,中間腳的電壓跟著變。
注意:ADC 腳位能量的電壓不能超過開發板的工作電壓。要量 5V 或更高的電壓,先用分壓電路降下來。
逐步看:Pico 讀可變電阻
可變電阻的中間腳接在 GP26。模擬時旋鈕從 10% 慢慢轉到 90%,看讀值與換算出的電壓怎麼變。
小測驗:數位輸入
按鈕接在 GPIO 與 GND 之間,程式寫 Pin(4, Pin.IN),沒有開上拉也沒有外接電阻。放開按鈕時會讀到什麼?
ESP32 電源 3.3V,一個輸入腳的電壓是 1.6V,會讀到什麼?
上拉電阻接法(3.3V ─ 10 kΩ ─ GPIO ─ 按鈕 ─ GND),按住按鈕時,流過電阻的電流大約是多少?
小測驗:類比與 ADC
下面的程式會印出什麼?
raw = 32768
volts = raw / 65535 * 3.3
print(f"{volts:.2f} V")
一個感測器輸出 0~5V 的電壓,要接到 Pico 的 ADC 腳,該怎麼做?
重點整理
- 數位只有 0、1;類比是一段連續的電壓。數位輸入有門檻(ESP32:約 2.5V 以上是 1、約 0.8V 以下是 0),中間不保證。
- 輸入腳不能浮接:用上拉(放開=1、按下=0)或下拉(放開=0、按下=1)讓它有確定的電壓。
Pin.PULL_UP、Pin.PULL_DOWN打開內建電阻;ESP32 的 GPIO34~39 沒有內建的上拉、下拉。- ADC 把電壓切成 2ⁿ 個等級;12 位元、3.3V 時每一級約 0.81 mV。
read_u16()回傳 0~65535,電壓 ≈ 讀值 ÷ 65535 × 3.3。 - 超過 3.3V 的訊號先分壓再接到輸入腳或 ADC。
下一課介紹電容:它能儲存電荷、讓電壓慢慢變化,還能解決按鈕「按一下卻跳好幾次」的彈跳問題。