
學習目標 : 認識faya串列全彩LED模組的功能及使用方式
學習時間 : 40min
示範模組 : (1) faya brickNano
(2) faya 串列8x8點矩陣模組
工具 : (1) 樂高底板(相容)
====================功能介紹====================
faya串列8x8點矩陣模組,透過3條的串列訊號線,配合簡單的程式,就能控制上方8x8=64顆LED燈。本段功能介紹僅解釋範例中用到的指令,更多的函示庫指令用法可參考官方說明。
介紹指令前,先看一下faya串列8x8點矩陣模組的外觀,它的左邊有三個輸入埠,分別是DIN、CLK、LOAD,用來和Arduion進行串列資料的傳輸,使用此模組前,需先宣告Arduino連到此三個埠的腳位。模組中間就是主角-8x8點矩陣顯示器,上方的64顆LED燈都能夠用程式精準地控制顯示。

- #include<LedControl.h>;
- LedControl 物件名稱 = LedControl(DIN,CLK,LOAD,n);
物件名稱 : 可自行命名
DIN、CLK、LOAD : 連接Arduino的數位腳號碼
n : 連接串列裝置的數量,最多可連接8個,因此n介於1~8之間
(例) 當我們建構一物件名稱為"fayaSerial8x8Dot",把DIN連到第12隻腳,CLK連到11隻
腳,LOAD連到第10隻腳,並且只連了1個串列8x8點矩陣,我們在程式中需宣告:
LedControl fayaSerial8x8Dot = LedControl(12,11,10,1);
- 物件名稱 .shutdown(n-1, power_saving_mode);
n-1 : 選擇第n個串聯裝置
power_saving_mode : true代表進入省電模式,false代表進入一般電源模式
(例) 當我們要將第一個裝置(物件名稱為fayaSerial8x8Dot)進入一般電源模式,程式如下
fayaSerial8x8Dot.shutdown(0,false);
- 物件名稱 .setIntensity(n-1,intensity);
n-1 : 選擇第n個串聯裝置
intensity : 亮度參數設定0~15,0最暗、15最亮
(例) 當我們要將第一個裝置(物件名稱為fayaSerial8x8Dot)設定中間亮度時,程式如下
fayaSerial8x8Dot.setIntensity(0,8);
- 物件名稱 .clearDisplay(n-1);
n-1 : 選擇第n個串聯裝置
(例) 當我們要清除第一個裝置(fayaSerial8x8Dot)的顯示設定內容時,程式如下:
faya7seg.setIntensity(0,8);
- 物件名稱 .setLed(n-1,row,col,state);
n-1 : 選擇第n個串聯裝置
row : 第rol列 (0~7)
col : 第col行 (0~7)
state : 1 = 亮 / 0 = 滅
(例) 當我們要設定第一個裝置(fayaSerial8x8Dot)的第5列、第3行LED兩起來時,程式如下:
fayaSerial8x8Dot.setLed(0,4,2,1);
備註: 由於每家的點矩陣在PCB版上的電路排列順序不一定會相同,ROW 和 COL 甚至0~7的順序可能會相反,下圖為faya串列8x8點矩陣模組LED位置與行列的關係,在撰寫程式時需要用到。

====================原理知識====================
以下解釋提供給有需要知道背後原理的人:
原本8x8點矩陣模組的控制方式,需透過16條訊號線控制每一行列 (8條訊號+8條掃描),利用視覺暫留與行列的導通來控制每顆LED,讓顯示器上的64顆LED隨時能達到明暗的效果。
這個方式的缺點是需要拉很多訊號線,掃描的時候也會占用控制器的資源,有鑑於此,我們可借助一顆IC來處理顯示的工作,降低控制器的負擔。
晶片 Max7219 就是針對所需要的功能設計出來的,他具配了掃描電路和串列埠電路,能夠輕易地將控制器送來的串列訊號解碼送至顯示器,內建的掃描功能也能夠讓顯示器一次顯示所有的LED。本模組的電路如下 (Dig0~7為掃描線、SegA~G為訊號線),接法是固定的,有興趣深入研究的人可以參考datasheet。

===================範例實作(1)===================
了解模組功能(原理)後,我們用以下範例來展示模組的功能:
目標:
(1) faya 串列8x8點矩陣模組上顯示一個愛心圖案
接線:
(1) 電源線連接
如下圖所示,連接的說明請看這篇文章 或簡易版

(2) 訊號線連接
Arduino_12 ===> 串列七段顯示模組_DIN
Arduino_11 ===> 串列七段顯示模組_CLK
Arduino_10 ===> 串列七段顯示模組_LOAD

