小夜燈

晚上會自動點亮的小夜燈要用到光敏電阻,這個小元件可以根據光線強弱來改變電阻值,光線越強電阻值越低;光線越暗電阻值越高,因此這是一個類比感測元件,可以接到 Pico 的 ADC0、ADC1 與 ADC2 這三隻類比輸入腳。

這裡打算設計一個特殊的小夜燈,可以根據不同地點的環境光強度自動決定開關小夜燈時機,另外小夜燈的亮度使用 PWM 來控制,因此可以做到多段亮度變化,而不是只有亮與滅兩種狀態。線路接法如下,其中黃色線接到類比腳 ADC2。與光敏電阻相連的10KΩ電阻,若阻值太小或不接,會導致收到的數值區間太窄,較不易分辨目前環境光強弱變化,所以建議接一個大一點的電阻。

picow_light_sensor_bb

程式碼如下。

from machine import *
from utime import *

light_sensor = machine.ADC(2)
led = PWM(Pin(0))
led.freq(1000)

max = -1
min = 65536
max_level = 4

while True:        
    value = light_sensor.read_u16()

    if value > max:
        max = value
    elif value < min:
        min = value

    # mapping
    new_value = int((value - min) * 65535 / (max - min))
    level = int(new_value / 65535 * max_level)
    # PWM output
    led.duty_u16(int(level * 65535 / (max_level - 1)))
    
    print(str((min, max, value)) + ' => ' + str((0, 65535, new_value, level)))
    sleep(0.5)

程式邏輯為首先透過 light_sensor.read_u16() 得到目前透過光敏電阻取得的環境光強弱數據,數據範圍為 0 到 65535 之間的整數,但實際上當然不可能是這個範圍,根據光敏電阻的規格,數值範圍可能落在3萬到5萬間,接下來的條件判斷會記錄到目前為止收到的最小值與最大值。

在 mapping 註解下方的程式碼是用來將目前取得的光敏電阻數值,配合目前記錄到的最小值與最大值,重新對映到 0 到 65535 的區間內,也就是將 “min | value | max” 對映成 “0 | new_value | 65535″,目的是將原有的數值範圍拉到一個固定的範圍內也就是標準化。然後再根據 max_level 的值來等分 0 到 65535 區間。以 max_level = 4 而言,會等分成四份,也就是 0、65535*1/4、65535*2/4、65535*3/4、65535,有了區間後計算目前收到的光敏電阻值會落在哪一個區間內並放到 level 變數中,所以 level 的內容為 0 到 4 間的整數。由於採用無條件捨去小數的關係,最後 level 的結果幾乎不會出現 4 這個數字,所以最大值會落在 3,也就是 max_level – 1。

最後根據目前的 level 值,轉換成對映的 PWM 訊號值,由於 Pico 的 PWM 範圍剛好也是 0 到 65535,所以若 level = 0,就將 PWM 設定為 0,若 level = 1,則將 PWM 設定為 65536 *1/3,以此類推。如此一來,這時 LED 的亮度就有四種變化了:全暗、1/3 亮度、2/3 亮度、全亮。

★本系列收錄於「第一次就上手」選單

發表迴響