《ESP32 入門》ESP32 光敏電阻教學
使用 NodeMCU-32S(ESP32)搭配兩腳光敏電阻,透過分壓電路與 ADC 讀取環境光線強度。內容涵蓋電路原理、接線方式、Arduino 程式碼。
前言
光敏電阻(LDR,Light Dependent Resistor或Photoresistor)是最入門、最實用的感測元件之一。它的阻值會隨著光線強弱改變,光線越強、阻值越低;光線越暗、阻值越高。搭配 ESP32 的 ADC(類比數位轉換器),我們可以輕鬆讀取環境光線強度,進而做出自動調光、夜燈感應、光控繼電器等應用。
本篇使用的是市面上最常見的兩腳光敏電阻(5mm 規格),不需要額外的感測模組,成本極低,非常適合初學者練習。

所需材料
| 材料 | 數量 |
|---|---|
| NodeMCU-32S(ESP32) | 1 片 |
| 兩腳光敏電阻(GL5528 或同規格) | 1 個 |
| 電阻 10kΩ | 1 個 |
| 麵包板 | 1 片 |
| 杜邦線(公對公) | 數條 |





光敏電阻原理
光敏電阻本身沒有正負極,兩腳可以任意接線。它的核心原理是利用半導體材料(通常是硫化鎘 CdS)的光電導效應:
- 有光照射 → 載子增加 → 阻值下降(數百 Ω 至數 kΩ)
- 黑暗環境 → 載子減少 → 阻值升高(可達 1MΩ 以上)
為了讓 ESP32 能讀取它的變化,我們需要搭配一個固定電阻,組成一個分壓電路(Voltage Divider):
3.3V
│
[10kΩ 固定電阻]
│
├──→ GPIO34(ADC 讀取點)
│
[光敏電阻]
│
GND
光線越強 → 光敏電阻阻值越小 → GPIO34 分到的電壓越高 → ADC 值越大
光線越暗 → 光敏電阻阻值越大 → GPIO34 分到的電壓越低 → ADC 值越小
接線圖

⚠️ 注意:ESP32 的 ADC 輸入電壓最高為 3.3V,請勿接 5V,以免損壞晶片。
⚠️ GPIO34 為輸入專用腳位(Input Only),沒有內部上拉電阻,非常適合用來接 ADC 感測。
Arduino 程式碼
基礎版:Serial 監控光線數值
// ESP32 光敏電阻讀取範例
// 接線:3.3V → 10kΩ → GPIO34 → 光敏電阻 → GND
// 傑森創工 jmaker.com.tw
const int LDR_PIN = 34; // 光敏電阻接 GPIO34
void setup() {
Serial.begin(115200);
Serial.println("ESP32 光敏電阻測試開始");
}
void loop() {
int rawValue = analogRead(LDR_PIN); // 讀取 ADC 原始值(0~4095)
float voltage = rawValue * (3.3 / 4095.0); // 換算成電壓
// 將原始值映射成 0~100 的光線百分比
// ADC 值越大 = 光線越強
int lightPercent = map(rawValue, 0, 4095, 0, 100);
Serial.print("ADC 原始值: ");
Serial.print(rawValue);
Serial.print(" 電壓: ");
Serial.print(voltage, 2);
Serial.print("V 光線強度: ");
Serial.print(lightPercent);
Serial.println("%");
delay(500);
}
打開 Serial Monitor,鮑率設為 115200,遮住光敏電阻或對著它照手電筒,就能看到數值明顯變化:
- ☀️ 照光 → 數值趨近 100%
- 🌑 遮住 → 數值趨近 0%

進階版:自動夜燈(光控 LED)
當環境變暗時,自動點亮 LED;光線足夠時自動關閉。
// ESP32 光控自動夜燈
// 接線:3.3V → 10kΩ → GPIO34 → 光敏電阻 → GND
// LED:GPIO2(NodeMCU-32S 內建 LED)
// 傑森創工 jmaker.com.tw
const int LDR_PIN = 34;
const int LED_PIN = 2;
const int THRESHOLD = 500; // 閾值,可依環境調整(0~4095)
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
Serial.println("自動夜燈啟動!");
}
void loop() {
int rawValue = analogRead(LDR_PIN);
Serial.print("ADC 值: ");
Serial.print(rawValue);
if (rawValue < THRESHOLD) {
// 光線不足,點亮 LED
digitalWrite(LED_PIN, HIGH);
Serial.println(" → 環境昏暗,LED 亮起");
} else {
// 光線充足,關閉 LED
digitalWrite(LED_PIN, LOW);
Serial.println(" → 環境明亮,LED 熄滅");
}
delay(300);
}
💡 閾值調整技巧:先執行基礎版,記錄白天環境的 ADC 值和夜晚(或遮住時)的 ADC 值,取兩者中間的數字作為 THRESHOLD。
ESP32 ADC 使用注意事項
1. 12-bit 解析度
ESP32 的 ADC 解析度為 12-bit,數值範圍 0 ~ 4095,對應 0V ~ 3.3V。
2. ADC 非線性問題
ESP32 的 ADC 在接近 0V 和 3.3V 時會有非線性誤差。若需要精準電壓量測,建議使用 analogSetAttenuation() 調整衰減範圍,或加入校正補償。對於光線感應這類應用,原始值已相當夠用。
3. ADC2 與 WiFi 衝突
NodeMCU-32S 的 ADC 分為 ADC1(GPIO32~39)和 ADC2。當 WiFi 啟用時,ADC2 無法使用。因此建議光敏電阻接在 ADC1 的腳位,例如 GPIO34、GPIO35、GPIO36、GPIO39。
實驗延伸應用
掌握基本光線讀取後,可以嘗試以下進階應用:
- 🌙 智慧夜燈:結合繼電器,控制真實燈具
- 📊 光線記錄器:搭配 SPIFFS 將數值寫入檔案
- 📡 IoT 光線監控:透過 WiFi 將數值上傳 MQTT 或 Google Sheet
- 🖥️ OLED 顯示:即時在 SSD1306 顯示光線強度百分比
- 🎛️ PWM 調光:光線越暗,LED 亮度越高(模擬真實夜燈)
常見問題
Q:ADC 值一直是 0 或 4095,沒有變化?
A:檢查分壓電路接線是否正確,確認光敏電阻和 10kΩ 電阻都有確實接好,且 GPIO34 接在兩者中間的節點。
Q:遮住時反而是 100%,照光反而是 0%?
A:代表光敏電阻與 10kΩ 的位置和本文相反。最快的解法是修改程式,將 map(rawValue, 0, 4095, 0, 100) 改為 map(rawValue, 0, 4095, 100, 0) 即可,夜燈版的 THRESHOLD 判斷方向也要同步對調。
Q:讀到的數值跳動很大、不穩定?
A:可以在程式中加入多次取樣取平均來濾波:
int readAvg(int pin, int samples = 10) {
long sum = 0;
for (int i = 0; i < samples; i++) {
sum += analogRead(pin);
delay(5);
}
return sum / samples;
}
Q:可以直接把光敏電阻接 GPIO 當數位輸入嗎?
A:不建議。沒有分壓電路的話,腳位電壓不穩定,容易超出安全範圍。如果只需要判斷「有光/無光」,建議還是用分壓電路搭配 analogRead() 設定閾值,會比直接讀取數位訊號更穩定。
小結
| 重點 | 說明 |
|---|---|
| 光敏電阻類型 | 兩腳,無極性 |
| 接法 | 分壓電路(搭配 10kΩ) |
| 建議腳位 | GPIO34(ADC1,輸入專用) |
| ADC 解析度 | 12-bit(0~4095) |
| ADC 值越大 | 光線越強 |
| WiFi 注意 | 使用 ADC1 腳位避免衝突 |
光敏電阻雖然簡單,但它是理解 類比感測 → ADC 轉換 → 程式判斷 這條鏈路的最佳入門元件。掌握它之後,溫度感測、土壤濕度、聲音感測等模組的邏輯都是同樣的思路,舉一反三非常容易!




