This tutorial is part of: ESP32-S3 RGB LED matica
Skvelý projekt na tvorbu zábavných a praktických aplikácií s použitím modulu ESP32-S3 RGB Matrix. Odkazy na ďalšie videá nájdete pod týmto článkom.
Projekt ESP32-S3 RGB LED Matrix 5 - Šípka vždy hore
Projekt 5 – šípka vždy hore (indikátor orientácie pomocou QMI8658C)
Projekt 5 používa pohybový senzor QMI8658C na zistenie orientácie ESP32-S3 RGB LED matice a vždy zobrazuje šípku smerujúcu HORE vzhľadom na gravitáciu. Bez ohľadu na to, ako dosku otočíte – stranou USB hore, stranou OUSB hore, stranou „15“ alebo stranou „34“ – šípka sa automaticky otočí a ukazuje smerom fyzicky nahor.
Je to výkonná ukážka snímania orientácie v reálnom čase pomocou vstavaného akcelerometra. Všetkých šesť projektov pre tento modul je predvedených v jednom YouTube videu, ktoré je tiež vložené na tejto stránke. Kompletný kód pre Projekt 5 sa automaticky načíta nižšie pod článkom a affiliate odkazy sa zobrazujú pod sekciou s kódom.

Prehľad modulu ESP32-S3 RGB LED Matrix
Modul ESP32-S3 RGB LED Matrix obsahuje niekoľko komponentov, ktoré umožňujú tento projekt:

- Mikrokontrolér ESP32-S3 — poskytuje Wi-Fi, BLE a spúšťa logiku LED/IMU.
- 8×8 RGB LED matica — zobrazuje šípku v jednej zo štyroch orientácií.
- Akcelerometer QMI8658C — zisťuje náklon, pohyb a orientáciu.:contentReference[oaicite:0]{index=0}
- Port USB-C na napájanie a programovanie v Arduino IDE.
- Tlačidlá Reset a Boot na nahrávanie skíc.
- GPIO piny dostupné okolo dosky pre ďalšie projekty.
Smer šípky je určený výhradne hodnotami z akcelerometra. Keď sa doska otočí, QMI8658C zaznamená nové hodnoty X/Y/Z a skica vyberie, ktorý vzor šípky (↑, ↓, ←, →) sa má nakresliť.

Projekty zahrnuté vo videu (časové značky)
- 00:00 – Úvod
- 02:01 – Inštalácia dosiek ESP32
- 03:32 – Inštalácia knižníc
- 05:32 – Projekt 1: Pohybujúca sa bodka
- 11:11 – Projekt 2: Posúvanie textu
- 12:59 – Projekt 3: HTTP text
- 16:41 – Projekt 4: Náklonová bodka
- 18:55 – Projekt 5: Šípka vždy hore (tento projekt)
- 20:02 – Projekt 6: Cieľová hra
Video jasne ukazuje, ako šípka okamžite mení smer na základe toho, ako je modul otočený. Pozretie tejto časti sa dôrazne odporúča.:contentReference[oaicite:1]{index=1}