範例程式:
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/11/01 | |
// Faya-Nugget 範例程式 (Serial8x8Dot_1.ino) | |
// 單元: 模組介紹 :faya 串列8x8點矩陣模組 | |
// 網址: https://fayalab.blogspot.com/2017/11/serial8x8dot.html | |
// 目標 (1) 串列8x8點矩陣模組上顯示一愛心 | |
// 接線: Arduino ==> faya模組 | |
// D10 ==> LOAD (8*8矩陣顯示器模組) | |
// D11 ==> CLK (8*8矩陣顯示器模組) | |
// D12 ==> DIN (8*8矩陣顯示器模組) | |
#include "LedControl.h" | |
//定義Arduino與七字節模組的連接腳位與參數 | |
LedControl fayaSerial8x8Dot = LedControl(12,11,10,1); | |
//定義愛心形狀 | |
boolean heart[8][8] = | |
{ | |
{0,0,0,0,0,0,0,0}, | |
{0,1,1,0,0,1,1,0}, | |
{1,1,1,1,1,1,1,1}, | |
{1,1,1,1,1,1,1,1}, | |
{1,1,1,1,1,1,1,1}, | |
{0,1,1,1,1,1,1,0}, | |
{0,0,1,1,1,1,0,0}, | |
{0,0,0,1,1,0,0,0} | |
}; | |
void setup() { | |
fayaSerial8x8Dot.shutdown(0,false); // 初始化 | |
fayaSerial8x8Dot.setIntensity(0,10); // 設定亮度 (0~15,15最亮) | |
fayaSerial8x8Dot.clearDisplay(0); // 清除畫面 | |
show_heart(); | |
} | |
void loop() { | |
} | |
void show_heart() //顯示愛心副程式 | |
{ | |
for(int i=0; i<=7; i++) | |
{ | |
for (int j=0; j<=7; j++) | |
{ | |
fayaSerial8x8Dot.setLed(0,j,i,heart[i][j]); | |
} | |
} | |
} |
備註:
- 由於只需要一次顯示的指令,因此loop裡面沒有程式,我們在setup{}裡面呼叫顯示愛心的副程式即可。
- L45 : 由於硬體連接的row和col和是定義的方式剛好相反,因此我們在迴圈裡面把i j對調,就能正確的依序顯示是先建好的愛心圖騰。
- 大家可以在第45行下方增加一行delay(200),看這個模組點亮LED的順序
- L17~L27定義了愛心形狀,筆者習慣在Excel先畫好,然後才在Arduino內填入0和1碼,excel檔案可以在這邊下載。
範例結果:
了解模組功能(原理)後,我們用以下範例來展示模組的功能:
目標:
(1) 在8x8矩陣顯示器上隨機顯示剪刀石頭布
(2) 按下觸控開關時,顯示當時的圖騰3秒鐘
接線:
(1) 電源線連接
如下圖所示,連接的說明請看這篇文章 或簡易版

(2) 訊號線連接
Arduino_12 ===> 串列七段顯示模組_DIN
Arduino_11 ===> 串列七段顯示模組_CLK
Arduino_10 ===> 串列七段顯示模組_LOAD

