This tutorial is part of: Matrice LED RGB ESP32-S3
Proiect interesant de creat pentru aplicații distractive și practice folosind modulul ESP32-S3 RGB Matrix. Linkuri către alte videoclipuri sunt sub acest articol.
Proiect ESP32-S3 cu matrice LED RGB 5 - Săgeata mereu în sus
Proiectul 5 – Săgeata Întotdeauna în Sus (Indicator de Orientare folosind QMI8658C)
Proiectul 5 folosește senzorul de mișcare QMI8658C pentru a detecta orientarea matricei LED RGB ESP32-S3 și pentru a afișa întotdeauna o săgeată îndreptată în SUS în raport cu gravitația. Indiferent cum rotiți placa—cu partea USB în sus, cu partea OUSB în sus, cu partea “15” sau cu partea “34”—săgeata se rotește automat și indică direcția fizică în sus.
Aceasta este o demonstrație puternică a detectării orientării în timp real folosind accelerometrul integrat. Toate cele șase proiecte pentru acest modul sunt demonstrate într-un singur videoclip YouTube, care este de asemenea încorporat pe această pagină. Codul complet pentru Proiectul 5 se încarcă automat mai jos de articol, iar linkurile de afiliere apar sub secțiunea de cod.

Prezentare Generală a Modulului Matrice LED RGB ESP32-S3
Modulul Matrice LED RGB ESP32-S3 include mai multe componente care fac posibil acest proiect:

- Microcontrolerul ESP32-S3 — oferă Wi-Fi, BLE și rulează logica LED/IMU.
- Matrice LED RGB 8×8 — afișează săgeata în oricare dintre cele patru orientări.
- Accelerometrul QMI8658C — detectează înclinarea, mișcarea și orientarea.:contentReference[oaicite:0]{index=0}
- Port USB-C pentru alimentare și programare în Arduino IDE.
- Butoanele Reset și Boot pentru încărcarea schițelor.
- Pinii GPIO disponibili în jurul plăcii pentru proiecte suplimentare.
Direcția săgeții este determinată în întregime de citirile accelerometrului. Când placa este rotită, QMI8658C detectează noile valori X/Y/Z, iar schița alege ce model de săgeată (↑, ↓, ←, →) trebuie desenat.

Proiecte Acoperite în Videoclip (Marcaje de Timp)
- 00:00 – Introducere
- 02:01 – Instalarea plăcilor ESP32
- 03:32 – Instalarea bibliotecilor
- 05:32 – Proiectul 1: Punct în Mișcare
- 11:11 – Proiectul 2: Derulare Text
- 12:59 – Proiectul 3: Text HTTP
- 16:41 – Proiectul 4: Punct de Înclinare
- 18:55 – Proiectul 5: Săgeata Întotdeauna în Sus (acest proiect)
- 20:02 – Proiectul 6: Jocul Țintă
Videoclipul arată clar cum săgeata își schimbă direcția instantaneu în funcție de modul în care este rotit modulul. Vizionarea acestei secțiuni este puternic recomandată.:contentReference[oaicite:1]{index=1}

Instalarea Plăcilor ESP32 în Arduino IDE
Dacă ați finalizat orice proiect anterior, configurarea plăcii este deja făcută. În caz contrar:
Fișier > Preferințe→ Adăugați URL-ul plăcii ESP32Instrumente > Placă > Manager de Plăci…→ Instalați “ESP32”- Selectați placa ESP32-S3 sub
Instrumente > Placă - Selectați portul USB COM corect sub
Instrumente > Port
Instalarea Bibliotecilor Necesare
Proiectul 5 folosește:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658(senzor de mișcare)
Schiță > Include Bibliotecă > Gestionați Bibliotecile…- Căutați: NeoMatrix → Instalați
- Instalați dependențele: NeoPixel + GFX
- Căutați și instalați QMI8658 de autorul său
Cum Funcționează Proiectul 5
QMI8658C măsoară gravitația pe axele X, Y și Z. Comparând aceste valori, schița determină ce parte fizică a plăcii este orientată în sus:
- Partea USB în sus
- Partea OUSB în sus (opusă USB)
- Partea “15” în sus
- Partea “34” în sus
Fiecare orientare corespunde unui model diferit de săgeată pe matricea 8×8. Maparea urmează logica dvs. confirmată de orientare din sesiunile anterioare de depanare. Rotația plăcii este citită continuu, iar săgeata se actualizează imediat ce partea orientată în sus se schimbă.
Proiectul 5 – Setări de Cod (Săgeata Întotdeauna în Sus)
Mai jos sunt valorile reglabile de utilizator din zona de configurare. Codul complet al proiectului apare automat mai jos de articol.
Configurarea Matricei
// Configurarea matricei
const int MATRIX_PIN = 14; // fix pentru acest modul
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Orientare recomandată: origine Colț-Sus-Stânga, mod progresiv
// (constructorul real este în codul încărcat mai jos)
Acest proiect folosește aspectul NEO_MATRIX_PROGRESSIVE pentru a asigura că săgeata indică corect în funcție de mișcarea reală.
Luminozitate
uint8_t matrixBrightness = 40; // 0–255
Puteți crește această valoare pentru medii mai luminoase. Pentru utilizare în interior, 30–60 este confortabil.
Culoarea Săgeții
// Culoarea săgeții
uint8_t arrowRed = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue = 0;
Schimbați aceste valori pentru a modifica culoarea săgeții. De exemplu:
- Săgeată verde:
(0, 255, 0) - Săgeată albastră:
(0, 0, 255) - Săgeată albă:
(255, 255, 255)
Sensibilitate și Netezire
Pentru a evita tremurul, codul include logică de netezire și prag. În setări puteți găsi ceva de genul:
// Ajustare sensibilitate / netezire
float tiltThreshold = 0.30f; // ajustați dacă săgeata se schimbă prea ușor
- Dacă săgeata ta se răstoarnă prea ușor → crește pragul.
- Dacă săgeata este prea lentă la schimbare → scade pragul.
Modele de săgeți
Schița include modele bitmap de săgeți pentru:
- ↑ sus
- ↓ jos
- ← stânga
- → dreapta
Nu trebuie să le modifici, dar poți schimba formele din cod dacă dorești un stil diferit.
Rezumat
Proiectul 5 demonstrează cum matricea LED RGB ESP32-S3 și accelerometrul QMI8658C lucrează împreună pentru a detecta orientarea și a afișa o săgeată care indică întotdeauna în sus. Acest proiect se bazează pe Tilt Dot (Proiectul 4) și te pregătește pentru jocul interactiv final din Proiectul 6.
Schița completă “Arrow Always Up” este disponibilă mai jos în acest articol (încărcată automat). Vizionarea părții corespunzătoare din video este foarte recomandată pentru a vedea cât de instantaneu răspunde săgeata la rotația plăcii. Dacă dorești să construiești acest proiect acasă, linkurile afiliate pentru modulul matricei LED RGB ESP32-S3 apar sub secțiunea de cod.
Imagini
This tutorial is part of: Matrice LED RGB ESP32-S3
- Proiect ESP32-S3 cu Matrice LED RGB 1 - Punct de bază
- Proiect ESP32-S3 cu Matrice LED RGB 2 - Text Derulant
- Proiect 3 cu matrice LED RGB ESP32-S3 - Text de pe telefonul mobil
- Proiect ESP32-S3 cu matrice LED RGB 4 - Punct de înclinare
- Proiect Matrice LED RGB ESP32-S3 6 - Joc Cible
- Proiect de ceas Wi-Fi + NTP cu matrice LED RGB ESP32-S3 -1 Ceas de bază
- Proiect de ceas cu matrice LED RGB ESP32-S3 conectat la internet - Afișaj de oră și dată în 2 ceasuri multicolore
- Proiect de ceas cu matrice LED RGB ESP32-S3 conectat la internet - 3 culori de noapte cu dată
- Proiect de ceas internet cu matrice LED RGB ESP32-S3 - 5 culori curcubeu
- Proiect de ceas internet cu matrice LED RGB ESP32-S3 - 4 culori aleatorii
- 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);
}
Lucruri de care ai putea avea nevoie
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Resurse și referințe
-
Internă🎨 Color picker Toolrobojax.com
Fișiere📁
Fișier Fritzing
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB