2026-08-30

使用光敏電阻製作提示器

最近有位視障朋友拜託我製作一款提示器,希望能在櫃雪門沒關好時發出警示。
由於市面上常見的家用櫃雪內部都有照明燈,因此在下嘗試使用光敏電阻作為感應器,
藉由偵測光線變化來判斷櫃雪門的開閉狀態。

外觀

光敏電阻與一般電阻相似,同樣只有兩個引腳,且安裝時不分正負極方向。

測試效果

光敏電阻是一種電阻值會受亮度改變的電子零件:亮度越高電阻值越低;反之電阻值越高。

在下使用電筒直接照射時,電阻值最低可降至約 400Ω ;而在完全遮蔽光源的極致黑暗下,電阻值則高達 20MΩ以上 。
(超過了萬用錶上限為 20MΩ 的測量範圍。)

線路原型

製作原型時 不能直接將光敏電阻 接在 參考電壓(Voltage Reference)類比輸入(Analog-Digital Conveter, ADC) 引腳 之間。
因為沒有分壓,ADC引腳 只會一直讀到接近 參考電壓 的數值(以 Raspberry Pi Pico 為例,就是持續讀到接近 65535 的上限值)。
線路上必須搭建 分壓電路(Voltage Divider) ,並將 ADC引腳 連接至分壓電路的中間點,才能正確讀取類比訊號亮度變化。

import machine, time
adc = machine.ADC(26)
while True:
	print(adc.read_u16())
	time.sleep(0.1)

測試效果。
由於實際環境中仍然會些許折射光線,即使遮蓋光敏電阻的感光區域,因此讀取到的 類比訊號 不會完全降至 0 。

import machine, time
adc = machine.ADC(26)
led = machine.Pin("LED", machine.Pin.OUT)
while True:
	value = adc.read_u16()
	print(value)
	led.value(value < 40960)
	time.sleep(0.1)

MicroPython 的 ADC 採用 16位元解析度,讀取數值範圍為 0 至 65535 。
編寫程式邏輯前,需要先實測不同光照環境下的數值 (例如雪櫃關門與開門時的環境亮度),進而找出合適的 臨界值(Threshold)
確認 臨界值 後,就能以此作為基準,當讀取值 高於或低於臨界線 時,分別觸發對應的處理程序。

確定操作原理後,便能根據邏輯來撰寫程式。整體運作流程如下:

  • 持續偵測:裝置保持監控狀態。
  • 開門觸發:當偵測到開啟雪櫃門時,發出 1次短提示音,代表已感應到開門,計時器開始倒數。
  • 關門重置:當偵測到雪櫃門關閉時,發出 2次短提示音,代表已感應到關閉,計時器重置倒數。
  • 逾時警示:若雪櫃門未關閉至倒數結束,裝置循環警示:
    1. 發出 1秒長提示音。
    2. 暫停指定時間。
import machine
import time
res = machine.ADC(26)
# GPIO
led = machine.Pin(25, machine.Pin.OUT)
is_open = False
previous_time = 0
# 亮度臨界值
LIGHT_THRESHOLD = 40960
# 超時秒數
TIMEOUT_THRESHOLD = 5
# 循環秒數
CYCLE_THRESHOLD = 3
def signal(times):
	for i in range(times):
		if i > 0:
			time.sleep_ms(100)
		led.value(True)
		time.sleep_ms(100)
		led.value(False)
while True:
	value = res.read_u16()
	current_time = time.ticks_ms()
	if value < LIGHT_THRESHOLD:
		if is_open:
			is_open = False
			signal(2)
	else:
		if not is_open:
			is_open = True
			signal(1)
			previous_time = current_time
		elapsed_time = time.ticks_diff(current_time, previous_time) // 1000
		if elapsed_time >= TIMEOUT_THRESHOLD:
			cycle_time = elapsed_time % CYCLE_THRESHOLD
			if not led.value() and cycle_time < 1:
				led.value(True)
			elif led.value() and cycle_time >= 1:
				led.value(False)
	time.sleep_ms(50)

(請特別留意 板載LED 的閃動狀態。)

萬用板線路

測試完成後,只需將控制 板載LED 的 GPIO25 修改為其他 GPIO ,並連接到 蜂鳴器(Buzzer) 便可以讓視障朋友試用。
另外還可以修改 亮度臨界值 來改變敏感度;修改 超時秒數 來改變開門倒數時間;修改 循環秒數 來改變提示器頻率。

此外,程式中保留了參數調整空間:

  • 亮度臨界值(Threshold):調整感測敏感度,以適應不同冰箱內部的燈光亮度。
  • 超時秒數(Timeout):自訂開門後的計時倒數時間。
  • 循環秒數(Interval):自訂提示音間隔的頻率。

為了方便朋友實際使用,在下將所需零件焊接在萬用板上。

因為控制主板不需要放進雪櫃,只有光敏電阻需要延伸到雪櫃內部偵測亮度,
所以在下在光敏電阻兩端焊接了約 2米的跳線,方便將感應器延伸安裝。

由於跳線的焊點比較脆弱,在焊點處塗上 UV膠 來提升焊點強度。
同時,為了強化抗拉扯能力,將兩條跳線以 雙絞線(Twisted Pair) 的方式編織在一起。
另外,為了方便日後更換或重用光敏電阻,在下使用 插頭插座 的方式來進行連接。

補充資料

光敏電阻有許多不同的尺寸規格,這次專案選用的是 5528型號
數字 55 代表元件的直徑大小,例如:

  • 35 代表 直徑3毫米 。
  • 55 代表 直徑5毫米 。
  • 75 代表 直徑7毫米 。
  • 125 代表 直徑12毫米 。

28 表示亮電阻值大約 10kΩ 至 20kΩ 暗電阻值為 1MΩ 以上。
還有甚他編號:

編號 亮電阻 暗電阻
06 2kΩ 至 5kΩ 1MΩ
16 5kΩ 至 10kΩ 0.5MΩ
28 10kΩ 至 20kΩ 1MΩ
37-1 20kΩ 至 30kΩ 2MΩ
37-2 30kΩ 至 50kΩ 5MΩ
39 50kΩ 至 100kΩ 20MΩ
49 100kΩ 至 200kΩ 10MΩ

針對不同的環境選擇合適的光敏電阻,能達到更好的感測效果:

  • 16 型號:對微弱光線更敏感。
  • 39 或 49 型號:在高亮度環境下不易飽和。

不過在實際開發中,可以在程式中調整 臨界值 來改變敏感度,因此一般情況下選用哪一款光敏電阻差異並不算太大。
因此,在下選用規格較中性、通用性高的 5528光敏電阻 來測試。

總結

在下的視障朋友都是從事科技開發工作,了解運作原理及修改設定值後,已經能夠自行處理,
不過由於 MicroPython 需要使用 Thonny 或 RPEL 會比較麻煩,
因此如果開發第二版本,在下打算使用:

  • 加入 EEPROM.h 讓微控制器讀取 EEPROM 來設定資料,再配合 序列通訊 更新 EEPROM 來修改設定值
  • 改用 CircuitPython 能夠將 RP2040 當作一般USB儲存裝置直接修改code.py
  • 改用 Pico W 或 ESP32 等支援 WiFi 的微控制器,經網頁修改設定值

由於在下的視障朋友本身也是從事科技開發工作,在了解運作原理與參數修改方式後,已經能夠自行處理與設定。
不過,考慮到 MicroPython 必須透過 Thonny 或 REPL 環境連線修改,對一般日常操作來說還是稍微麻煩。
因此,如果要開發第二代,我打算有這些改動:

  • EEPROM 及 序列通訊:加入 EEPROM.h 讓微控制器從 EEPROM 讀取設定值,並搭配 序列命令 來更新。
  • 改用 CircuitPython:讓 RP2040 直接被電腦識別為 USB儲存裝置,令讓使用直接修改 code.py。
  • 改用 Pico W 或 ESP32:導入支援 WiFi 的微控制器,讓使用者以網頁界面 修改設定值。

硬件方面:

  • 改用 RCA:原本使用 USB Type-C,但 Type-C 太細小、手工焊接難度較高,
    而且這個專案亦不需要使用 USB Type-C 的資料傳輸功能,其實是浪費 USB Type-C ;
    改用 RCA 插頭插座 不僅焊接容易,且接點堅固耐用。
  • 改用紅黑平行線:跳線原本就不適合外露,且抗扯拉強度不足,即使做成雙絞線依然偏弱。
    改用強度較高的紅黑線不僅抗拉扯,而且雙線的結構也更方便沿著雪櫃邊緣鋪設。

不過現在其實已經有具備未關門提示的雪櫃,及貼在雪櫃門上的未關門提示裝置,因此在下的專案老早已經有發售。

參考資料

沒有留言 :

張貼留言