Código de búsqueda

Proyecto de Matriz LED RGB ESP32-S3 5 - Flecha siempre arriba

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:

  1. File > Preferences→ Agregar URL de la placa ESP32
  2. Tools > Board > Boards Manager…→ Instalar "ESP32"
  3. Seleccione la placa ESP32-S3 bajoTools > Board
  4. Seleccione el puerto COM USB correcto bajoTools > Port

Instalando bibliotecas requeridas

El Proyecto 5 utiliza:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658(sensor de movimiento)
  1. Sketch > Include Library > Manage Libraries…
  2. Buscar:NeoMatrix→ Instalar
  3. Instalar dependencias:NeoPixel+GFX
  4. 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

ESP32 S3 Matrix
ESP32 S3 Matrix
ESP32 S3 Matrix  pin out
ESP32 S3 Matrix pin out
ESP32-S3_RGB_8x8_matrix-3
ESP32-S3_RGB_8x8_matrix-3
ESP32 S3 Matrix attached with buzzer to pin6 and GND
ESP32 S3 Matrix attached with buzzer to pin6 and GND
ESP32 S3 Matrix displaying red heart
ESP32 S3 Matrix displaying red heart
ESP32 S3 Matrix displaying green heart
ESP32 S3 Matrix displaying green heart
ESP32 S3 Matrix displaying rainbow heart 3
ESP32 S3 Matrix displaying rainbow heart 3
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3-Mtrix - Alway Up
ESP32-S3-Mtrix - Alway Up
803-ESP32-S3 RGB LED Matrix Project 5 - Arrow always up
Idioma: C++
/*
 * 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

Recursos y referencias

Archivos📁

Archivo de Fritzing