Cerca codice

Progetto Matrice LED RGB ESP32-S3 5 - Freccia sempre verso l'alto

Progetto Matrice LED RGB ESP32-S3 5 - Freccia sempre verso l'alto

Progetto 5 - Freccia Sempre Su (Indicatore di Orientamento utilizzando QMI8658C)

Il Progetto 5 utilizza il sensore di movimento QMI8658C per rilevare l'orientamento della matrice LED RGB ESP32-S3 e visualizzare sempre una freccia che punta verso l'alto rispetto alla gravità. Non importa come ruoti la scheda - lato USB in alto, lato OUSB in alto, lato "15" o lato "34" - la freccia si gira automaticamente e punta verso la direzione fisicamente superiore.

Questa è una potente dimostrazione di rilevamento dell'orientamento in tempo reale utilizzando l'accelerometro integrato. Tutti e sei i progetti per questo modulo sono dimostrati in un video di YouTube, che è anche incorporato in questa pagina. Il codice completo per il Progetto 5 si carica automaticamente sotto l'articolo, e i link affiliati appaiono sotto la sezione del codice.

Panoramica del modulo matrice LED RGB ESP32-S3

Il modulo matrice LED RGB ESP32-S3 include diversi componenti che rendono possibile questo progetto:

  • microcontrollore ESP32-S3- fornisce Wi-Fi, BLE e gestisce la logica LED/IMU.
  • matrice LED RGB 8×8- visualizza la freccia in una delle quattro orientamenti.
  • accelerometro QMI8658C- rileva inclinazione, movimento e orientamento.:contentReference[oaicite:0]{index=0}
  • porta USB-Cper la potenza e la programmazione in Arduino IDE.
  • Pulsanti di Reset e Avvioper caricare schizzi.
  • Pini GPIOdisponibile per tutta la commissione per progetti aggiuntivi.

La direzione della freccia è determinata interamente dalle letture dell'accelerometro. Quando la scheda viene ruotata, il QMI8658C rileva i nuovi valori X/Y/Z e lo sketch sceglie quale modello di freccia (↑, ↓, ←, →) dovrebbe essere disegnato.

Progetti Coperti nel Video (Timestamp)

  • 00:00- Introduzione
  • 02:01- Installazione delle schede ESP32
  • 03:32- Installazione delle librerie
  • 05:32- Progetto 1: Punto in movimento
  • 11:11- Progetto 2: Scorrimento Testo
  • 12:59- Progetto 3: Testo HTTP
  • 16:41- Progetto 4: Tilt Dot
  • 18:55-Progetto 5: Freccia Sempre Su (questo progetto)
  • 20:02- Progetto 6: Gioco di Mira

Il video mostra chiaramente come la freccia cambi direzione istantaneamente in base a come viene girato il modulo. Si consiglia vivamente di guardare questo segmento.:contentReference[oaicite:1]{index=1}

Installazione delle schede ESP32 nell'IDE Arduino

Se hai completato un progetto precedente, la configurazione della scheda è già stata completata. Altrimenti:

  1. File > Preferences→ Aggiungi URL della scheda ESP32
  2. Tools > Board > Boards Manager…→ Installa "ESP32"
  3. Seleziona la scheda ESP32-S3 sottoTools > Board
  4. Seleziona la porta USB COM corretta sottoTools > Port

Installazione delle librerie necessarie

Il Progetto 5 utilizza:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658(sensore di movimento)
  1. Sketch > Include Library > Manage Libraries…
  2. Cerca:NeoMatrix→ Installa
  3. Installa le dipendenze:NeoPixel+GFX
  4. Cerca e installaQMI8658dal suo autore

Come funziona il Progetto 5

Il QMI8658C misura la gravità sugli assi X, Y e Z. Confrontando questi valori, il circuito determina quale lato fisico della scheda è rivolto verso l'alto:

  • USB rivolto verso l'alto
  • Lato OUSB rivolto verso l'alto(opposto USB)
  • Lato "15" in su
  • Lato "34" in su

Ogni orientamento corrisponde a un diverso schema di frecce nella matrice 8×8. La mappatura segue la logica di orientamento confermata nelle precedenti sessioni di debug. La rotazione della scheda viene letta continuamente e la freccia si aggiorna non appena il lato superiore cambia.

Progetto 5 - Impostazioni Codice (Freccia Sempre Su)

Di seguito ci sono i valori regolabili dall'utente nell'area di configurazione. Il codice completo del progetto appare automaticamente sotto l'articolo.

Configurazione della matrice


// 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)

Questo progetto utilizzaNEO_MATRIX_PROGRESSIVElayout per assicurarsi che la freccia punti correttamente in base al movimento reale.

Luminosità


uint8_t matrixBrightness = 40;   // 0–255

Puoi aumentare questo valore per ambienti più luminosi. Per l'uso interno, 30-60 è confortevole.

Colore della freccia


// Arrow color
uint8_t arrowRed   = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue  = 0;

Cambia questi valori per modificare il colore della freccia. Ad esempio:

  • Freccia verde:(0, 255, 0)
  • Freccia blu:(0, 0, 255)
  • Freccia bianca:(255, 255, 255)

Sensibilità e Lisciatura

Per evitare il jitter, il codice include logica di smoothing e soglia. Nelle impostazioni potresti trovare qualcosa come:


// Sensitivity / smoothing adjustment
float tiltThreshold = 0.30f;   // adjust if arrow changes too easily
  • Se la tua freccia si capovolge troppo facilmente →aumentosoglia.
  • Se la freccia è troppo lenta a cambiare →diminuiresoglia.

Modelli di Frecce

Il disegno include modelli di bitmap con frecce per:

  • su
  • giù
  • ← sinistra
  • → destra

Non è necessario modificare questi, ma puoi cambiare le forme all'interno del codice se desideri uno stile diverso.

Riepilogo

Il Progetto 5 dimostra come il Matrix LED RGB ESP32-S3 e l'accelerometro QMI8658C lavorino insieme per rilevare l'orientamento e visualizzare una freccia che punta sempre verso l'alto. Questo progetto si basa sul Tilt Dot (Progetto 4) e ti prepara per il gioco interattivo finale nel Progetto 6.

Il disegno completo "Arrow Always Up" è disponibile sotto questo articolo (caricato automaticamente). Si consiglia vivamente di guardare la parte corrispondente del video per vedere come l'arrow risponde istantaneamente alla rotazione della scheda. Se desideri realizzare questo progetto a casa, i link affiliati per il modulo ESP32-S3 RGB LED Matrix appaiono sotto la sezione del codice.

Immagini

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
Lingua: C++
/*
 * Progetto 5: Freccia Sempre Su - Matrice LED RGB ESP32-S3 (Waveshare) Questo sketch legge l'inclinazione dall'IMU QMI8658C e sposta dolcemente un punto sulla matrice LED RGB 8×8 in base all'orientamento della scheda.
 * 
 * ▶️ Video Tutorial: https://youtu.be/JKLuYrRcLMI
 * 
 * 📚⬇️ Risorse & Pagina di Codice: 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> // di Lahav Gahali

 // -------- CONFIGURAZIONE MATRICE 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
);

 // -------- CONFIGURAZIONE IMU QMI8658 --------
QMI8658 imu;
QMI8658_Data imuData;

 // -------- IMPOSTAZIONI UTENTE --------

 // vero -> la freccia punta al lato opposto
 // USB↔OUSB, 34↔15
 // falso -> la freccia punta verso lo stesso lato che è IN ALTO
bool useOppositeMapping = false;

 // Colore della freccia (0-255 ciascuno)
uint8_t dotRed   = 0;
uint8_t dotGreen = 150;
uint8_t dotBlue  = 0;

 // Lati della tavola
enum Side {
  SIDE_CENTER = 0,
  SIDE_USB,
  SIDE_OUSB,
  SIDE_15,
  SIDE_34
};

 // Direzione per il disegno della freccia
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 "?";
  }
}

 // -------- DISEGNO DI FRECCIA (IL TUO CODICE, INVARIATO) --------

 // Disegna una semplice freccia su una matrice 8x8 che punta nella direzione fornita.
void drawArrow(ArrowDir dir, uint16_t color) {
  matrix.fillScreen(0);

  switch (dir) {
    case ARROW_UP:
 // Suggerimento
      matrix.drawPixel(3, 0, color);
      matrix.drawPixel(4, 0, color);
 // Seconda fila
      matrix.drawPixel(2, 1, color);
      matrix.drawPixel(3, 1, color);
      matrix.drawPixel(4, 1, color);
      matrix.drawPixel(5, 1, color);
 // Albero
      matrix.drawLine(3, 2, 3, 6, color);
      matrix.drawLine(4, 2, 4, 6, color);
      break;

    case ARROW_DOWN:
 // Suggerimento
      matrix.drawPixel(3, 7, color);
      matrix.drawPixel(4, 7, color);
 // Riga sopra la punta
      matrix.drawPixel(2, 6, color);
      matrix.drawPixel(3, 6, color);
      matrix.drawPixel(4, 6, color);
      matrix.drawPixel(5, 6, color);
 // Albero
      matrix.drawLine(3, 1, 3, 5, color);
      matrix.drawLine(4, 1, 4, 5, color);
      break;

    case ARROW_LEFT:
 // Suggerimento
      matrix.drawPixel(0, 3, color);
      matrix.drawPixel(0, 4, color);
 // Colonna dopo la mancia
      matrix.drawPixel(1, 2, color);
      matrix.drawPixel(1, 3, color);
      matrix.drawPixel(1, 4, color);
      matrix.drawPixel(1, 5, color);
 // Albero
      matrix.drawLine(2, 3, 6, 3, color);
      matrix.drawLine(2, 4, 6, 4, color);
      break;

    case ARROW_RIGHT:
 // Suggerimento
      matrix.drawPixel(7, 3, color);
      matrix.drawPixel(7, 4, color);
 // Colonna prima della punta
      matrix.drawPixel(6, 2, color);
      matrix.drawPixel(6, 3, color);
      matrix.drawPixel(6, 4, color);
      matrix.drawPixel(6, 5, color);
 // Albero
      matrix.drawLine(1, 3, 5, 3, color);
      matrix.drawLine(1, 4, 5, 4, color);
      break;

    case ARROW_CENTER:
    default:
 // Semplice più al 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 → RILEVAMENTO LATERALE --------
 // Abbiamo calibrato prima:
 // +X = USB, -X = OUSB
 // +Y = 15, -Y = 34 (dopo la tua correzione)

Side detectSideUp(float ax_g, float ay_g, float az_g) {
 // Rilevamento di piani
  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;

 // Soglie per dire "questo asse è davvero inclinato"
  const float tiltThreshY = 0.5f;
  const float tiltThreshX = 0.5f;

 // Preferisci l'asse Y per 15 / 34
  if (fabs(ay_g) >= tiltThreshY) {
    if (ay_g > 0) {
      return SIDE_34; // +Y = 34 su
    } else {
      return SIDE_15; // -Y = 15 su
    }
  }

 // In caso contrario, utilizzare l'asse X per USB / OUSB
  if (fabs(ax_g) >= tiltThreshX) {
    if (ax_g > 0) {
      return SIDE_USB; // +X = USB su
    } else {
      return SIDE_OUSB; // -X = OUSB su
    }
  }

 // Non inclinato chiaramente → trattare come centrale
  return SIDE_CENTER;
}

 // Mappa dal lato UP verso dove dovrebbe puntare la freccia
Side arrowSideFromUpSide(Side upSide) {
  if (!useOppositeMapping) {
 // La freccia indica il lato che è IN ALTO.
    return upSide;
  }

 // La freccia indica il lato opposto.
  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;
  }
}

 // Converti SIDE in 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;
  }
}

 // ---------------- CONFIGURAZIONE & CICLO ----------------

void setup() {
  Serial.begin(115200);
  delay(500);

  matrix.begin();
  matrix.setBrightness(20);
  matrix.fillScreen(0);
  matrix.show();

 // IMU: SDA=11, SCL=12 su 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);
}

Cose di cui potresti avere bisogno

Risorse e riferimenti

File📁

File Fritzing