National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 06

讀取類比訊號:ADC

可變電阻、光敏電阻與 12 位元的讀值
Interaction 25 minute(s)

Learning Objectives

  • 說明 ADC 如何把電壓換成數字,以及 12 位元代表 0~4095
  • 把可變電阻、光敏電阻接成分壓電路,用 machine.ADC 讀取
  • 分辨 read()、read_u16()、read_uv() 的範圍,並說明衰減設定的作用
  • 用讀值控制 LED 亮度,並用兩個門檻(遲滯)做出不會一直閃的夜燈

世界不是只有 0 與 1

第 04 課的按鈕只有按下與放開兩種狀態,這是數位訊號。但很多感測器輸出的是連續變化的電壓: 旋鈕轉到一半是 1.65V、光線越亮電壓越高、溫度升高電壓跟著變,這是類比訊號。

微控制器的 CPU 只會處理數字,所以需要類比數位轉換器(ADC,Analog-to-Digital Converter): 量一次腳位的電壓,換成一個整數。

12 位元:把電壓切成 4096 格

ESP32 的 ADC 是 12 位元,讀值範圍是 0~4095(2¹² = 4096 種值)。可以想成把量測範圍切成 4096 格:

讀值 ≈ 電壓 ÷ 量測上限 × 4095

假設量測上限是 3.3V:
0V    → 0
1.65V → 約 2047
3.3V  → 4095
每一格約 3.3V ÷ 4096 ≈ 0.8 mV

格子越細,量得越精細,這叫解析度。電壓介於兩格之間時只能取其中一格,這個誤差叫量化誤差。 數字的二進位表示可以對照「計算機概論」軌的數字系統。

可變電阻與光敏電阻怎麼接

可變電阻(電位器)有三支腳:兩端接 3.3V 與 GND,中間的腳(滑動端)接到 ADC 腳位。 轉動旋鈕時,中間腳的位置在電阻上移動,電壓就在 0V 到 3.3V 之間變化。這種接法叫分壓,「自造者入門」軌第 04 課會算給你看。

3.3V ──┐
       ╪ 可變電阻 ←── 中間腳接 GPIO34
GND  ──┘

光敏電阻(LDR)只有兩支腳,電阻值隨光線改變。和一顆固定電阻(例如 10kΩ)串聯成分壓電路, 中間點接 ADC,光線改變時中間點的電壓就跟著變。本課的接法是「越亮讀值越大」,接法反過來,讀值也會反過來。

接到 ADC 腳位的電壓不可以超過 3.3V。可變電阻的兩端要接 3.3V,不要接 5V。

ESP32 有兩組 ADC

組別 腳位 注意
ADC1 GPIO32~39 隨時都能用
ADC2 GPIO0、2、4、12~15、25~27 Wi-Fi 開啟時不能用,讀取會出現例外

之後的課要連 Wi-Fi,所以類比感測器一律接 ADC1。GPIO34~39 只能當輸入,剛好適合接感測器。

machine.ADC:三種讀法與衰減

from machine import Pin, ADC

pot = ADC(Pin(34))
pot.atten(ADC.ATTN_11DB)     # 設定衰減
pot.read()                   # 0~4095:原始讀值(依解析度)
pot.read_u16()               # 0~65535:換成 16 位元的範圍,不同開發板寫法一致
pot.read_uv()                # 校正過的電壓,單位是微伏(μV)

衰減(attenuation)決定能量多高的電壓。不衰減時 ADC 只能量到大約 0.95V,衰減會先把輸入的電壓縮小再量,所以能量的範圍變大。 MicroPython 官方文件列出 ESP32 大約的線性範圍:

設定 大約可量的範圍
ADC.ATTN_0DB 100 mV~950 mV
ADC.ATTN_2_5DB 100 mV~1250 mV
ADC.ATTN_6DB 150 mV~1750 mV
ADC.ATTN_11DB 150 mV~2450 mV

