Ten poradnik jest częścią: Matryca LED RGB ESP32-S3
Fajny projekt do stworzenia dla zabawy i praktycznych zastosowań z wykorzystaniem modułu matrycy RGB ESP32-S3. Linki do innych filmów znajdują się poniżej tego artykułu.
Projekt matrycy LED RGB ESP32-S3 5 - Strzałka zawsze w górę
Projekt 5 – Strzałka zawsze w górę (wskaźnik orientacji z użyciem QMI8658C)
Projekt 5 wykorzystuje czujnik ruchu QMI8658C do wykrywania orientacji matrycy LED RGB ESP32-S3 i zawsze wyświetla strzałkę wskazującą GÓRĘ względem grawitacji. Niezależnie od tego, jak obrócisz płytkę—stroną USB do góry, stroną OUSB do góry, bokiem „15” lub bokiem „34”—strzałka automatycznie się obraca i wskazuje fizycznie kierunek ku górze.
To doskonała demonstracja wykrywania orientacji w czasie rzeczywistym z użyciem wbudowanego akcelerometru. Wszystkie sześć projektów dla tego modułu jest zaprezentowanych w jednym filmie na YouTube, który jest również osadzony na tej stronie. Kompletny kod Projektu 5 ładuje się automatycznie poniżej artykułu, a linki afiliacyjne pojawiają się pod sekcją z kodem.

Przegląd modułu matrycy LED RGB ESP32-S3
Moduł matrycy LED RGB ESP32-S3 zawiera kilka komponentów, które umożliwiają realizację tego projektu:

- Mikrokontroler ESP32-S3 — zapewnia Wi-Fi, BLE i obsługuje logikę LED/IMU.
- Matryca LED RGB 8×8 — wyświetla strzałkę w jednej z czterech orientacji.
- Akcelerometr QMI8658C — wykrywa przechylenie, ruch i orientację.
- Port USB-C do zasilania i programowania w Arduino IDE.
- Przyciski Reset i Boot do przesyłania szkiców.
- Piny GPIO dostępne wokół płytki do dodatkowych projektów.
Kierunek strzałki jest określany wyłącznie na podstawie odczytów akcelerometru. Gdy płytka jest obracana, QMI8658C wykrywa nowe wartości X/Y/Z, a szkic wybiera, który wzór strzałki (↑, ↓, ←, →) powinien zostać narysowany.

Projekty omówione w filmie (znaczniki czasu)
- 00:00 – Wprowadzenie
- 02:01 – Instalacja płytek ESP32
- 03:32 – Instalacja bibliotek
- 05:32 – Projekt 1: Ruchoma kropka
- 11:11 – Projekt 2: Przewijanie tekstu
- 12:59 – Projekt 3: Tekst HTTP
- 16:41 – Projekt 4: Kropka przechylenia
- 18:55 – Projekt 5: Strzałka zawsze w górę (ten projekt)
- 20:02 – Projekt 6: Gra w cel
Film wyraźnie pokazuje, jak strzałka natychmiast zmienia kierunek w zależności od obrotu modułu. Obejrzenie tego fragmentu jest zdecydowanie zalecane.

Instalacja płytek ESP32 w Arduino IDE
Jeśli ukończyłeś którykolwiek wcześniejszy projekt, konfiguracja płytki jest już gotowa. W przeciwnym razie:
Plik > Preferencje→ Dodaj adres URL płytki ESP32Narzędzia > Płytka > Menedżer płytek…→ Zainstaluj „ESP32”- Wybierz płytkę ESP32-S3 w
Narzędzia > Płytka - Wybierz właściwy port USB COM w
Narzędzia > Port
Instalacja wymaganych bibliotek
Projekt 5 wykorzystuje:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658(czujnik ruchu)
Szkic > Dołącz bibliotekę > Zarządzaj bibliotekami…- Szukaj: NeoMatrix → Zainstaluj
- Zainstaluj zależności: NeoPixel + GFX
- Wyszukaj i zainstaluj QMI8658 według autora
Jak działa Projekt 5
QMI8658C mierzy grawitację na osiach X, Y i Z. Porównując te wartości, szkic określa, która fizyczna strona płytki jest skierowana ku górze:
- Strona USB do góry
- Strona OUSB do góry (przeciwna do USB)
- Bok „15” do góry
- Bok „34” do góry
Każda orientacja odpowiada innemu wzorowi strzałki na matrycy 8×8. Mapowanie jest zgodne z potwierdzoną logiką orientacji z wcześniejszych sesji debugowania. Obrót płytki jest odczytywany w sposób ciągły, a strzałka aktualizuje się natychmiast po zmianie strony skierowanej ku górze.
Projekt 5 – Ustawienia kodu (Strzałka zawsze w górę)
Poniżej znajdują się wartości regulowane przez użytkownika z obszaru konfiguracji. Pełny kod projektu pojawia się automatycznie poniżej artykułu.
Konfiguracja matrycy
// Konfiguracja matrycy
const int MATRIX_PIN = 14; // stałe dla tego modułu
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Zalecana orientacja: początek w lewym górnym rogu, tryb progresywny
// (rzeczywisty konstruktor znajduje się w kodzie załadowanym poniżej)
Ten projekt wykorzystuje układ NEO_MATRIX_PROGRESSIVE, aby zapewnić prawidłowe wskazywanie strzałki na podstawie rzeczywistego ruchu.
Jasność
uint8_t matrixBrightness = 40; // 0–255
Możesz zwiększyć tę wartość w jaśniejszym otoczeniu. Do użytku wewnątrz pomieszczeń wygodny jest zakres 30–60.
Kolor strzałki
// Kolor strzałki
uint8_t arrowRed = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue = 0;
Zmień te wartości, aby zmodyfikować kolor strzałki. Na przykład:
- Zielona strzałka:
(0, 255, 0) - Niebieska strzałka:
(0, 0, 255) - Biała strzałka:
(255, 255, 255)
Czułość i wygładzanie
Aby uniknąć drgań, kod zawiera logikę wygładzania i progów. W ustawieniach możesz znaleźć coś takiego:
// Regulacja czułości / wygładzania
float tiltThreshold = 0.30f; // dostosuj, jeśli strzałka zmienia się zbyt łatwo
- Jeśli twoja strzałka zbyt łatwo się zmienia → zwiększ próg.
- Jeśli strzałka zmienia się zbyt wolno → zmniejsz próg.
Wzory strzałek
Szkic zawiera wzory bitmapowe strzałek dla:
- ↑ góra
- ↓ dół
- ← lewo
- → prawo
Nie musisz ich modyfikować, ale możesz zmienić kształty w kodzie, jeśli chcesz inny styl.
Podsumowanie
Projekt 5 pokazuje, jak ESP32-S3 RGB LED Matrix i akcelerometr QMI8658C współpracują, aby wykrywać orientację i wyświetlać strzałkę, która zawsze wskazuje górę. Projekt ten opiera się na Tilt Dot (Projekt 4) i przygotowuje cię do końcowej interaktywnej gry w Projekcie 6.
Pełny szkic “Strzałka zawsze w górę” jest dostępny poniżej tego artykułu (automatycznie ładowany). Zaleca się obejrzenie odpowiedniej części wideo, aby zobaczyć, jak natychmiast strzałka reaguje na obrót płytki. Jeśli chcesz zbudować ten projekt w domu, linki partnerskie do modułu ESP32-S3 RGB LED Matrix znajdują się pod sekcją z kodem.
Obrazy
Ten poradnik jest częścią: Matryca LED RGB ESP32-S3
- Projekt matrycy LED RGB ESP32-S3 1 – podstawowa kropka
- Projekt matrycy LED RGB ESP32-S3 2 - Przewijany tekst
- Projekt ESP32-S3 z matrycą LED RGB 3 - Tekst z telefonu komórkowego
- Projekt ESP32-S3 z matrycą LED RGB 4 - Punkt przechyłu
- Projekt ESP32-S3 z matrycą LED RGB 6 - gra w cel
- Projekt zegara czasu Wi-Fi + NTP z matrycą LED RGB ESP32-S3 -1 Zegar podstawowy
- Projekt zegara internetowego z matrycą LED RGB ESP32-S3 - 2 zegary wielokolorowe z wyświetlaniem czasu i daty
- Projekt zegara internetowego z matrycą LED RGB ESP32-S3 - 3 kolory nocne z datą
- Projekt zegara internetowego z matrycą LED RGB ESP32-S3 - 5 kolorów tęczy
- Projekt zegara internetowego z matrycą LED RGB ESP32-S3 - 4 losowe kolory
- 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);
}
Rzeczy, których możesz potrzebować
-
Amazon
-
Allegro
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Zasoby i odniesienia
-
Wewnętrzny🎨 Color picker Toolrobojax.com
Pliki📁
Plik Fritzing
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB