This tutorial is part of: ESP32-S3 RGB LED 点阵
这是一个很棒的项目,可以使用 ESP32-S3 RGB 矩阵模块进行创作,兼具趣味性和实用性。本文下方有其他相关视频的链接。
ESP32-S3 RGB LED矩陣項目 4 - 傾斜點
項目4 – 傾斜點點(透過傾斜ESP32-S3 RGB LED矩陣嚟移動點點)
項目4介紹咗ESP32-S3 RGB LED矩陣模組內置嘅運動感應器。唔似項目1咁自動移動點點,或者項目2同3咁滾動文字,呢個項目畀你透過簡單傾斜塊板嚟控制點點嘅位置。點點會根據模組背面QMI8658C加速度計嘅即時讀數,喺8×8 RGB顯示屏上流暢咁移動。
呢個系列嘅全部六個項目都喺一條YouTube影片入面示範。同一條影片都嵌入咗喺呢一頁,所以你可以確切咁睇到點點喺塊板傾斜時點樣實時移動。呢個項目嘅完整代碼會自動載入喺文章下面,而模組嘅聯盟購買連結會出現喺代碼部分下面。


ESP32-S3 RGB LED矩陣模組概覽
呢個項目使用ESP32-S3 RGB LED矩陣模組,包括:

- ESP32-S3微控制器,具備Wi-Fi同藍牙功能
- 8×8 RGB LED矩陣(64粒獨立可尋址LED)
- QMI8658C加速度計喺背面,用嚟偵測傾斜同運動
- USB端口用嚟編程同供電
- Boot / Reset按鈕
- 可用GPIO引腳方便將來擴展
QMI8658C感應器讀取X、Y同Z軸嘅加速度同方向數值,令點點可以根據塊板嘅傾斜方向向上/下/左/右移動。

影片入面涵蓋嘅項目(時間戳)
- 00:00 – 介紹
- 02:01 – 安裝ESP32開發板
- 03:32 – 安裝程式庫
- 05:32 – 項目1:移動點點
- 11:11 – 項目2:文字滾動
- 12:59 – 項目3:HTTP文字
- 16:41 – 項目4:傾斜點點(呢個項目)
- 18:55 – 項目5:向上箭嘴
- 20:02 – 項目6:目標遊戲
強烈建議睇吓影片入面嘅傾斜示範,因為你可以睇到點點點樣流暢咁對應塊板嘅方向作出反應。

喺Arduino IDE入面安裝ESP32開發板
如果你已經完成咗之前任何一個項目,開發板支援應該已經安裝好。否則,跟住以下步驟:
- 開啟
檔案 > 偏好設定→ 加入ESP32開發板URL。 - 去
工具 > 開發板 > 開發板管理員…並安裝ESP32。 - 喺
工具 > 開發板下面選擇你嘅ESP32-S3開發板。 - 喺
工具 > 連接埠下面選擇正確嘅COM端口。
安裝所需程式庫
呢個項目需要以下程式庫:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFX LibraryQMI8658(運動感應器)
喺程式庫管理員入面安裝佢哋:
- 開啟
草稿碼 > 匯入程式庫 > 管理程式庫…。 - 搜尋Adafruit NeoMatrix → 安裝。
- 允許自動安裝Adafruit GFX同Adafruit NeoPixel。
- 按列出嘅作者搜尋QMI8658 → 安裝。
項目4嘅運作原理
QMI8658C感應器持續提供沿X、Y同Z軸嘅加速度數據。對於呢個項目,我哋只用X同Y軸嚟決定:
- 點點向左或向右移動幾遠(X軸)
- 點點向上或向下移動幾遠(Y軸)
感應器數值會被映射到0至7嘅座標範圍(對應8×8 LED矩陣)。點點位置每秒更新好多次,令到你傾斜模組時有流暢嘅滑動效果。
項目4 – 代碼設定(傾斜點點)
以下係項目代碼頂部附近用戶可編輯嘅設定。完整草稿碼會自動顯示喺文章下面。
矩陣引腳同尺寸
// 8×8 RGB矩陣配置
const int MATRIX_PIN = 14; // 呢塊板嘅固定引腳
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
將MATRIX_PIN保持喺14。佢係硬件接線到板上矩陣嘅。
亮度
// 整體亮度(0–255)
uint8_t matrixBrightness = 40;
有需要可以調高,但近距離睇嘅時候避免用極端亮度。
點點顏色
// 點點顏色(R, G, B)
uint8_t dotRed = 0;
uint8_t dotGreen = 200; // 淺綠色(預設)
uint8_t dotBlue = 0;
更改呢啲數值可以整到任何顏色。例子:
- 紅色:
(255, 0, 0) - 黃色:
(255, 255, 0) - 白色:
(255, 255, 255)
運動靈敏度
為咗防止極端跳動,加速度計數值通常會被限制或縮放。一個典型設定好似:
// 傾斜影響移動嘅程度
float sensitivity = 4.0f; // 數值越大 = 喺屏幕上面移動得越快
如果點點郁得太慢 → 增加數值。如果點點郁得太突然 → 減少數值。
更新速度(刷新率)
你可以在更新之間加一個小延遲,令移動更流暢:
// 位置更新之間嘅延遲(毫秒)
int refreshDelayMs = 20; // 數值越低 = 更流暢同更快反應
10–30 毫秒之間嘅數值會感覺好靈敏。
總結
Project 4 令 ESP32-S3’s 內置嘅 QMI8658C 加速度計活躍起嚟,畀你可以用物理動作控制 LED 矩陣。輕輕傾斜開發板,點就會向同一方向移動,令呢個項目成為更進階嘅 “Arrow Up” 同 “Target Game” 項目嘅完美踏腳石。
完整嘅 Tilt Dot 程式碼會(自動)載入喺呢篇文章下面。為求最佳理解,請睇影片入面嘅傾斜示範,你可以見到開發板旋轉時點樣流暢咁移動。購買 ESP32-S3 RGB LED Matrix 模組嘅連結已包括喺程式碼部分下面。
This tutorial is part of: ESP32-S3 RGB LED 点阵
- ESP32-S3 RGB LED矩陣項目1-基本點
- ESP32-S3 RGB LED矩陣項目2 - 滾動文字
- ESP32-S3 RGB LED矩陣項目3 - 手機文字
- ESP32-S3 RGB LED矩陣項目5 - 箭嘴永遠向上
- ESP32-S3 RGB LED矩陣項目6 - Cible遊戲
- ESP32-S3 RGB LED矩陣 Wi-Fi + NTP時鐘項目 -1 基本時鐘
- ESP32-S3 RGB LED矩陣網絡時鐘項目 - 2個時鐘多色時間及日期顯示
- ESP32-S3 RGB LED矩陣互聯網時鐘項目 - 3種夜間顏色連日期
- ESP32-S3 RGB LED矩陣網絡時鐘項目 - 5 彩虹色
- ESP32-S3 RGB LED矩陣網絡時鐘項目 - 4種隨機顏色
- ESP32-S3 RGB LED Matrix test for RGB, GRB setting
/*
Project 4: Tilt Dot – ESP32-S3 RGB LED Matrix (Waveshare)
This sketch reads tilt from the QMI8658C IMU and smoothly moves a dot
on the 8×8 RGB LED matrix based on board orientation.
▶️ Video Tutorial:
https://youtu.be/JKLuYrRcLMI
📚⬇️ Resources & Code Page:
https://robojax.com/RJT829
QMI8658_RGB_2
*/
#include <Arduino.h>
#include <math.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include <QMI8658.h> // by Lahav Gahali
// -------- LED MATRIX SETUP --------
#define MATRIX_PIN 14
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
NEO_RGB + NEO_KHZ800
);
// -------- QMI8658 IMU SETUP --------
QMI8658 imu;
QMI8658_Data imuData;
// -------- USER SETTINGS --------
// true -> dot on opposite side: USB↔OUSB, 34↔15
// false -> dot on same side as UP
bool useOppositeMapping = false;
// Dot color (0–255 each)
uint8_t dotRed = 0;
uint8_t dotGreen = 100;
uint8_t dotBlue = 0;
// Board sides
enum Side {
SIDE_CENTER = 0,
SIDE_USB,
SIDE_OUSB,
SIDE_15,
SIDE_34
};
// Smooth dot position (in pixel coordinates, but kept as float for easing)
float dotPosX = 3.0f; // start at center
float dotPosY = 3.0f;
// Smoothing factor: smaller = slower movement (0.1 very slow, 0.5 faster)
const float dotSmooth = 0.25f;
bool isFlat = false;
const char* sideName(Side s) {
switch (s) {
case SIDE_CENTER: return "CENTER";
case SIDE_USB: return "USB";
case SIDE_OUSB: return "OUSB";
case SIDE_15: return "15";
case SIDE_34: return "34";
default: return "?";
}
}
// Detect which side is UP using calibrated axes:
// +X = USB, -X = OUSB, +Y = 34, -Y = 15
Side detectSideUp(float ax_g, float ay_g, float az_g) {
// Flat detection
const float flatThreshXY = 0.15f;
const float flatThreshZ = 0.15f;
if (fabs(ax_g) < flatThreshXY &&
fabs(ay_g) < flatThreshXY &&
fabs(az_g - 1.0f) < flatThreshZ) {
isFlat = true;
return SIDE_CENTER;
}
isFlat = false;
// Thresholds to say "this axis is really tilted"
const float tiltThreshY = 0.5f;
const float tiltThreshX = 0.5f;
// 1) Prefer Y axis for 15 / 34 if it's clearly tilted
if (fabs(ay_g) >= tiltThreshY) {
if (ay_g > 0) {
return SIDE_15; // +Y = 34 up
} else {
return SIDE_34; // -Y = 15 up
}
}
// 2) Otherwise, check X axis for USB / OUSB
if (fabs(ax_g) >= tiltThreshX) {
if (ax_g > 0) {
return SIDE_USB; // +X = USB up
} else {
return SIDE_OUSB; // -X = OUSB up
}
}
// 3) If nothing is strongly tilted, just call it CENTER
return SIDE_CENTER;
}
// Map from UP side to where the dot should go
Side dotSideFromUpSide(Side upSide) {
switch (upSide) {
case SIDE_USB:
return useOppositeMapping ? SIDE_OUSB : SIDE_USB;
case SIDE_OUSB:
return useOppositeMapping ? SIDE_USB : SIDE_OUSB;
case SIDE_34:
return useOppositeMapping ? SIDE_15 : SIDE_34;
case SIDE_15:
return useOppositeMapping ? SIDE_34 : SIDE_15;
case SIDE_CENTER:
default:
return SIDE_CENTER;
}
}
// Convert dot side to matrix coordinates
void getDotPixel(Side dotSide, int &px, int &py) {
// Matrix (0,0) = top-left
// top center: (3,0) → USB
// bottom center: (3,7) → OUSB
// left center: (0,3) → 15
// right center: (7,3) → 34
// center: (3,3)
switch (dotSide) {
case SIDE_USB: px = 3; py = 0; break;
case SIDE_OUSB: px = 3; py = 7; break;
case SIDE_15: px = 0; py = 3; break;
case SIDE_34: px = 7; py = 3; break;
case SIDE_CENTER:
default: px = 3; py = 3; break;
}
}
void setup() {
Serial.begin(115200);
delay(500);
matrix.begin();
matrix.setBrightness(20);
matrix.fillScreen(0);
matrix.show();
// IMU: SDA=11, SCL=12 for ESP32-S3-Matrix
if (!imu.begin(11, 12)) {
Serial.println("Failed to initialize QMI8658!");
while (1) { delay(1000); }
}
imu.setAccelUnit_mg(true);
imu.setGyroUnit_dps(true);
imu.setDisplayPrecision(4);
Serial.print("QMI8658 initialized. useOppositeMapping = ");
Serial.println(useOppositeMapping ? "TRUE" : "FALSE");
}
void loop() {
if (!imu.readSensorData(imuData)) {
return;
}
float ax_g = imuData.accelX / 1000.0f;
float ay_g = imuData.accelY / 1000.0f;
float az_g = imuData.accelZ / 1000.0f;
Side upSide = detectSideUp(ax_g, ay_g, az_g);
Side dotSide = dotSideFromUpSide(upSide);
int targetX, targetY;
getDotPixel(dotSide, targetX, targetY);
// --- Smooth movement toward target ---
dotPosX += (targetX - dotPosX) * dotSmooth;
dotPosY += (targetY - dotPosY) * dotSmooth;
// Convert to integer pixel coordinates
int px = (int)round(dotPosX);
int py = (int)round(dotPosY);
// Clamp just in case
if (px < 0) px = 0;
if (px > 7) px = 7;
if (py < 0) py = 0;
if (py > 7) py = 7;
// --- Draw dot ---
matrix.fillScreen(0);
uint16_t color = matrix.Color(dotRed, dotGreen, dotBlue);
matrix.drawPixel(px, py, color);
matrix.show();
// Debug
Serial.print("AX="); Serial.print(ax_g, 3);
Serial.print(" AY="); Serial.print(ay_g, 3);
Serial.print(" AZ="); Serial.print(az_g, 3);
Serial.print(" | UP="); Serial.print(sideName(upSide));
Serial.print(" | DOT="); Serial.print(sideName(dotSide));
Serial.print(" | px="); Serial.print(px);
Serial.print(" py="); Serial.println(py);
delay(80);
}
你可能需要嘅嘢
-
亞馬遜
-
易贝
-
阿里巴巴速卖通Purchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
阿里巴巴速卖通Purchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
資源與參考資料
-
內部🎨 Color picker Toolrobojax.com
文件📁
Fritzing 文件
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB