專題生:411114207賴廷軒
作品說明:LED matrix是由n*m的LED燈以矩陣樣式排列組成,以不同程式碼調控,會產生不同樣式的圖形,設計一迴路也能使其變為跑馬燈形貌。
專案動機:相信多多少少都有在街道上看過不同色彩的跑馬燈,近距離放大會發現這些是有一塊n*m的矩陣LED燈所組成,而調控不同程式碼,就能展示出不同樣式的跑馬燈,故想實際實做看看並熟悉程式碼應用。
專案目標:以此為目標,採用MAX7219 matrix,製作一個Arduino簡易小型跑馬燈,並使用矩陣方式製作不同樣式的跑馬燈。
應用場景:街道上各式各樣的跑馬燈。
成品照片(跑馬燈形式):
(手勢)可控跑馬燈方向形式:
正面圖
背面圖
程式碼:
(以單顆matrix跑箭頭動畫):
#include <LedControl.h>
// Pin 12:Data in, Pin 11: Clock, Pin 10: CS(Load)
LedControl display = LedControl(12,11,10,1);
const uint64_t R_IMAGES[] = { //往右箭頭
0x0000000100000000,
0x0000010301000000,
0x0001030703010000,
0x0103070f07030100,
0x02060f1f0f060200,
0x040c1f3f1f0c0400,
0x08183f7f3f180800,
0x08183f7f3f180800,
0x10307fff7f301000,
0x2060fefefe602000,
0x40c0fcfcfcc04000,
0x8080f8f8f8808000,
0x0000f0f0f0000000,
0x0000e0e0e0000000,
0x0000c0c0c0000000,
0x0000808080000000,
0x0000000000000000
};
const int R_IMAGES_LEN = sizeof(R_IMAGES)/8;
void setup()
{
display.clearDisplay(0); // 清除螢幕
display.shutdown(0, false); // 關閉省電模式
display.setIntensity(0, 10); // 設定亮度為 8 (介於0~15之間)
}
void displayImage(uint64_t image) {
for (int i = 0; i < 8; i++) {
byte row = (image >> i * 8) & 0xFF;
for (int j = 0; j < 8; j++) {
display.setLed(0, i, j, bitRead(row, j));
}
}
}
int i = 0;
void loop() {
displayImage(R_IMAGES[i]);
if (++i >= R_IMAGES_LEN ) {
i = 0;
}
delay(100);
}
(手勢)可控跑馬燈形式(加入APDS9960後):
#include <Arduino_APDS9960.h>
#include <LedControl.h>
// Pin 12:Data in, Pin 11: Clock, Pin 10: CS(Load)
LedControl display = LedControl(12,11,10,1);
const uint64_t R_IMAGES[] = { //往右箭頭
0x0000000100000000,
0x0000010301000000,
0x0001030703010000,
0x0103070f07030100,
0x02060f1f0f060200,
0x040c1f3f1f0c0400,
0x08183f7f3f180800,
0x08183f7f3f180800,
0x10307fff7f301000,
0x2060fefefe602000,
0x40c0fcfcfcc04000,
0x8080f8f8f8808000,
0x0000f0f0f0000000,
0x0000e0e0e0000000,
0x0000c0c0c0000000,
0x0000808080000000,
0x0000000000000000
};
const int R_IMAGES_LEN = sizeof(R_IMAGES)/8;
const uint64_t L_IMAGES[] = { //往左箭頭
0x0000008000000000,
0x000080c080000000,
0x0080c0e0c0800000,
0x80c0e0f0e0c08000,
0x4060f0f8f0604000,
0x2030f8fcf8302000,
0x1018fcfefc181000,
0x080cfefffe0c0800,
0x04067f7f7f060400,
0x02033f3f3f030200,
0x01011f1f1f010100,
0x00000f0f0f000000,
0x0000070707000000,
0x0000030303000000,
0x0000010101000000,
0x0000000000000000
};
const int L_IMAGES_LEN = sizeof(L_IMAGES)/8;
int LastGesture = 0; //紀錄最後一次的手勢
int i = 0;
void setup() {
Serial.begin(115200);
if(!APDS.begin()){
Serial.println("failed to initialize device! Please check your wiring.");
}
else Serial.println("Detecting gestures ...");
display.clearDisplay(0); // 清除螢幕
display.shutdown(0, false); // 關閉省電模式
display.setIntensity(0, 10); // 設定亮度為 8 (介於0~15之間)
}
void displayImage(uint64_t image) {
for (int i = 0; i < 8; i++) {
byte row = (image >> i * 8) & 0xFF;
for (int j = 0; j < 8; j++) {
display.setLed(0, i, j, bitRead(row, j));
}
}
}
void loop() {
if (APDS.gestureAvailable()) {
//讀取 APDS9960 的值
uint8_t gesture = APDS.readGesture();
if(gesture == GESTURE_DOWN) Serial.println("DOWN");
if(gesture == GESTURE_UP) Serial.println("UP");
if(gesture == GESTURE_LEFT) {
Serial.println("LEFT");
LastGesture = 1;
}
if(gesture == GESTURE_RIGHT) {
Serial.println("RIGHT");
LastGesture = 2;
}
}
if (LastGesture == 1) {
displayImage(L_IMAGES[i]);
if (++i >= L_IMAGES_LEN ) {
i = 0;
}
delay(10);
}
if (LastGesture == 2) {
displayImage(R_IMAGES[i]);
if (++i >= R_IMAGES_LEN ) {
i = 0;
}
delay(10);
}
}
(以兩顆matrix串聯方式跑動畫):
//用兩個 LED MAX 7219 8*8 矩陣模組,製作一個簡易跑馬燈。
#include <MaxMatrix.h> //含入程式庫 MaxMatrix.h
#include <avr/pgmspace.h> //Arduino 內建程式庫
// LED MAX7219 矩陣模組,所有能顯示的字元:
PROGMEM const unsigned char CH[] = {
3, 8, B00000000, B00000000, B00000000, B00000000, B00000000, // space
1, 8, B01011111, B00000000, B00000000, B00000000, B00000000, // !
3, 8, B00000011, B00000000, B00000011, B00000000, B00000000, // "
5, 8, B00010100, B00111110, B00010100, B00111110, B00010100, // #
4, 8, B00100100, B01101010, B00101011, B00010010, B00000000, // $
5, 8, B01100011, B00010011, B00001000, B01100100, B01100011, // %
5, 8, B00110110, B01001001, B01010110, B00100000, B01010000, // &
1, 8, B00000011, B00000000, B00000000, B00000000, B00000000, // '
3, 8, B00011100, B00100010, B01000001, B00000000, B00000000, // (
3, 8, B01000001, B00100010, B00011100, B00000000, B00000000, // )
5, 8, B00101000, B00011000, B00001110, B00011000, B00101000, // *
5, 8, B00001000, B00001000, B00111110, B00001000, B00001000, // +
2, 8, B10110000, B01110000, B00000000, B00000000, B00000000, // ,
4, 8, B00001000, B00001000, B00001000, B00001000, B00000000, // -
2, 8, B01100000, B01100000, B00000000, B00000000, B00000000, // .
4, 8, B01100000, B00011000, B00000110, B00000001, B00000000, // /
4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // 0
3, 8, B01000010, B01111111, B01000000, B00000000, B00000000, // 1
4, 8, B01100010, B01010001, B01001001, B01000110, B00000000, // 2
4, 8, B00100010, B01000001, B01001001, B00110110, B00000000, // 3
4, 8, B00011000, B00010100, B00010010, B01111111, B00000000, // 4
4, 8, B00100111, B01000101, B01000101, B00111001, B00000000, // 5
4, 8, B00111110, B01001001, B01001001, B00110000, B00000000, // 6
4, 8, B01100001, B00010001, B00001001, B00000111, B00000000, // 7
4, 8, B00110110, B01001001, B01001001, B00110110, B00000000, // 8
4, 8, B00000110, B01001001, B01001001, B00111110, B00000000, // 9
2, 8, B01010000, B00000000, B00000000, B00000000, B00000000, // :
2, 8, B10000000, B01010000, B00000000, B00000000, B00000000, // ;
3, 8, B00010000, B00101000, B01000100, B00000000, B00000000, // <
3, 8, B00010100, B00010100, B00010100, B00000000, B00000000, // =
3, 8, B01000100, B00101000, B00010000, B00000000, B00000000, // >
4, 8, B00000010, B01011001, B00001001, B00000110, B00000000, // ?
5, 8, B00111110, B01001001, B01010101, B01011101, B00001110, // @
4, 8, B01111110, B00010001, B00010001, B01111110, B00000000, // A
4, 8, B01111111, B01001001, B01001001, B00110110, B00000000, // B
4, 8, B00111110, B01000001, B01000001, B00100010, B00000000, // C
4, 8, B01111111, B01000001, B01000001, B00111110, B00000000, // D
4, 8, B01111111, B01001001, B01001001, B01000001, B00000000, // E
4, 8, B01111111, B00001001, B00001001, B00000001, B00000000, // F
4, 8, B00111110, B01000001, B01001001, B01111010, B00000000, // G
4, 8, B01111111, B00001000, B00001000, B01111111, B00000000, // H
3, 8, B01000001, B01111111, B01000001, B00000000, B00000000, // I
4, 8, B00110000, B01000000, B01000001, B00111111, B00000000, // J
4, 8, B01111111, B00001000, B00010100, B01100011, B00000000, // K
4, 8, B01111111, B01000000, B01000000, B01000000, B00000000, // L
5, 8, B01111111, B00000010, B00001100, B00000010, B01111111, // M
5, 8, B01111111, B00000100, B00001000, B00010000, B01111111, // N
4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // O
4, 8, B01111111, B00001001, B00001001, B00000110, B00000000, // P
4, 8, B00111110, B01000001, B01000001, B10111110, B00000000, // Q
4, 8, B01111111, B00001001, B00001001, B01110110, B00000000, // R
4, 8, B01000110, B01001001, B01001001, B00110010, B00000000, // S
5, 8, B00000001, B00000001, B01111111, B00000001, B00000001, // T
4, 8, B00111111, B01000000, B01000000, B00111111, B00000000, // U
5, 8, B00001111, B00110000, B01000000, B00110000, B00001111, // V
5, 8, B00111111, B01000000, B00111000, B01000000, B00111111, // W
5, 8, B01100011, B00010100, B00001000, B00010100, B01100011, // X
5, 8, B00000111, B00001000, B01110000, B00001000, B00000111, // Y
4, 8, B01100001, B01010001, B01001001, B01000111, B00000000, // Z
2, 8, B01111111, B01000001, B00000000, B00000000, B00000000, // [
4, 8, B00000001, B00000110, B00011000, B01100000, B00000000, // \ backslash
2, 8, B01000001, B01111111, B00000000, B00000000, B00000000, // ]
3, 8, B00000010, B00000001, B00000010, B00000000, B00000000, // hat
4, 8, B01000000, B01000000, B01000000, B01000000, B00000000, // _
2, 8, B00000001, B00000010, B00000000, B00000000, B00000000, // `
4, 8, B00100000, B01010100, B01010100, B01111000, B00000000, // a
4, 8, B01111111, B01000100, B01000100, B00111000, B00000000, // b
4, 8, B00111000, B01000100, B01000100, B00101000, B00000000, // c
4, 8, B00111000, B01000100, B01000100, B01111111, B00000000, // d
4, 8, B00111000, B01010100, B01010100, B00011000, B00000000, // e
3, 8, B00000100, B01111110, B00000101, B00000000, B00000000, // f
4, 8, B10011000, B10100100, B10100100, B01111000, B00000000, // g
4, 8, B01111111, B00000100, B00000100, B01111000, B00000000, // h
3, 8, B01000100, B01111101, B01000000, B00000000, B00000000, // i
4, 8, B01000000, B10000000, B10000100, B01111101, B00000000, // j
4, 8, B01111111, B00010000, B00101000, B01000100, B00000000, // k
3, 8, B01000001, B01111111, B01000000, B00000000, B00000000, // l
5, 8, B01111100, B00000100, B01111100, B00000100, B01111000, // m
4, 8, B01111100, B00000100, B00000100, B01111000, B00000000, // n
4, 8, B00111000, B01000100, B01000100, B00111000, B00000000, // o
4, 8, B11111100, B00100100, B00100100, B00011000, B00000000, // p
4, 8, B00011000, B00100100, B00100100, B11111100, B00000000, // q
4, 8, B01111100, B00001000, B00000100, B00000100, B00000000, // r
4, 8, B01001000, B01010100, B01010100, B00100100, B00000000, // s
3, 8, B00000100, B00111111, B01000100, B00000000, B00000000, // t
4, 8, B00111100, B01000000, B01000000, B01111100, B00000000, // u
5, 8, B00011100, B00100000, B01000000, B00100000, B00011100, // v
5, 8, B00111100, B01000000, B00111100, B01000000, B00111100, // w
5, 8, B01000100, B00101000, B00010000, B00101000, B01000100, // x
4, 8, B10011100, B10100000, B10100000, B01111100, B00000000, // y
3, 8, B01100100, B01010100, B01001100, B00000000, B00000000, // z
3, 8, B00001000, B00110110, B01000001, B00000000, B00000000, // {
1, 8, B01111111, B00000000, B00000000, B00000000, B00000000, // |
3, 8, B01000001, B00110110, B00001000, B00000000, B00000000, // }
4, 8, B00001000, B00000100, B00001000, B00000100, B00000000, // ~
};
int data = 8; //DIN (Data IN) 連接 Arduino pin 8
int load = 9; //CS load 連接 Arduino pin 9
int clock = 10; //CLK (Clock) 連接 Arduino pin 10
int maxInUse = 2; //設定 LED MAX 7219 矩陣模組的數目
MaxMatrix m(data, load, clock, maxInUse);
byte buffer[10];
char string1[] = " Ray Arduino "; //要跑馬燈顯示的字元
void setup(){
m.init();
m.setIntensity(5); // LED 亮度 0-15
}
void loop(){
byte c;
delay(100);
m.shiftLeft(false, true);
printStringWithShift(string1, 100);
}
void printCharWithShift(char c, int shift_speed){
if (c < 32) return;
c -= 32;
memcpy_P(buffer, CH + 7*c, 7);
m.writeSprite(maxInUse*8, 0, buffer);
m.setColumn(maxInUse*8 + buffer[0], 0);
for (int i=0; i<buffer[0]+1; i++)
{
delay(shift_speed);
m.shiftLeft(false, false);
}
}
// Extract characters from Scrolling text
void printStringWithShift(char* s, int shift_speed){
while (*s != 0){
printCharWithShift(*s, shift_speed);
s++;
}
}
心得:
這學期因改回實體上課,多多少少需要校正回歸到之前的作息,上學期是因為在家實作Arduino專題,故時間較充裕,這學期則課業加重無法分配太多時間,但追根究底仍舊完成一份像樣的報告了。上學期因為是與其餘兩位同學一起合做,但其實當時都是我做的,網站、報告用的ppt等都是我個人製作,影片、接線材料也都是我獨自完成,但我在ppt上仍然寫其他兩人分配的工作(雖然當天我在線上報告時他們也沒上線),等同於當時報告我獨自完成,可能也是因為這樣導致上學期分數偏低。當然也有一原因是因為報告的專題太過於簡單(一個人做也行),但變成三人做一個專題,故分數也偏低,不過這學期我變成獨立製作,這樣也比較好。
說完心路歷程後講講製作過程,雖然製作過程非常簡單,甚至接線也很簡單,程式碼的部分是可以延拓到n個matrix的排列,以及顯示不同的文字跑馬燈,這也是現今路上跑馬燈的原型,如果有機會的話,下學期希望將這份專題延伸,以及兼做Arduino月球車,月球車是循跡車+怪手的組合,故到時候會有兩組程式碼,分別代表操控這兩種模型。