接 0~3.3V 的感測器通常設 ATTN_11DB。注意兩端:大約 100 mV 以下會讀成 0,接近 3.3V 時讀值也不準。 需要準確的電壓時用 read_uv(),它用晶片裡的校正資料換算,但也只在線性範圍內準確。

本站的模擬器把 0~3.3V 簡單地對應到 0~4095,方便看懂數字;真的 ESP32 讀值在兩端會偏離直線,而且每次讀都會有一點雜訊。

逐步看:讀可變電阻

旋鈕從 0 轉到底(上方的可變電阻顯示目前的比例)。每一圈用三種方法讀同一個電壓,比較它們的範圍。

逐步看:旋鈕調光

輸入接到輸出:讀旋鈕的位置,直接當作 LED 的工作週期。旋鈕先轉大、再轉回來,LED 跟著變亮又變暗。

夜燈:一個門檻不夠

做一個天黑自動開燈的夜燈,最直覺的寫法是一個門檻:

if ldr.read() < 1400:
    lamp.value(1)
else:
    lamp.value(0)

問題是黃昏時光線在門檻附近,加上讀值本身有雜訊,讀值會在 1390、1410 之間跳來跳去,燈就一直閃。

解法是用兩個門檻:低於 DARK 才開燈,高於 BRIGHT 才關燈,兩者之間維持原本的狀態。 兩個門檻中間的這段緩衝叫遲滯(hysteresis),冷氣的溫控、水塔的抽水馬達都用同樣的想法。

逐步看:有遲滯的夜燈

光線先變暗、再慢慢變亮。注意讀值在 1200~1600 之間時,燈維持上一次的狀態:變暗的途中維持暗,變亮的途中維持亮。

互動練習:旋鈕控制亮度與角度

電路上有可變電阻(GPIO34)、LED(GPIO23)與伺服馬達(GPIO18)。模擬時旋鈕會從 10% 轉到 90%, 你也可以在「輸入設定」拖曳滑桿,改變開始與結束的位置。依序完成任務:

  1. 直接執行起始程式,看讀值的變化。
  2. 讓 LED 的亮度跟著旋鈕變化(旋鈕轉到 30%,亮度大約 30%)。
  3. 讓伺服的角度也跟著旋鈕:0% 是 0 度,100% 是 180 度(伺服的換算在第 05 課)。
  4. 回答一個問題。

小測驗:解析度與範圍

1.

ESP32 的 ADC 是 12 位元,read() 最大會回傳多少?

2.

假設 0~3.3V 線性對應 0~4095,下面的程式會印出什麼?

raw = 1241
print(round(raw / 4095 * 3.3, 2))
3.

要把 0~3.3V 的感測器電壓盡量量完整,衰減應該設成哪一個?

第 1 次作答

小測驗:讀法與門檻

1.

下面模擬有遲滯的夜燈:readings 是依序讀到的光線值,會印出什麼?

readings = [1500, 1100, 1300, 1700, 1400]
lamp = 0
for v in readings:
    if v < 1200:
        lamp = 1
    elif v > 1600:
        lamp = 0
    print(lamp, end=" ")
2.

想用旋鈕直接控制 PWM 的工作週期,哪一種讀法最方便?

第 1 次作答

重點整理

  • ADC 把電壓換成整數;ESP32 是 12 位元,read() 範圍 0~4095。
  • 可變電阻與光敏電阻用分壓接法接到 ADC 腳位;輸入電壓不可超過 3.3V。
  • read() 原始讀值、read_u16() 0~65535、read_uv() 校正後的微伏。
  • atten() 設定衰減:ATTN_11DB 可量的範圍最大,兩端(約 100 mV 以下、接近 3.3V)讀值不準。
  • ADC1(GPIO32~39)隨時可用;ADC2 在 Wi-Fi 開啟時不能用。
  • 用兩個門檻做遲滯,讀值在門檻附近時輸出才不會一直跳動。

下一課處理時間:程式在 sleep 的時候什麼都不能做,要怎麼同時閃燈、讀按鈕、讀感測器?

這一課完成了!
Next lesson:計時:不讓程式卡住
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。