This tutorial is part of: Ma trận LED RGB ESP32-S3
Đây là một dự án thú vị và hữu ích sử dụng module ma trận RGB ESP32-S3. Các liên kết đến các video khác được cung cấp bên dưới bài viết này.
Dự án Ma trận LED RGB ESP32-S3 5 - Mũi tên luôn hướng lên
Dự án 5 – Mũi tên Luôn Hướng Lên (Chỉ báo Định hướng sử dụng QMI8658C)
Dự án 5 sử dụng cảm biến chuyển động QMI8658C để phát hiện định hướng của ESP32-S3 RGB LED Matrix và luôn hiển thị một mũi tên hướng LÊN so với trọng lực. Dù bạn xoay bo mạch theo cách nào—cổng USB hướng lên, cổng OUSB hướng lên, cạnh “15”, hay cạnh “34”—mũi tên sẽ tự động xoay và chỉ về hướng vật lý hướng lên trên.
Đây là một minh chứng mạnh mẽ về khả năng cảm biến định hướng thời gian thực sử dụng gia tốc kế tích hợp. Tất cả sáu dự án cho mô-đun này được trình diễn trong một video YouTube, cũng được nhúng trên trang này. Mã hoàn chỉnh cho Dự án 5 tự động tải bên dưới bài viết, và các liên kết tiếp thị liên kết xuất hiện dưới phần mã.

Tổng quan về Mô-đun ESP32-S3 RGB LED Matrix
Mô-đun ESP32-S3 RGB LED Matrix bao gồm một số thành phần giúp thực hiện dự án này:

- Vi điều khiển ESP32-S3 — cung cấp Wi-Fi, BLE và chạy logic LED/IMU.
- Ma trận LED RGB 8×8 — hiển thị mũi tên ở một trong bốn định hướng.
- Gia tốc kế QMI8658C — phát hiện độ nghiêng, chuyển động và định hướng.:contentReference[oaicite:0]{index=0}
- Cổng USB-C để cấp nguồn và lập trình trong Arduino IDE.
- Các nút Reset và Boot để nạp chương trình.
- Các chân GPIO có sẵn xung quanh bo mạch cho các dự án bổ sung.
Hướng của mũi tên được xác định hoàn toàn bằng các số đọc từ gia tốc kế. Khi bo mạch được xoay, QMI8658C cảm nhận các giá trị X/Y/Z mới và chương trình chọn mẫu mũi tên (↑, ↓, ←, →) nào sẽ được vẽ.

Các Dự án trong Video (Dấu mốc thời gian)
- 00:00 – Giới thiệu
- 02:01 – Cài đặt bo mạch ESP32
- 03:32 – Cài đặt thư viện
- 05:32 – Dự án 1: Chấm di chuyển
- 11:11 – Dự án 2: Cuộn chữ
- 12:59 – Dự án 3: Văn bản HTTP
- 16:41 – Dự án 4: Chấm nghiêng
- 18:55 – Dự án 5: Mũi tên Luôn Hướng Lên (dự án này)
- 20:02 – Dự án 6: Trò chơi bắn mục tiêu
Video cho thấy rõ ràng cách mũi tên thay đổi hướng ngay lập tức dựa trên cách mô-đun được xoay. Xem phân đoạn này được khuyến nghị mạnh mẽ.:contentReference[oaicite:1]{index=1}

Cài đặt Bo mạch ESP32 trong Arduino IDE
Nếu bạn đã hoàn thành bất kỳ dự án nào trước đó, việc thiết lập bo mạch đã hoàn tất. Nếu không:
File > Preferences→ Thêm URL bo mạch ESP32Tools > Board > Boards Manager…→ Cài đặt “ESP32”- Chọn bo mạch ESP32-S3 trong
Tools > Board - Chọn cổng COM USB chính xác trong
Tools > Port
Cài đặt các Thư viện Cần thiết
Dự án 5 sử dụng:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658(cảm biến chuyển động)
Sketch > Include Library > Manage Libraries…- Tìm kiếm: NeoMatrix → Cài đặt
- Cài đặt các phần phụ thuộc: NeoPixel + GFX
- Tìm kiếm và cài đặt QMI8658 theo tác giả của nó
Cách Dự án 5 Hoạt động
QMI8658C đo trọng lực trên các trục X, Y và Z. Bằng cách so sánh các giá trị này, chương trình xác định cạnh vật lý nào của bo mạch đang hướng lên:
- Cạnh USB hướng lên
- Cạnh OUSB hướng lên (đối diện USB)
- Cạnh “15” hướng lên
- Cạnh “34” hướng lên
Mỗi định hướng tương ứng với một mẫu mũi tên khác nhau trên ma trận 8×8. Việc ánh xạ tuân theo logic định hướng đã xác nhận của bạn từ các phiên gỡ lỗi trước đó. Sự xoay của bo mạch được đọc liên tục và mũi tên cập nhật ngay khi cạnh hướng lên thay đổi.
Dự án 5 – Cài đặt Mã (Mũi tên Luôn Hướng Lên)
Dưới đây là các giá trị người dùng có thể điều chỉnh từ khu vực cấu hình. Mã dự án đầy đủ tự động xuất hiện bên dưới bài viết.
Cấu hình Ma trận
// Cấu hình ma trận
const int MATRIX_PIN = 14; // cố định cho mô-đun này
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Định hướng được khuyến nghị: Gốc trên-trái, chế độ tuần tự
// (hàm tạo thực tế nằm trong mã được tải bên dưới)
Dự án này sử dụng bố cục NEO_MATRIX_PROGRESSIVE để đảm bảo mũi tên chỉ đúng dựa trên chuyển động thực tế.
Độ sáng
uint8_t matrixBrightness = 40; // 0–255
Bạn có thể tăng giá trị này cho môi trường sáng hơn. Đối với sử dụng trong nhà, 30–60 là thoải mái.
Màu Mũi tên
// Màu mũi tên
uint8_t arrowRed = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue = 0;
Thay đổi các giá trị này để sửa màu của mũi tên. Ví dụ:
- Mũi tên xanh lá:
(0, 255, 0) - Mũi tên xanh dương:
(0, 0, 255) - Mũi tên trắng:
(255, 255, 255)
Độ nhạy và Làm mịn
Để tránh rung lắc, mã bao gồm logic làm mịn và ngưỡng. Trong cài đặt, bạn có thể thấy một cái gì đó như:
// Điều chỉnh độ nhạy / làm mịn
float tiltThreshold = 0.30f; // điều chỉnh nếu mũi tên thay đổi quá dễ dàng
- Nếu mũi tên của bạn lật quá dễ dàng → tăng ngưỡng.
- Nếu mũi tên đổi hướng quá chậm → giảm ngưỡng.
Các Mẫu Mũi Tên
Bản phác thảo bao gồm các mẫu bitmap mũi tên cho:
- ↑ lên
- ↓ xuống
- ← trái
- → phải
Bạn không cần phải sửa đổi những mẫu này, nhưng bạn có thể thay đổi hình dạng bên trong mã nếu muốn có kiểu khác.
Tóm tắt
Dự án 5 minh họa cách ESP32-S3 RGB LED Matrix và cảm biến gia tốc QMI8658C hoạt động cùng nhau để phát hiện hướng và hiển thị một mũi tên luôn chỉ lên trên. Dự án này xây dựng dựa trên Tilt Dot (Dự án 4) và chuẩn bị cho bạn trò chơi tương tác cuối cùng trong Dự án 6.
Bản phác thảo đầy đủ “Arrow Always Up” có sẵn bên dưới bài viết này (tự động tải). Xem phần tương ứng của video được khuyến nghị cao để thấy mũi tên phản ứng tức thì với việc xoay bo mạch. Nếu bạn muốn tự xây dựng dự án này tại nhà, các liên kết liên kết cho mô-đun ESP32-S3 RGB LED Matrix xuất hiện dưới phần mã.
Hình ảnh
This tutorial is part of: Ma trận LED RGB ESP32-S3
- Dự án Ma trận LED RGB ESP32-S3 1- Chấm cơ bản
- Dự án Ma trận LED RGB ESP32-S3 2 - Văn bản cuộn
- Dự án ma trận LED RGB ESP32-S3 3 - Văn bản từ điện thoại di động
- Dự án Ma trận LED RGB ESP32-S3 4 - Chấm nghiêng
- Dự án Ma trận LED RGB ESP32-S3 6 - Trò chơi Cible
- Dự án Đồng hồ thời gian Wi-Fi + NTP sử dụng ma trận LED RGB ESP32-S3 - 1 Đồng hồ cơ bản
- Dự án Đồng hồ Internet Ma trận LED RGB ESP32-S3 - Hiển thị Thời gian & Ngày tháng 2 Đồng hồ đa màu sắc
- Dự án Đồng hồ Internet Ma trận LED RGB ESP32-S3 - 3 Màu Ban Đêm kèm Ngày
- Dự án Đồng hồ Internet Ma trận LED RGB ESP32-S3 - 5 Màu cầu vồng
- Dự án Đồng hồ Internet Ma trận LED RGB ESP32-S3 - 4 màu ngẫu nhiên
- ESP32-S3 RGB LED Matrix test for RGB, GRB setting
/*
Project 5: Arrow Always Up – 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/RJT833
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 -> arrow points to opposite side
// USB↔OUSB, 34↔15
// false -> arrow points to the same side that is UP
bool useOppositeMapping = false;
// Arrow color (0–255 each)
uint8_t dotRed = 0;
uint8_t dotGreen = 150;
uint8_t dotBlue = 0;
// Board sides
enum Side {
SIDE_CENTER = 0,
SIDE_USB,
SIDE_OUSB,
SIDE_15,
SIDE_34
};
// Direction for arrow drawing
enum ArrowDir {
ARROW_CENTER,
ARROW_UP,
ARROW_DOWN,
ARROW_LEFT,
ARROW_RIGHT
};
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 "?";
}
}
// -------- ARROW DRAWING (YOUR CODE, UNCHANGED) --------
// Draw a simple arrow on 8x8 matrix pointing in the given direction
void drawArrow(ArrowDir dir, uint16_t color) {
matrix.fillScreen(0);
switch (dir) {
case ARROW_UP:
// Tip
matrix.drawPixel(3, 0, color);
matrix.drawPixel(4, 0, color);
// Second row
matrix.drawPixel(2, 1, color);
matrix.drawPixel(3, 1, color);
matrix.drawPixel(4, 1, color);
matrix.drawPixel(5, 1, color);
// Shaft
matrix.drawLine(3, 2, 3, 6, color);
matrix.drawLine(4, 2, 4, 6, color);
break;
case ARROW_DOWN:
// Tip
matrix.drawPixel(3, 7, color);
matrix.drawPixel(4, 7, color);
// Row above tip
matrix.drawPixel(2, 6, color);
matrix.drawPixel(3, 6, color);
matrix.drawPixel(4, 6, color);
matrix.drawPixel(5, 6, color);
// Shaft
matrix.drawLine(3, 1, 3, 5, color);
matrix.drawLine(4, 1, 4, 5, color);
break;
case ARROW_LEFT:
// Tip
matrix.drawPixel(0, 3, color);
matrix.drawPixel(0, 4, color);
// Column after tip
matrix.drawPixel(1, 2, color);
matrix.drawPixel(1, 3, color);
matrix.drawPixel(1, 4, color);
matrix.drawPixel(1, 5, color);
// Shaft
matrix.drawLine(2, 3, 6, 3, color);
matrix.drawLine(2, 4, 6, 4, color);
break;
case ARROW_RIGHT:
// Tip
matrix.drawPixel(7, 3, color);
matrix.drawPixel(7, 4, color);
// Column before tip
matrix.drawPixel(6, 2, color);
matrix.drawPixel(6, 3, color);
matrix.drawPixel(6, 4, color);
matrix.drawPixel(6, 5, color);
// Shaft
matrix.drawLine(1, 3, 5, 3, color);
matrix.drawLine(1, 4, 5, 4, color);
break;
case ARROW_CENTER:
default:
// Simple plus in the center
matrix.drawLine(3, 3, 4, 3, color);
matrix.drawLine(3, 4, 4, 4, color);
matrix.drawLine(3, 3, 3, 4, color);
matrix.drawLine(4, 3, 4, 4, color);
break;
}
matrix.show();
}
// -------- IMU → SIDE DETECTION --------
// We calibrated earlier:
// +X = USB, -X = OUSB
// +Y = 15, -Y = 34 (after your correction)
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;
// Prefer Y axis for 15 / 34
if (fabs(ay_g) >= tiltThreshY) {
if (ay_g > 0) {
return SIDE_34; // +Y = 34 up
} else {
return SIDE_15; // -Y = 15 up
}
}
// Otherwise, use 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
}
}
// Not clearly tilted → treat as center
return SIDE_CENTER;
}
// Map from UP side to where the arrow should point
Side arrowSideFromUpSide(Side upSide) {
if (!useOppositeMapping) {
// Arrow shows the side that is UP
return upSide;
}
// Arrow shows the opposite side
switch (upSide) {
case SIDE_USB: return SIDE_OUSB;
case SIDE_OUSB: return SIDE_USB;
case SIDE_15: return SIDE_34;
case SIDE_34: return SIDE_15;
case SIDE_CENTER:
default: return SIDE_CENTER;
}
}
// Convert SIDE to ArrowDir
ArrowDir arrowDirFromSide(Side s) {
switch (s) {
case SIDE_USB: return ARROW_UP;
case SIDE_OUSB: return ARROW_DOWN;
case SIDE_15: return ARROW_LEFT;
case SIDE_34: return ARROW_RIGHT;
case SIDE_CENTER:
default: return ARROW_CENTER;
}
}
// ---------------- SETUP & LOOP ----------------
void setup() {
Serial.begin(115200);
delay(500);
matrix.begin();
matrix.setBrightness(20);
matrix.fillScreen(0);
matrix.show();
// IMU: SDA=11, SCL=12 on 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 arrowSide = arrowSideFromUpSide(upSide);
ArrowDir dir = arrowDirFromSide(arrowSide);
uint16_t color = matrix.Color(dotRed, dotGreen, dotBlue);
drawArrow(dir, color);
// 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(" | ARROW="); Serial.println(sideName(arrowSide));
delay(80);
}
Nghĩ bạn có thể cần
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Tài nguyên & tài liệu tham khảo
-
Nội bộ🎨 Color picker Toolrobojax.com
Tập tin📁
Tập tin Fritzing
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB