《ESP32 入門》ESP32 光敏電阻教學

使用 NodeMCU-32S(ESP32)搭配兩腳光敏電阻,透過分壓電路與 ADC 讀取環境光線強度。內容涵蓋電路原理、接線方式、Arduino 程式碼。

《ESP32 入門》ESP32 光敏電阻教學

前言

光敏電阻(LDR,Light Dependent Resistor或Photoresistor)是最入門、最實用的感測元件之一。它的阻值會隨著光線強弱改變,光線越強、阻值越低;光線越暗、阻值越高。搭配 ESP32 的 ADC(類比數位轉換器),我們可以輕鬆讀取環境光線強度,進而做出自動調光、夜燈感應、光控繼電器等應用。

本篇使用的是市面上最常見的兩腳光敏電阻(5mm 規格),不需要額外的感測模組,成本極低,非常適合初學者練習。


所需材料

材料 數量
NodeMCU-32S(ESP32) 1 片
兩腳光敏電阻(GL5528 或同規格) 1 個
電阻 10kΩ 1 個
麵包板 1 片
杜邦線(公對公) 數條
NodeMCU-32S 相容版本 ESP32開發板 WiFi 藍牙 可用Arduino IDE
全腳位引出,還保持迷你的身型,插上麵包後還能插杜邦線,真的是太棒了! 和NodeMCU V2幾乎一樣尺寸! 有5V供電輸出,非常方便! 有了ESP32開發板,真的可以忘記原來的那些Arduino板子了! 可以用Arduino IDE開發,但效能更強大,還內建WiFi 傑森實測記錄,大家可以到 F 粉 絲 團 B 看貼文哦! ESP32-D0WDQ6 內置兩個低功耗 Xtensa® 32-bit LX6 MCU。片上存儲包括: • 448 KB 的 ROM,用於程序啟動和內核功能
光敏電阻 光電開關 3根1組
最大電壓(V-dc):150 最大功耗(mW):100 環境溫度(°C):-30--- +70 光譜峰值(nm):540 亮電阻(10Lux)(KΩ):10-20 暗電阻(MΩ):1 100λ10:0.6 回應時間(ms):上升:20 下降:30 照度電阻特性:3
10個 1/4W 10KΩ 電阻DIP 插板電阻 碳膜電阻 1%
1/4W 10KΩ 本賣場一個單位是20根
400孔 麵包板 紅藍線 85x55mm Arduino 迷你麵包板 小麵包板
高品質麵包板 400孔,紅藍線 多次拔插也不會鬆動
ESP32S擴展板 適用於Nodemcu-32s 38Pin全引出
※ 不含ESP32S開發板,需另購! ESP32S專用擴展板 適用於Nodemcu-32s,其它型號都不相容哦!請留意。 38Pin全引出,無敵方便!

光敏電阻原理

光敏電阻本身沒有正負極,兩腳可以任意接線。它的核心原理是利用半導體材料(通常是硫化鎘 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 轉換 → 程式判斷 這條鏈路的最佳入門元件。掌握它之後,溫度感測、土壤濕度、聲音感測等模組的邏輯都是同樣的思路,舉一反三非常容易!