Arduino_A0 ===> 觸控開關模組 _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/11/2 | |
// Faya-Nugget 範例程式 (Serial8x8Dot_2.ino) | |
// 單元: 模組介紹 :faya 串列8x8點矩陣模組 | |
// 網址: | |
// 目標 (1) 在8x8矩陣顯示器上隨機顯示剪刀石頭布 | |
// (2) 按下觸控開關時,顯示當時的圖騰3秒鐘 | |
// 接線: Arduino ==> faya模組 | |
// D10 ==> LOAD (8*8矩陣顯示器模組) | |
// D11 ==> CLK (8*8矩陣顯示器模組) | |
// D12 ==> DIN (8*8矩陣顯示器模組) | |
// A0 ==> OUT (觸控開關) | |
#include "LedControl.h" | |
#define button A0 | |
//定義Arduino與七字節模組的連接腳位與參數 | |
LedControl fayaSerial8x8Dot = LedControl(12,11,10,1); | |
boolean scissor[8][8] = //剪刀圖騰 | |
{ | |
{0,0,0,1,0,1,0,0}, | |
{0,0,0,1,0,1,0,0}, | |
{0,0,0,1,0,1,0,0}, | |
{0,1,1,1,1,1,1,0}, | |
{1,1,1,1,1,1,1,1}, | |
{1,1,1,1,1,1,1,0}, | |
{0,1,1,1,1,1,0,0}, | |
{0,0,1,1,1,0,0,0} | |
}; | |
boolean stone[8][8] = //石頭圖騰 | |
{ | |
{0,0,0,0,0,0,0,0}, | |
{0,0,0,0,0,0,0,0}, | |
{0,0,1,1,1,1,0,0}, | |
{0,1,1,1,1,1,1,0}, | |
{1,1,1,1,1,1,1,1}, | |
{1,1,1,1,1,1,1,1}, | |
{0,1,1,1,1,1,1,0}, | |
{0,0,1,1,1,0,0,0} | |
}; | |
boolean paper[8][8] = //布圖騰 | |
{ | |
{0,0,1,0,1,0,0,0}, | |
{1,0,1,0,1,0,1,0}, | |
{1,0,1,0,1,0,1,0}, | |
{1,1,1,1,1,1,1,0}, | |
{1,1,1,1,1,1,1,0}, | |
{1,1,1,1,1,1,1,1}, | |
{0,1,1,1,1,1,0,0}, | |
{0,0,1,1,1,0,0,0} | |
}; | |
int result; //儲存圖騰結果 | |
void setup() { | |
fayaSerial8x8Dot.shutdown(0,false); // 初始化 | |
fayaSerial8x8Dot.setIntensity(0,10); // 設定亮度 | |
fayaSerial8x8Dot.clearDisplay(0); // 清除畫面 | |
pinMode(button, INPUT); | |
} | |
void loop() { | |
randomSeed(analogRead(5)); //取得亂數種子 | |
result = random(1,4); //1~3中亂數取一值 | |
switch (result) { | |
case 1: // 1出剪刀 | |
show_scissor(); | |
break; | |
case 2: | |
show_stone(); // 2出石頭 | |
break; | |
case 3: | |
show_paper(); // 3出布 | |
break; | |
default: | |
// if nothing else matches, do the default | |
// default is optional | |
break; | |
} | |
delay(50); // 每次顯示間隔0.05秒 | |
if(digitalRead(button) == HIGH) { //當按下按鍵時 | |
delay(3000); //最後一次的圖示停留三秒 | |
} | |
} | |
void show_scissor() //顯示剪刀圖示 | |
{ | |
for(int i=0; i<=7; i++) | |
{ | |
for (int j=0; j<=7; j++) | |
{ | |
fayaSerial8x8Dot.setLed(0,j,i,scissor[i][j]); | |
} | |
} | |
} | |
void show_stone() //顯示石頭圖示 | |
{ | |
for(int i=0; i<=7; i++) | |
{ | |
for (int j=0; j<=7; j++) | |
{ | |
fayaSerial8x8Dot.setLed(0,j,i,stone[i][j]); | |
} | |
} | |
} | |
void show_paper() //顯示布圖示 | |
{ | |
for(int i=0; i<=7; i++) | |
{ | |
for (int j=0; j<=7; j++) | |
{ | |
fayaSerial8x8Dot.setLed(0,j,i,paper[i][j]); | |
} | |
} | |
} |
備註:
- L67: 利用A5腳位浮接狀態,電壓不穩定的狀態,取得亂數種子
- L70: 取得亂數後,再用switch功能將相關的圖形顯示到8x8點矩陣
- 剪刀、石頭、布的形狀,同樣先在excel內畫好,然後才在Arduino內填入0和1碼,excel檔案可以在這邊下載。

範例結果:
討論:
- 由本篇的教學可得知控制串列式點矩陣顯示器是很容易的,不要被64顆LED燈嚇到了,基本上,我們拿到一個點矩陣顯示器時,會先弄清楚LED的行與列的排列順序,這樣整理出來的陣列圖案才會和硬體上顯示相同。如何弄清楚LED行與列的排列順序呢? 大家可以先把Loop{ }裡的程式先空著,然後在Seup裡面寫個幾行程式,看看LED的顯示位置,如此一來,就能快速地把行與列的排列順序弄清楚了!
delay(500); // 暫停0.5秒
fayaSerial8x8Dot.setLed(0,5,7,1); //點亮第6列第8行的LED
- 程式中我們在建立陣列圖案(愛心、剪刀、石頭、布)時,採用了int資料型態,代表一次就宣告了64個int資料變數,這是很浪費記憶體空間的,由於陣列裡面只會放0和1,因此宣告這些陣列時,使用boolean就可以了,舉例如下:

當宣告int時,使用的全域變數為487 bytes (23%)

宣告成boolean時,使用的全域變數降到295 bytes (14%)

順道一提,Arduino程式碼儲存在晶片中的Flash Memory (UNO和NANO還有fayaBrickNano的容量都是30KB = 30720 bytes),宣告的全域變數則儲存在SRAM (UNO和NANO還有fayaBrickNano的容量都是2KB = 2048 bytes)
也歡迎大家在底下留言或到我們的粉絲團留言喔!
====================================
fayalab 粉絲團
FB本篇留言版
沒有留言:
張貼留言