繼前一篇使用 xantorohara.github.io 產生方向箭頭的 8x8 LED 矩陣程式碼後,接著繼續使用 APS9960 手勢感測器來當作方向控制,當往左方揮手時,方向燈箭頭往左移動;當手勢往右揮時,箭頭方向往右移動。
一開始撰寫程式,就因為讀取手勢值 readGesture()這個指令,它會讓程式停在這裡等候新的手勢變化,無法讓迴圈內的 LED燈產生動畫的效果。想改用硬體插斷的方式,結果不行。後來找了 Arduino_APDS9960 的函式庫,是否能偵測手勢的讀取,結果找到一個判斷是否有讀取值的函式 gestureAvailable(),才順利完成程式。以下就來看看如何完成手勢控制方向燈實作。
APDS-9960是一個極小的感測器,內置紫外線和紅外線阻隔濾鏡,四個單獨的二極體不同方向的敏感,以及一個I2C相容介面。其他規格如下:
一開始撰寫程式,就因為讀取手勢值 readGesture()這個指令,它會讓程式停在這裡等候新的手勢變化,無法讓迴圈內的 LED燈產生動畫的效果。想改用硬體插斷的方式,結果不行。後來找了 Arduino_APDS9960 的函式庫,是否能偵測手勢的讀取,結果找到一個判斷是否有讀取值的函式 gestureAvailable(),才順利完成程式。以下就來看看如何完成手勢控制方向燈實作。
APDS-9960是一個極小的感測器,內置紫外線和紅外線阻隔濾鏡,四個單獨的二極體不同方向的敏感,以及一個I2C相容介面。其他規格如下:
- 工作電壓:3.3V
- 環境光及RGB色彩感應
- 接近檢測
- 手勢檢測
- 測量範圍:4-8in (10-20CM)
- I2C介面 (I2C位址:0x39)
[安裝APDS9960 Library]
Arduino_APDS9960 函式庫提供用於從 APDS-9960 手勢感測器,可以偵測環境光線讀取數據。本實作需要安裝以下程式庫: 您可以在 Arduino IDE的介面上的「管理程式庫」找到這個程式庫。有關程式庫(Library)安裝方法請參考另一篇文章: Arduino筆記:安裝 Arduino IDE 程式庫(Library)。[材料]
- Arduino Uno
- APDS-9960 顏色、非接觸手勢檢測傳感器模組 x1
- MAX7219 8x8 LED矩陣模組 x1
- 連接線 x n
[接線圖]
| Arduino Uno | APDS-9960 | 8x8 LED Matrix 模組 |
|---|---|---|
| 3.3V | VCC | - |
| GND | GND | GND |
| A5 | SCL | - |
| A4 | SDA | - |
| D2 | INT | - |
| +5V | - | VCC |
| D10 | - | CS |
| D11 | - | CLK |
| D12 | - | Data In(DIN) |
[程式]
#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);
}
}

張貼留言