Pretraži kod

ESP32-S3 RGB LED Matrica Projekat 5 - Strelica uvijek gore

ESP32-S3 RGB LED Matrica Projekat 5 - Strelica uvijek gore

Projekat 5 – Strelica uvijek gore (Indikator orijentacije pomoću QMI8658C)

Projekat 5 koristi QMI8658C senzor pokreta za detekciju orijentacije ESP32-S3 RGB LED matrice i uvijek prikazuje strelicu koja pokazuje GORE u odnosu na gravitaciju. Bez obzira na to kako rotirate ploču—USB stranom gore, OUSB stranom gore, stranom “15” ili stranom “34”—strelica se automatski okreće i pokazuje prema fizički gornjem smjeru.

Ovo je moćna demonstracija praćenja orijentacije u realnom vremenu pomoću ugrađenog akcelerometra. Svih šest projekata za ovaj modul prikazano je u jednom YouTube videu, koji je također ugrađen na ovoj stranici. Kompletan kod za Projekat 5 automatski se učitava ispod članka, a affiliate linkovi se pojavljuju ispod sekcije s kodom.

Pregled ESP32-S3 RGB LED Matrix modula

ESP32-S3 RGB LED Matrix modul uključuje nekoliko komponenti koje omogućavaju ovaj projekat:

  • ESP32-S3 mikrokontroler — pruža Wi-Fi, BLE i pokreće LED/IMU logiku.
  • 8×8 RGB LED matrica — prikazuje strelicu u jednoj od četiri orijentacije.
  • QMI8658C akcelerometar — detektuje nagib, pokret i orijentaciju.
  • USB-C priključak za napajanje i programiranje u Arduino IDE.
  • Reset i Boot dugmad za upload skica.
  • GPIO pinovi dostupni oko ploče za dodatne projekte.

Smjer strelice u potpunosti je određen očitanjima akcelerometra. Kada se ploča rotira, QMI8658C osjeti nove X/Y/Z vrijednosti, a skica bira koji uzorak strelice (↑, ↓, ←, →) treba nacrtati.

Projekti prikazani u videu (Vremenske oznake)

  • 00:00 – Uvod
  • 02:01 – Instaliranje ESP32 ploča
  • 03:32 – Instaliranje biblioteka
  • 05:32 – Projekat 1: Pokretna tačka
  • 11:11 – Projekat 2: Tekst pomjeranje
  • 12:59 – Projekat 3: HTTP tekst
  • 16:41 – Projekat 4: Nagibna tačka
  • 18:55Projekat 5: Strelica uvijek gore (ovaj projekat)
  • 20:02 – Projekat 6: Igra ciljanja

Video jasno pokazuje kako strelica trenutno mijenja smjer na osnovu toga kako je modul okrenut. Gledanje ovog segmenta se snažno preporučuje.

Instaliranje ESP32 ploča u Arduino IDE

Ako ste završili bilo koji raniji projekat, podešavanje ploče je već gotovo. U suprotnom:

  1. File > Preferences → Dodajte ESP32 board URL
  2. Tools > Board > Boards Manager… → Instalirajte “ESP32”
  3. Odaberite ESP32-S3 ploču pod Tools > Board
  4. Odaberite ispravan USB COM port pod Tools > Port

Instaliranje potrebnih biblioteka

Projekat 5 koristi:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (senzor pokreta)
  1. Sketch > Include Library > Manage Libraries…
  2. Pretraga: NeoMatrix → Instalirajte
  3. Instalirajte zavisnosti: NeoPixel + GFX
  4. Pretražite i instalirajte QMI8658 od njegovog autora

Kako Projekat 5 radi

QMI8658C mjeri gravitaciju na X, Y i Z osama. Poređenjem ovih vrijednosti, skica određuje koja fizička strana ploče je okrenuta prema gore:

  • USB strana gore
  • OUSB strana gore (suprotna od USB)
  • Strana “15” gore
  • Strana “34” gore

Svaka orijentacija odgovara različitom uzorku strelice na 8×8 matrici. Mapiranje slijedi vašu potvrđenu logiku orijentacije iz ranijih sesija otklanjanja grešaka. Rotacija ploče se kontinuirano očitava, a strelica se ažurira čim se gornja strana promijeni.

Projekat 5 – Podešavanja koda (Strelica uvijek gore)

Ispod su korisnički podesive vrijednosti iz konfiguracijske oblasti. Kompletan projektni kod pojavljuje se automatski ispod članka.

Konfiguracija matrice


// Konfiguracija matrice
const int MATRIX_PIN    = 14;   // fiksno za ovaj modul
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

// Preporučena orijentacija: Gornji-lijevi početak, progresivni način
// (stvarni konstruktor je unutar koda učitano ispod)

Ovaj projekat koristi NEO_MATRIX_PROGRESSIVE raspored kako bi se osiguralo da strelica ispravno pokazuje na osnovu stvarnog pokreta.

Svjetlina


uint8_t matrixBrightness = 40;   // 0–255

Ovu vrijednost možete povećati za svjetlija okruženja. Za unutrašnju upotrebu, 30–60 je ugodno.

Boja strelice


// Boja strelice
uint8_t arrowRed   = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue  = 0;

Promijenite ove vrijednosti da biste modificirali boju strelice. Na primjer:

  • Zelena strelica: (0, 255, 0)
  • Plava strelica: (0, 0, 255)
  • Bijela strelica: (255, 255, 255)

Osjetljivost i izglađivanje

Da bi se izbjeglo podrhtavanje, kod uključuje logiku izglađivanja i praga. U postavkama možete pronaći nešto poput:


// Podešavanje osjetljivosti / izglađivanja
float tiltThreshold = 0.30f;   // prilagodite ako se strelica prelako mijenja
  • Ako se vaša strelica previše lako okrene → povećajte prag.
  • Ako je strelica prespora da se promijeni → smanjite prag.

Uzorci strelica

Skica uključuje bitmap uzorke strelica za:

  • ↑ gore
  • ↓ dolje
  • ← lijevo
  • → desno

Ne morate ih mijenjati, ali možete promijeniti oblike unutar koda ako želite drugačiji stil.

Sažetak

Projekat 5 pokazuje kako ESP32-S3 RGB LED matrica i QMI8658C akcelerometar rade zajedno kako bi detektovali orijentaciju i prikazali strelicu koja uvijek pokazuje prema gore. Ovaj projekat se nadograđuje na Tilt Dot (Projekat 4) i priprema vas za finalnu interaktivnu igru u Projektu 6.

Kompletna skica “Strelica uvijek gore” dostupna je ispod ovog članka (automatski učitana). Preporučuje se gledanje odgovarajućeg dijela videa kako biste vidjeli koliko trenutno strelica reaguje na rotaciju ploče. Ako želite izgraditi ovaj projekat kod kuće, affiliate linkovi za ESP32-S3 RGB LED Matrix modul pojavljuju se ispod odjeljka s kodom.

Slike

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
Jezik: C++
/* 
  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);
}

Stvari koje bi vam mogle zatrebati

Resursi i reference

Datoteke📁

Fritzing datoteka