學習目標 : 認識色彩感應模組的功能及使用方式
學習時間 : 55mins
示範模組 : (1) faya brickNano
(2) faya 色彩感應模組
(3) faya RGB LED 模組
工具 : (1) 樂高底板(相容)
====================功能介紹====================
fayalab的色彩感應模組外觀如下所示,其核心為TCS3200,能將感測到的全彩光線編輯成相對應的頻率,透過微處理器計算其頻率後,判斷所感測的顏色。
TCS3200負責讀取彩色光的強度以及頻率的輸出,讀取到光的強度會以正比的方式轉換成相對應的頻率由輸出(OUT)埠輸出,輸出頻率的高低可通過兩個控制輸入腳位(S0、S1)進行縮放,讓輸出頻率能夠調整到適合微控制器讀取的頻段。晶片裡面有紅綠藍(RGB)三種濾光器,將接收到的光分成R/G/B三種成份,可由輸入腳位(S2、S3)來選擇讀取哪一種成分。
模組周圍的4顆白光LED負責打光照亮待測物體,待測物體反射出該物體的顏色,讓TCS3200進行分析,輸入埠(LED)可用來控制此4顆LED的開關。
- S0/S1 : 縮放輸出的方波頻率
- S1/S2 : 選擇分析的顏色
- LED : 控制四顆白光LED明暗, HIGH = 點亮、LOW = 熄滅
- OUT : 輸出和光強度成正比的方波頻率
以下補充解釋提供給有需要知道背後原理的人:
三原色原理 : 我們所看到的物體顏色,是由於物體表面吸收了照射到它上面的白光(日光)中的部分有色成分,沒有被吸收的部分,會反射出有色光在人眼中反應。白色是由各種頻率的可見光混合在一起構成的,也就是說白光中包含著各種顏色的色光(如紅R、黃Y、綠G、青V、藍B、紫P等等...)。
對於TCS3200而言,當選定一個顏色濾波器時,它只允許某種特定的原色通過,阻止其它原色的通過。例如:當選擇紅色濾波器時,入射光中只有紅色可以通過,藍色和綠色都被阻止,這樣就可以得到紅色光的光強度;同理,選擇其它的濾波器,就可以得到藍色光和綠色光的光強。通過這三個值,就可以分析投射到TCS3200 感測器上的光的顏色。
模組電路圖如下,輸入與輸出直接拉出使用,4顆白光LED透過NPN電晶體Q1來切換明暗狀態。輸入LED埠為HIGH時,Q1導通,LED點亮,反之LED熄滅。
======================範例實作======================
(2) 利用測出RGB值去判斷該顏色讓RGB LED顯示正確的顏色
Arduino_D11 ==> RGB LED模組_G
Arduino_D10 ==> RGB LED模組_B
Arduino_D9 ==> 色彩感應模組_S0
Arduino_D8 ==> 色彩感應模組_S1
Arduino_D7 ==> 色彩感應模組_S2
Arduino_D6 ==> 色彩感應模組_S3
Arduino_D5 ==> 色彩感應模組_LED
Arduino_D2 ==> 色彩感應模組_OUT
範例程式:
備註:
- 本程式範例可用來判斷紅、綠、藍、黃、白、黑6種顏色
- L47~48: 由datasheet得知當S0=0、S1=1時,輸出頻率會落在12KHz以下,將輸出頻率(速度)調低一點,讓Arduino能夠更精確的讀取其頻率值。
- L55~L57 : 先透過3個副程式,讀取待測物的R、G、B光強度的成份值
- L63~L71 : 讀取待測物R顏色光強度的成份值,由於光的強度和頻率成正比,我們先利用pulseIn函式讀取其輸出週期(微秒),將此週期乘上1,000,000改變單位為秒,再將之倒數得到輸出頻率。
- L54、58 : 讀取待測物的RGB光強度成份值前,我們先開啟4顆LED燈打光,完成讀取後,關閉LED燈,才不會讓白光LED持續開啟,避免刺眼。
- L59 : 取得RGB光強度的成份值後,就可以進行判斷偵測到哪個顏色的待測物,並且秀在RGB LED上。
- L95~L111 : 進行顏色的判斷,並且秀在RGB LED上。我們可以很確定的知道當待測勿接近紅色時,其紅色成份值一定比綠色和藍色大,因此我們利用次關係判斷了紅色,綠色和藍色的判斷也可套用同樣的邏輯。下片幾張圖是利用樂高積木在串列埠視窗中讀取到的RGB成份,另外提供三原色圖方便參考。
註:以下成份值的大小和量測的距離有關,我們的大測方式距離底板3個樂高積木的高度來量測,大家可在最後的影片中看到示範。
紅色積木 => R成份最大
綠色積木 => G成份最大
藍色積木 => B成份最大
-L113~117 : 由三原色圖中,我們可以知道黃色時由紅和綠混合而成的,因此R和G的成份一定比B大,但是如果只有用此規則判斷,可能會和紅色待測物的判斷 (L95~L99)或者綠色待測物的判斷 (L101~L105)產生衝突,因此我們透過串列埠視窗先了解讀取黃色樂高積木時,B的成份一定穩穩的小於 2000,因此多加了此判斷式,讓判斷沒有衝突。
-L119~124 : 白色集合了RGB的三個成份,RGB讀取值會接近最大值,我們同樣透過串列埠視窗先了解讀取白色樂高積木時,RGB的成份皆大於3000,因此用此判斷式判斷白色。
-L116~131 : 黑色將全部的光都吸收了,RGB讀取值會接近最小值,我們同樣透過串列埠視窗先了解讀取黑色樂高積木時,RGB的成份皆小於1000,因此用此判斷式判斷黑色。
範例結果:
討論:
也歡迎大家在底下留言或到我們的粉絲團留言喔!
====================================
fayalab 粉絲團
FB本篇留言版
TCS3200 對於擷取的顏色,是以不同頻率的方波輸出(50% duty cycle) 為結果,判斷一物體的顏色,需分三次取得三原色 ( RGB )。
對於TCS3200而言,當選定一個顏色濾波器時,它只允許某種特定的原色通過,阻止其它原色的通過。例如:當選擇紅色濾波器時,入射光中只有紅色可以通過,藍色和綠色都被阻止,這樣就可以得到紅色光的光強度;同理,選擇其它的濾波器,就可以得到藍色光和綠色光的光強。通過這三個值,就可以分析投射到TCS3200 感測器上的光的顏色。
模組電路圖如下,輸入與輸出直接拉出使用,4顆白光LED透過NPN電晶體Q1來切換明暗狀態。輸入LED埠為HIGH時,Q1導通,LED點亮,反之LED熄滅。
======================範例實作======================
目標:
(1) 使用顏色感應模組測出RGB值(2) 利用測出RGB值去判斷該顏色讓RGB LED顯示正確的顏色
接線:
(1) 電源線連接
Arduino_D12 ==> RGB LED模組_RArduino_D11 ==> RGB LED模組_G
Arduino_D10 ==> RGB LED模組_B
Arduino_D9 ==> 色彩感應模組_S0
Arduino_D8 ==> 色彩感應模組_S1
Arduino_D7 ==> 色彩感應模組_S2
Arduino_D6 ==> 色彩感應模組_S3
Arduino_D5 ==> 色彩感應模組_LED
Arduino_D2 ==> 色彩感應模組_OUT
範例程式:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 2017/02/9 | |
// Faya-Nugget 範例程式 (ColorSensor_1.ino) | |
// 單元: 模組介紹:faya 顏色感測模組 | |
// 網址:https://fayalab.blogspot.com/2018/02/colorsensor.html | |
// 目標: (1) 利用顏色感應模組測出物體的RGB值 | |
// (2) 將測出的RGB值顯示在RGB LED模組 | |
// 接線: Arduino ==> faya RGB LED模組 | |
// 12 ==> R | |
// 11 ==> G | |
// 10 ==> B | |
// 接線: Arduino ==> faya 色彩感應模組 | |
// 9 ==> S0 | |
// 8 ==> S1 | |
// 7 ==> S2 | |
// 6 ==> S3 | |
// 5 ==> LED | |
// 2 ==> OUT | |
//定義腳位 | |
#define LED_R 12 | |
#define LED_G 11 | |
#define LED_B 10 | |
#define S0 9 | |
#define S1 8 | |
#define S2 7 | |
#define S3 6 | |
#define LED 5 | |
#define OUT 2 | |
//預設RGB的輸出頻率為0 | |
int frequencyR = 0; | |
int frequencyG = 0; | |
int frequencyB = 0; | |
void setup() { | |
//設定腳位輸出為INPUT或OUTPUT | |
pinMode(S0, OUTPUT); | |
pinMode(S1, OUTPUT); | |
pinMode(S2, OUTPUT); | |
pinMode(S3, OUTPUT); | |
pinMode(LED, OUTPUT); | |
pinMode(LED_R, OUTPUT); | |
pinMode(LED_G, OUTPUT); | |
pinMode(LED_B, OUTPUT); | |
pinMode(OUT, INPUT); | |
// 設定頻率縮放到2% | |
digitalWrite(S0,LOW); // setting output frequency scalingx | |
digitalWrite(S1,HIGH); // 00 = power down ; 01 = 2%; 10=20%; 11=100% | |
//開啟通訊阜 | |
Serial.begin(9600); | |
} | |
void loop() { | |
digitalWrite(LED,HIGH); //開啟LED燈 | |
R_detect(); //偵測紅光成份 | |
G_detect(); //偵測綠光成份 | |
B_detect(); //偵測藍光成份 | |
digitalWrite(LED,LOW); //關閉LED燈 | |
Color_show(); // 判斷顏色並在RGB LED上顯示 | |
delay(500); | |
} | |
void R_detect() //偵測紅光成份 | |
{ | |
digitalWrite(S2,LOW); //開啟紅色濾光器 | |
digitalWrite(S3,LOW); | |
frequencyR = 1000000/pulseIn(OUT, LOW); // 讀取輸出頻率 | |
Serial.print("R= "); // 印出數值在通訊阜上 | |
Serial.print(frequencyR); | |
Serial.print(" "); | |
} | |
void G_detect() //偵測綠光成份 | |
{ | |
digitalWrite(S2,HIGH); //開啟綠色濾光器 | |
digitalWrite(S3,HIGH); | |
frequencyG = 1000000/pulseIn(OUT, LOW); // 讀取輸出頻率 | |
Serial.print("G= "); // 印出數值在通訊阜上 | |
Serial.print(frequencyG); | |
Serial.print(" "); | |
} | |
void B_detect() //偵測藍光成份 | |
{ | |
digitalWrite(S2,LOW); //開啟藍色濾光器 | |
digitalWrite(S3,HIGH); | |
frequencyB = 1000000/pulseIn(OUT, LOW); // 讀取輸出頻率 | |
Serial.print("B= "); // 印出數值在通訊阜上 | |
Serial.print(frequencyB); | |
Serial.println(" "); | |
} | |
void Color_show() // 判斷顏色並在RGB LED上顯示 | |
{ | |
if(frequencyR > frequencyG && frequencyR > frequencyB) //判斷紅色待測物 | |
{ | |
digitalWrite(LED_R,HIGH); } | |
else { | |
digitalWrite(LED_R,LOW); } | |
if(frequencyG > frequencyR && frequencyG > frequencyB) //判斷綠色待測物 | |
{ | |
digitalWrite(LED_G,HIGH); } | |
else { | |
digitalWrite(LED_G,LOW);} | |
if(frequencyB > frequencyR && frequencyB > frequencyG) //判斷藍色待測物 | |
{ | |
digitalWrite(LED_B,HIGH); } | |
else { | |
digitalWrite(LED_B,LOW); } | |
if(frequencyR > frequencyB && frequencyG > frequencyB && frequencyB < 2000) //判斷黃色待測物 | |
{ | |
digitalWrite(LED_R,HIGH); | |
digitalWrite(LED_G,HIGH); | |
} | |
if(frequencyR > 3000 && frequencyG > 3000 && frequencyB > 3000) //判斷白色待測物 | |
{ | |
digitalWrite(LED_R,HIGH); | |
digitalWrite(LED_G,HIGH); | |
digitalWrite(LED_B,HIGH); | |
} | |
if(frequencyR < 1000 && frequencyG < 1000 && frequencyB < 1000) //判斷黑色待測物 | |
{ | |
digitalWrite(LED_R,LOW); | |
digitalWrite(LED_G,LOW); | |
digitalWrite(LED_B,LOW); | |
} | |
} |
備註:
- 本程式範例可用來判斷紅、綠、藍、黃、白、黑6種顏色
- L47~48: 由datasheet得知當S0=0、S1=1時,輸出頻率會落在12KHz以下,將輸出頻率(速度)調低一點,讓Arduino能夠更精確的讀取其頻率值。
- L55~L57 : 先透過3個副程式,讀取待測物的R、G、B光強度的成份值
- L63~L71 : 讀取待測物R顏色光強度的成份值,由於光的強度和頻率成正比,我們先利用pulseIn函式讀取其輸出週期(微秒),將此週期乘上1,000,000改變單位為秒,再將之倒數得到輸出頻率。
- L54、58 : 讀取待測物的RGB光強度成份值前,我們先開啟4顆LED燈打光,完成讀取後,關閉LED燈,才不會讓白光LED持續開啟,避免刺眼。
- L59 : 取得RGB光強度的成份值後,就可以進行判斷偵測到哪個顏色的待測物,並且秀在RGB LED上。
- L95~L111 : 進行顏色的判斷,並且秀在RGB LED上。我們可以很確定的知道當待測勿接近紅色時,其紅色成份值一定比綠色和藍色大,因此我們利用次關係判斷了紅色,綠色和藍色的判斷也可套用同樣的邏輯。下片幾張圖是利用樂高積木在串列埠視窗中讀取到的RGB成份,另外提供三原色圖方便參考。
註:以下成份值的大小和量測的距離有關,我們的大測方式距離底板3個樂高積木的高度來量測,大家可在最後的影片中看到示範。
紅色積木 => R成份最大
綠色積木 => G成份最大
藍色積木 => B成份最大
-L113~117 : 由三原色圖中,我們可以知道黃色時由紅和綠混合而成的,因此R和G的成份一定比B大,但是如果只有用此規則判斷,可能會和紅色待測物的判斷 (L95~L99)或者綠色待測物的判斷 (L101~L105)產生衝突,因此我們透過串列埠視窗先了解讀取黃色樂高積木時,B的成份一定穩穩的小於 2000,因此多加了此判斷式,讓判斷沒有衝突。
-L119~124 : 白色集合了RGB的三個成份,RGB讀取值會接近最大值,我們同樣透過串列埠視窗先了解讀取白色樂高積木時,RGB的成份皆大於3000,因此用此判斷式判斷白色。
-L116~131 : 黑色將全部的光都吸收了,RGB讀取值會接近最小值,我們同樣透過串列埠視窗先了解讀取黑色樂高積木時,RGB的成份皆小於1000,因此用此判斷式判斷黑色。
範例結果:
討論:
- 雖然程式碼只能偵測6種顏色,不過你可以自己增加你想要的顏色不過判斷條件會越來越難,不過這也是有趣的地方,可以試著挑戰一下你完成了幾種顏色判斷。
- 我們有機會時會將此模組接到faya串列全彩模組上進行全彩的判斷,概念大概是先用全白的顏色進行測試輸出的頻率值,再將其RGB成份利用MAP函式到最大值255,最後將此RGB成份輸出到faya串列全彩模組進行顯示,有興趣的人可以自行試試看!
也歡迎大家在底下留言或到我們的粉絲團留言喔!
====================================
fayalab 粉絲團
FB本篇留言版
沒有留言:
張貼留言