Inštalácia dosiek ESP32 v Arduino IDE
Ak ste dokončili niektorý z predchádzajúcich projektov, nastavenie dosky je už hotové. V opačnom prípade:
Súbor > Predvoľby→ Pridajte URL dosky ESP32Nástroje > Doska > Správca dosiek…→ Nainštalujte „ESP32“- Vyberte dosku ESP32-S3 v časti
Nástroje > Doska - Vyberte správny USB COM port v časti
Nástroje > Port
Inštalácia požadovaných knižníc
Projekt 5 používa:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658(pohybový senzor)
Skica > Zahrnúť knižnicu > Spravovať knižnice…- Hľadať: NeoMatrix → Inštalovať
- Nainštalujte závislosti: NeoPixel + GFX
- Vyhľadajte a nainštalujte QMI8658 od jeho autora
Ako funguje Projekt 5
QMI8658C meria gravitáciu na osiach X, Y a Z. Porovnaním týchto hodnôt skica určí, ktorá fyzická strana dosky smeruje nahor:
- Strana USB hore
- Strana OUSB hore (oproti USB)
- Strana „15“ hore
- Strana „34“ hore
Každá orientácia zodpovedá inému vzoru šípky na 8×8 matici. Mapovanie nasleduje vašu potvrdenú logiku orientácie z predchádzajúcich ladiacich sedení. Rotácia dosky sa číta nepretržite a šípka sa aktualizuje hneď, ako sa zmení strana smerujúca nahor.
Projekt 5 – Nastavenia kódu (Šípka vždy hore)
Nižšie sú uvedené používateľsky nastaviteľné hodnoty z konfiguračnej oblasti. Úplný kód projektu sa automaticky zobrazí nižšie pod článkom.
Konfigurácia matice
// Konfigurácia matice
const int MATRIX_PIN = 14; // pevné pre tento modul
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Odporúčaná orientácia: počiatok vľavo hore, progresívny režim
// (skutočný konštruktor je v kóde načítanom nižšie)
Tento projekt používa rozloženie NEO_MATRIX_PROGRESSIVE, aby sa zabezpečilo, že šípka ukazuje správne na základe skutočného pohybu.
Jas
uint8_t matrixBrightness = 40; // 0–255
Túto hodnotu môžete zvýšiť pre jasnejšie prostredie. Pre vnútorné použitie je 30–60 pohodlných.
Farba šípky
// Farba šípky
uint8_t arrowRed = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue = 0;
Zmeňte tieto hodnoty na úpravu farby šípky. Napríklad:
- Zelená šípka:
(0, 255, 0) - Modrá šípka:
(0, 0, 255) - Biela šípka:
(255, 255, 255)
Citlivosť a vyhladzovanie
Aby sa predišlo chveniu, kód obsahuje logiku vyhladzovania a prahu. V nastaveniach môžete nájsť niečo ako:
// Nastavenie citlivosti / vyhladzovania
float tiltThreshold = 0.30f; // upravte, ak sa šípka mení príliš ľahko
- Ak sa vaša šípka preklápa príliš ľahko → zvýšte prah.
- Ak je šípka pri zmene príliš pomalá → znížte prah.
Vzory šípok
Náčrt obsahuje bitmapové vzory šípok pre:
- ↑ hore
- ↓ dole
- ← vľavo
- → vpravo
Tieto nemusíte upravovať, ale ak chcete iný štýl, môžete zmeniť tvary v kóde.
Zhrnutie
Projekt 5 ukazuje, ako ESP32-S3 RGB LED Matrix a akcelerometer QMI8658C spolupracujú pri detekcii orientácie a zobrazení šípky, ktorá vždy smeruje nahor. Tento projekt nadväzuje na Tilt Dot (Projekt 4) a pripravuje vás na záverečnú interaktívnu hru v Projekte 6.
Plný náčrt “Arrow Always Up” je dostupný pod týmto článkom (automaticky načítaný). Odporúča sa pozrieť si príslušnú časť videa, aby ste videli, ako okamžite šípka reaguje na otočenie dosky. Ak si chcete tento projekt postaviť doma, affiliate odkazy na modul ESP32-S3 RGB LED Matrix nájdete pod sekciou s kódom.
Images
This tutorial is part of: ESP32-S3 RGB LED matica
- Projekt ESP32-S3 RGB LED matice 1 – Základná bodka
- Projekt 2 s RGB LED maticou ESP32-S3 - Posúvajúci sa text
- Projekt 3 s RGB LED maticou ESP32-S3 - Text z mobilného telefónu
- Projekt ESP32-S3 RGB LED Matrix 4 - Náklon bodky
- Projekt ESP32-S3 RGB LED Matrix 6 - Hra Cible
- Projekt ESP32-S3 RGB LED matica Wi-Fi + NTP časové hodiny - 1 Základné hodiny
- Projekt internetových hodín s RGB LED maticou ESP32-S3 - 2 hodiny s viacfarebným zobrazením času a dátumu
- Projekt internetových hodín s RGB LED maticou ESP32-S3 - 3 nočné farby s dátumom
- Projekt internetových hodín s RGB LED maticou ESP32-S3 - 5 dúhových farieb
- Projekt internetových hodín s RGB LED maticou ESP32-S3 - 4 náhodné farby
- 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);
}
Things you might need
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Resources & references
-
Internal🎨 Color picker Toolrobojax.com
Files📁
Fritzing File
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB