raspberrypi 官網 raspberrypi 官網

互動 IoT 系統應用 - 上課教材

互動 IoT 系統應用 > 課程內容 > 第 07 章 - 三色 LED 燈感測器互動

第 07 章 - 三色 LED 燈感測器互動

上次更新日期 2022/11/03

前一章我們大概了解了單色 LED 燈在樹莓派的安裝與操作,加上 gpiozero 模組的協助,很容易控制多顆 LED 燈。 那如果需要混色燈光呢?可能就得要三色 LED 燈的支援。三色 LED 燈就是 RGB 三原色的燈,共有四隻腳,除了一隻腳位在接地之外, 其他三隻當然就是三原色了。此外,為了增加跟環境的互動,透過一些額外的感測器來處理環境因素,也是相當重要的應用。

學習目標:

  1. 認識與應用三色 LED 燈
  2. 認識與使用光敏電阻
  3. 結合 LED 燈與光敏電阻

7.1: 認識與應用三色 LED 燈

除了單一顏色的 LED 燈之外,其實還有可以控制 RGB 三原色的三色 LED 燈喔!這種燈若搭配可調整的電力輸出, 那麼,就以搭配成為多種特殊顏色的燈光了!一顆燈可以玩很久~顏色也能夠做比較多的變化!

三色 LED 燈使用的就是電腦的三原色,那就是 RGB (紅綠藍)。若再加上接地線,那麼就總共有 4 個針腳了!這個三色 LED 燈可以查看一下底下的圖示, 該圖示來自 https://2blog.ilc.edu.tw/868/44309/ 網頁的圖示內容。 感謝廣大的網友們。要注意的是,最長針腳通常是用來接地使用,因此其他 RGB 三個腳位則是接在樹莓派 GPIO 針腳上面。

三色 LED 燈示意圖

一般來說,燈號接上樹莓派,最好還是加上電阻器來避免 LED 燈燒毀。不過,就如同前一章後面運作時所提到的,短時間操作的話, 就可以先不要使用電阻器。那如果真要接電阻時,三色 LED 燈的 RGB 腳位搭配到電阻器,有兩種接法,一種是使用 3 個電阻, 分別接在樹莓派 GPIO 腳位上,再接到 LED 的 RGB 上面,而接地則直接接在接地針腳上。另一種接法則是將接地透過電阻器, 其他三個直接接到樹莓派 GPIO 上!這樣也是可以的。

例題 7.1.1: 請將三色 LED 燈安插到樹莓派,大致上可以讓常見的 RGB 三色分別對應到 31, 33, 35 上面,然後讓接地接到 39 上, 在實作上面比較簡單。安裝完畢之後,請到 gpiozero 官方文件上面找到 RGBLED 的模組,如下連結: 請依據上述連結,建立名為 ~/3led/3led-1-1.py 的檔案,讓該程式碼完成:(請單純使用 .red, .green, .blue 先完成這個題目, 之後的題目才開始使用 .color 喔!)
  • 亮紅燈後延遲一秒
  • 亮綠燈後延遲一秒
  • 亮藍燈後延遲一秒
  • 上述燈號循環不斷出現 (迴圈)
  • 使用 .blink 的功能

跟前面的 LED 燈號類似,gpiozero 同樣三色 LED 燈一個名為 blink 的函數,使用方式與 LED 燈相同!官網提供的指令資訊如下:

blink(on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, 
  on_color=(1, 1, 1), off_color=(0, 0, 0) )

上述指令非常方便使用!來測試一下底下這題:

例題 7.1.2: 因為有淡入/淡出的功能,請重新設計 3led-1-1.py 成為 3led-1-2.py,完成底下的設定:
  • 設計一個變數,假設名為 dtime,這是每個顏色的延遲時間
  • 使用 dtime/2 秒淡入用 dtime/2 秒淡出。
  • 延遲 dtime 後換下一個顏色
直到使用者停止 (ctrl-c) 為止。若可能的話,也能將顏色變成紅、黃 (紅+綠) 、綠等特別顏色~

事實上,這個功能也可以使用 pulse 來取代!使用的方式如下:

pulse(fade_in_time=1, fade_out_time=1, on_color=(1, 1, 1), off_color=(0, 0, 0))
  • 使用亂數隨機產生顏色

單純的搭配三色 LED 燈的顏色,主要是這樣:

led.color = (red, green, blue)

那麼三種顏色的混色之後,能不能隨機產生顏色呢?可以的,這時可能就得要使用 random() (亂數) 函數的處理了! 亂數函數的處理有非常多種方式,這裡我們單純使用一個 0~1 之間的浮點數模式來處理,因為剛剛好我們的 .color 顏色使用的就是 0~1 的強度! 簡單的亂數可以這樣使用:

import random

mycolor = random.random()

現在,請搭配上述的指令來實作出隨機顏色的變化:

例題 7.1.3: 將 3led-1-2.py 複製成 3led-1.3.py,程式碼內部變化:
  • 透過亂數分別產生 rr, gg, bb 代表三顏色的數據 (如果沒有接電阻可能會太亮,建議數值可以除以 2 )
  • 螢幕輸出三種顏色的數值強度
  • 讓三色 LED 燈光產生上述顏色,然後延遲 2 秒。
  • 循環上述的動作。

7.2: 使用光敏電阻

先來討論一個光敏電阻的玩意兒,光敏電阻顧名思義,就是跟光有關的電阻。一般來說,當光線越強, 光敏電阻內部的電流可以放大,亦即電阻值變小,因此有光線的情況底下,電壓的強度會增加。當沒有光線時, 電阻變大,電壓自然就比較小了。

光敏電阻既然名為電阻,所以,兩隻腳當然就需要一個電力迴路!gpiozero 建議使用 3.3V 搭配接地即可。 只是,光敏電阻傳輸的資料基本上是類比訊號,因此使用樹莓派僅有的數位接腳只能讀取到 0/1 這樣的數據而已。 那怎麼偵測流過光敏電阻的 0/1 數據?我們很簡單的從樹莓派 GPIO 上面連接一條線到光敏電阻與電阻器相連結的那個麵包板群祖上即可。 你可以參考底下的 gpiozero 官網連線建議圖:

例題 7.2.1: 連結光敏電阻並讀取數據,請拿出一個電阻、一個光敏電阻、三條杜邦線
  • 樹莓派 3.3V(J8:1) --- 麵包板 --- 光敏電阻一腳
  • 光敏電阻另一腳 --- 麵包板 --- 10K 電阻
  • 10K 電阻另一腳 --- 麵包板 --- 樹莓派接地(這裡用 J8:9 號)
上面就是一個完整的迴路!先確認沒問題之後,然後另一條杜邦線從 J8:8 連接到電阻器的任何一腳同群組的麵包板上即可。 我們將透過 J8:8 (也就是GPIO14) 讀取光敏電阻的數值。設計 3led-2-1.py 程式,內容有點像這樣:
  • 匯入 LightSenrot 模組
  • 設定變數 lsensor 為 LightSensor("J8:8") 這樣的格式
  • 將光敏電阻的數值每 1 秒鐘讀出後,印出到螢幕上

我們提供的電阻有兩種形式,一種是一般的 1K 電阻,一種是 10K 的精密電阻,在這個範例當中使用的是 10K 精密電阻! 在連接線上面要特別注意喔!否則數據就會無法順利顯示。另外,因為是類似數位訊號,因此,只有 0/1 這兩個數據而已! 所以,你會發現到,只要遮住光敏電阻一點點,回傳值就會是 0,否則就是 0.8 以上的數據 (大部分都是 0.9 以上), 這點與 arduino 的類比訊號差很多!在這裡特別提醒。

  • wait_for_dark(), wait_for_light() 的使用

那如果你只需要等待光亮或變暗的情況,那可以直接使用 wait_for_dark() 以及 wait_for_light() 的函數, 例如底下的 3led-2-2.py 的內容:

$ vim 3led-2-2.py
from gpiozero import LightSensor

lsensor = LightSensor("J8:8")

lsensor.wait_for_dark()
print("OK! dark")
lsensor.wait_for_light()
print("OK! light")

$ python 3led-2-2.py

開始執行之後,用手遮一下光敏電阻,然後放開,你應該就可以看到螢幕上面顯示的資訊了!非常簡單!

  • 透過 .light_detected 進行處理

有時候我們可能是需要檢測一下目前是亮的還是暗的,倒不是一直在等待偵測中,這時就可以使用 if 搭配 .light_detected。 事實上,.light_detected 只會回傳 True 或 False 而已,所以使用搭配上面也挺方便的:

$ vim 3led-2-3.py
from gpiozero import LightSensor

lsensor = LightSensor("J8:8")

while True:
  if lsensor.light_detected:
    print("OK! light")
  else:
    print("No! dark")
  sleep(1)

$ python 3led-2-3.py

這樣就每秒檢測一次是否有亮光~

7.3: 當週實做

將 LED 與光敏電阻整合起來,當偵測到有光線時,則顯示 80% 紅燈,而當沒有燈光時,則顯示 20% 藍光。 每隔 1 秒偵測一次!設計程式檔名為 3led-3-1.py,完成之後請呼叫老師,作為一次實習成績。

  • 參考資料
  1. gpiozero 官網:https://gpiozero.readthedocs.io/en/stable/recipes.html#full-color-led

...