Este tutorial es parte de: Matriz de LED RGB ESP32-S3
Proyecto genial para crear aplicaciones prácticas y divertidas con el módulo de matriz RGB ESP32-S3. Encontrará enlaces a otros videos debajo de este artículo.
Proyecto de Matriz LED RGB ESP32-S3 5 - Flecha siempre arriba
Proyecto 5 - Flecha Siempre Arriba (Indicador de Orientación usando QMI8658C)
El Proyecto 5 utiliza el sensor de movimiento QMI8658C para detectar la orientación de la matriz de LED RGB ESP32-S3 y siempre mostrar una flecha apuntando hacia ARRIBA en relación con la gravedad. No importa cómo gires la placa: con el lado USB hacia arriba, el lado OUSB hacia arriba, el lado "15" o el lado "34", la flecha automáticamente gira y apunta hacia la dirección físicamente hacia arriba.
Esta es una poderosa demostración de detección de orientación en tiempo real utilizando el acelerómetro a bordo. Los seis proyectos de este módulo se demuestran en un video de YouTube, que también está incrustado en esta página. El código completo del Proyecto 5 se carga automáticamente debajo del artículo, y los enlaces de afiliados aparecen debajo de la sección de código.

Descripción general del Módulo de Matriz LED RGB ESP32-S3
El módulo de matriz LED RGB ESP32-S3 incluye varios componentes que hacen posible este proyecto:

- microcontrolador ESP32-S3- proporciona Wi-Fi, BLE y ejecuta la lógica de LED/IMU.
- Matriz LED RGB 8×8- muestra la flecha en cualquiera de las cuatro orientaciones.
- acelerómetro QMI8658C- detecta inclinación, movimiento y orientación.:contentReference[oaicite:0]{index=0}
- puerto USB-Cpara la potencia y programación en Arduino IDE.
- Botones de Reinicio y Arranquepara subir bocetos.
- pines GPIOdisponible en toda la junta para proyectos adicionales.
La dirección de la flecha se determina completamente por las lecturas del acelerómetro. Cuando se rota la placa, el QMI8658C detecta los nuevos valores X/Y/Z, y el boceto elige qué patrón de flecha (↑, ↓, ←, →) debe dibujarse.

Proyectos Cubiertos en el Video (Tiempos)
- 00:00- Introducción
- 02:01- Instalando placas ESP32
- 03:32- Instalando bibliotecas
- 05:32- Proyecto 1: Punto en Movimiento
- 11:11- Proyecto 2: Desplazamiento de Texto
- 12:59- Proyecto 3: Texto HTTP
- 16:41- Proyecto 4: Tilt Dot
- 18:55-Proyecto 5: Flecha Siempre Arriba (este proyecto)
- 20:02- Proyecto 6: Juego de Objetivos
El video muestra claramente cómo la flecha cambia de dirección instantáneamente según cómo se gire el módulo. Se recomienda encarecidamente ver este segmento.:contentReference[oaicite:1]{index=1}

Instalando placas ESP32 en el IDE de Arduino
Si completaste algún proyecto anterior, la configuración de la placa ya está hecha. De lo contrario:
File > Preferences→ Agregar URL de la placa ESP32Tools > Board > Boards Manager…→ Instalar "ESP32"- Seleccione la placa ESP32-S3 bajo
Tools > Board - Seleccione el puerto COM USB correcto bajo
Tools > Port
Instalando bibliotecas requeridas
El Proyecto 5 utiliza:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658(sensor de movimiento)
Sketch > Include Library > Manage Libraries…- Buscar:NeoMatrix→ Instalar
- Instalar dependencias:NeoPixel+GFX
- Buscar e instalarQMI8658por su autor
Cómo funciona el Proyecto 5
El QMI8658C mide la gravedad en los ejes X, Y y Z. Al comparar estos valores, el boceto determina qué lado físico de la placa está orientado hacia arriba:
- USB hacia arriba
- Lado OUSB hacia arriba(opuesto USB)
- Lado "15" hacia arriba
- Lado "34" hacia arriba
Cada orientación corresponde a un patrón de flechas diferente en la matriz de 8×8. El mapeo sigue tu lógica de orientación confirmada de sesiones de depuración anteriores. La rotación del tablero se lee continuamente, y la flecha se actualiza tan pronto como cambia el lado superior.
Proyecto 5 - Configuración de Código (Flecha Siempre Arriba)
A continuación se presentan los valores ajustables por el usuario en el área de configuración. El código completo del proyecto aparece automáticamente debajo del artículo.
Configuración de la matriz
// Matrix configuration
const int MATRIX_PIN = 14; // fixed for this module
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Recommended orientation: Top-Left origin, progressive mode
// (actual constructor is inside the code loaded below)
Este proyecto utilizaNEO_MATRIZ_PROGRESIVOdiseño para asegurar que la flecha apunte correctamente según el movimiento real.
Brillo
uint8_t matrixBrightness = 40; // 0–255
Puedes aumentar este valor para ambientes más luminosos. Para uso en interiores, 30-60 es cómodo.
Color de la flecha
// Arrow color
uint8_t arrowRed = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue = 0;
Cambia estos valores para modificar el color de la flecha. Por ejemplo:
- Flecha verde:
(0, 255, 0) - Flecha azul:
(0, 0, 255) - Flecha blanca:
(255, 255, 255)
Sensibilidad y Suavizado
Para evitar el jitter, el código incluye lógica de suavizado y umbral. En la configuración, puedes encontrar algo como:
// Sensitivity / smoothing adjustment
float tiltThreshold = 0.30f; // adjust if arrow changes too easily
- Si tu flecha se da vuelta demasiado fácilmente →aumentarumbral.
- Si la flecha es demasiado lenta para cambiar →disminuirumbral.
Patrones de flechas
El boceto incluye patrones de bitmap de flechas para:
- ↑ arriba
- ↓ abajo
- ← izquierda
- → derecha
No necesitas modificar estos, pero puedes cambiar las formas dentro del código si deseas un estilo diferente.
Resumen
El Proyecto 5 demuestra cómo la Matriz de LEDs RGB ESP32-S3 y el acelerómetro QMI8658C trabajan juntos para detectar la orientación y mostrar una flecha que siempre apunta hacia arriba. Este proyecto se basa en el Tilt Dot (Proyecto 4) y te prepara para el juego interactivo final en el Proyecto 6.
El boceto completo de "Arrow Always Up" está disponible debajo de este artículo (cargado automáticamente). Se recomienda encarecidamente ver la parte correspondiente del video para observar cómo responde instantáneamente la flecha a la rotación de la placa. Si deseas realizar este proyecto en casa, los enlaces de afiliados para el módulo de matriz LED RGB ESP32-S3 aparecen en la sección de código.
Imágenes
Este tutorial es parte de: Matriz de LED RGB ESP32-S3
- Proyectos con Matriz LED RGB para ESP32-S3 (Juego de Inclinación, Texto, Flecha, Demostración WiFi)
- Proyecto 2 de matriz de LED RGB ESP32-S3 - Texto en desplazamiento
- Proyecto de matriz LED RGB ESP32-S3 3 - Texto desde teléfono móvil
- Proyecto de matriz de LED RGB ESP32-S3 4 - Punto inclinado
- Proyecto de Matriz LED RGB ESP32-S3 6 - Juego de Cible
- Proyecto de reloj básico con matriz LED RGB ESP32-S3 Wi-Fi + hora NTP -1
- Proyecto de Reloj por Internet con Matriz LED RGB ESP32-S3 - Pantalla de Hora y Fecha multicolor de 2 Relojes
- Proyecto de Reloj de Internet con Matriz de LED RGB ESP32-S3 - 3 Colores Nocturnos con Fecha
- Proyecto de reloj de internet con matriz de LED RGB ESP32-S3 - 5 colores del arcoíris
- Proyecto de reloj en Internet con matriz de LED RGB ESP32-S3 - 4 colores aleatorios
- Prueba de matriz LED RGB ESP32-S3 para configuración RGB, GRB
/*
* Proyecto 5: Flecha Siempre Arriba - Matriz de LED RGB ESP32-S3 (Waveshare) Este boceto lee la inclinación del IMU QMI8658C y mueve suavemente un punto en la matriz de LED RGB de 8×8 según la orientación de la placa.
*
* ▶️ Tutorial en Video:
* https://youtu.be/JKLuYrRcLMI
*
* 📚⬇️ Recursos y Página de Código:
* 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> // por Lahav Gahali
// -------- CONFIGURACIÓN DE LA MATRIZ LED --------
#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
);
// -------- CONFIGURACIÓN DEL IMU QMI8658 --------
QMI8658 imu;
QMI8658_Data imuData;
// -------- CONFIGURACIÓN DEL USUARIO --------
// verdadero -> la flecha apunta al lado opuesto
// USB↔OUSB, 34↔15
// falso -> la flecha apunta hacia el mismo lado que está ARRIBA
bool useOppositeMapping = false;
// Color de la flecha (0-255 cada uno)
uint8_t dotRed = 0;
uint8_t dotGreen = 150;
uint8_t dotBlue = 0;
// Lados de la tabla
enum Side {
SIDE_CENTER = 0,
SIDE_USB,
SIDE_OUSB,
SIDE_15,
SIDE_34
};
// Dirección para el dibujo de flechas
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 "?";
}
}
// -------- DIBUJO DE FLECHA (SU CÓDIGO, SIN CAMBIOS) --------
// Dibuja una flecha simple en una matriz de 8x8 que apunte en la dirección dada.
void drawArrow(ArrowDir dir, uint16_t color) {
matrix.fillScreen(0);
switch (dir) {
case ARROW_UP:
// Consejo
matrix.drawPixel(3, 0, color);
matrix.drawPixel(4, 0, color);
// Segunda fila
matrix.drawPixel(2, 1, color);
matrix.drawPixel(3, 1, color);
matrix.drawPixel(4, 1, color);
matrix.drawPixel(5, 1, color);
// Eje
matrix.drawLine(3, 2, 3, 6, color);
matrix.drawLine(4, 2, 4, 6, color);
break;
case ARROW_DOWN:
// Consejo
matrix.drawPixel(3, 7, color);
matrix.drawPixel(4, 7, color);
// Fila arriba del consejo
matrix.drawPixel(2, 6, color);
matrix.drawPixel(3, 6, color);
matrix.drawPixel(4, 6, color);
matrix.drawPixel(5, 6, color);
// Eje
matrix.drawLine(3, 1, 3, 5, color);
matrix.drawLine(4, 1, 4, 5, color);
break;
case ARROW_LEFT:
// Consejo
matrix.drawPixel(0, 3, color);
matrix.drawPixel(0, 4, color);
// Columna después de la propina
matrix.drawPixel(1, 2, color);
matrix.drawPixel(1, 3, color);
matrix.drawPixel(1, 4, color);
matrix.drawPixel(1, 5, color);
// Eje
matrix.drawLine(2, 3, 6, 3, color);
matrix.drawLine(2, 4, 6, 4, color);
break;
case ARROW_RIGHT:
// Consejo
matrix.drawPixel(7, 3, color);
matrix.drawPixel(7, 4, color);
// Columna antes de la propina
matrix.drawPixel(6, 2, color);
matrix.drawPixel(6, 3, color);
matrix.drawPixel(6, 4, color);
matrix.drawPixel(6, 5, color);
// Eje
matrix.drawLine(1, 3, 5, 3, color);
matrix.drawLine(1, 4, 5, 4, color);
break;
case ARROW_CENTER:
default:
// Simple más en el centro
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 → DETECCIÓN LATERAL --------
// Calibramos antes:
// +X = USB, -X = OUSB
// +Y = 15, -Y = 34 (después de tu corrección)
Side detectSideUp(float ax_g, float ay_g, float az_g) {
// Detección de planos
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;
// Umbrales para decir "este eje está realmente inclinado"
const float tiltThreshY = 0.5f;
const float tiltThreshX = 0.5f;
// Preferir el eje Y para 15 / 34
if (fabs(ay_g) >= tiltThreshY) {
if (ay_g > 0) {
return SIDE_34; // +Y = 34 arriba
} else {
return SIDE_15; // -Y = 15 arriba
}
}
// De lo contrario, utiliza el eje X para USB / OUSB
if (fabs(ax_g) >= tiltThreshX) {
if (ax_g > 0) {
return SIDE_USB; // +X = USB arriba
} else {
return SIDE_OUSB; // -X = OUSB hacia arriba
}
}
// No claramente inclinado → tratar como centro
return SIDE_CENTER;
}
// Mapa desde el lado de UP hacia donde debería apuntar la flecha.
Side arrowSideFromUpSide(Side upSide) {
if (!useOppositeMapping) {
// La flecha indica el lado que está ARRIBA.
return upSide;
}
// La flecha muestra el lado opuesto.
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;
}
}
// Convertir LADO a 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;
}
}
// ---------------- CONFIGURACIÓN Y BUCLE ----------------
void setup() {
Serial.begin(115200);
delay(500);
matrix.begin();
matrix.setBrightness(20);
matrix.fillScreen(0);
matrix.show();
// IMU: SDA=11, SCL=12 en 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);
// Depurar
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);
}
Cosas que podrías necesitar
-
Amazonas
-
eBay
-
AliExpressCompra ESP32-S3 Matriz RGB en AliExpress (2)s.click.aliexpress.com
-
AliExpressCompra la matriz RGB ESP32-S3 en AliExpress.s.click.aliexpress.com
Recursos y referencias
-
Interno🎨 Herramienta de selección de colorrobojax.com
Archivos📁
Archivo de Fritzing
-
parte fritzing esp32-S3-supermini-tht
esp32-S3-supermini-tht.fzpz0.02 MB