Search Code

Proiect ESP32-S3 cu matrice LED RGB 4 - Punct de înclinare

Proiect ESP32-S3 cu matrice LED RGB 4 - Punct de înclinare

Proiectul 4 – Punct prin înclinare (Mută punctul înclinând matricea LED RGB ESP32-S3)

Proiectul 4 introduce senzorul de mișcare încorporat în modulul matricei LED RGB ESP32-S3. În loc să muți punctul automat (ca în Proiectul 1) sau să derulezi text (Proiectele 2 și 3), acest proiect îți permite să controlezi poziția punctului doar prin înclinarea plăcii. Punctul se mișcă lin pe afișajul RGB 8×8 pe baza citirilor în timp real de la accelerometrul QMI8658C din spatele modulului.

Toate cele șase proiecte din această serie sunt demonstrate într-un singur videoclip YouTube. Același videoclip este încorporat pe această pagină, astfel încât să poți vedea exact cum se mișcă punctul în timp real pe măsură ce placa este înclinată. Codul complet pentru acest proiect este încărcat automat mai jos, iar linkurile de achiziție afiliate pentru modul apar sub secțiunea de cod.

Prezentare generală a modulului matricei LED RGB ESP32-S3

Acest proiect folosește modulul matricei LED RGB ESP32-S3, care include:

  • Microcontrolerul ESP32-S3 cu Wi-Fi și Bluetooth
  • Matrice LED RGB 8×8 (64 de LED-uri adresabile individual)
  • Accelerometrul QMI8658C pe spate pentru detectarea înclinării și mișcării
  • Port USB pentru programare și alimentare
  • Butoane Boot / Reset
  • Pini GPIO utilizabili pentru extinderi viitoare

Senzorul QMI8658C citește valorile de accelerație și orientare X, Y și Z, permițând punctului să se miște sus/jos/stânga/dreapta în funcție de modul în care este înclinată placa.

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:41Proiectul 4: Punct prin înclinare (acest proiect)
  • 18:55 – Proiectul 5: Săgeată în sus
  • 20:02 – Proiectul 6: Jocul țintă

Este foarte recomandat să urmărești demonstrația de înclinare din videoclip, deoarece poți vedea cum reacționează punctul lin la orientarea plăcii.

Instalarea plăcilor ESP32 în Arduino IDE

Dacă ai finalizat orice proiect anterior, suportul pentru plăci este deja instalat. În caz contrar, urmează acești pași:

  1. Deschide Fișier > Preferințe → Adaugă URL-ul pentru plăcile ESP32.
  2. Mergi la Instrumente > Placă > Manager plăci… și instalează ESP32.
  3. Selectează placa ta ESP32-S3 sub Instrumente > Placă.
  4. Selectează portul COM corect sub Instrumente > Port.

Instalarea bibliotecilor necesare

Acest proiect necesită următoarele biblioteci:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX Library
  • QMI8658 (senzor de mișcare)

Instalează-le în Managerul de biblioteci:

  1. Deschide Schiță > Include bibliotecă > Gestionează bibliotecile….
  2. Caută Adafruit NeoMatrix → Instalează.
  3. Permite instalarea automată a Adafruit GFX și Adafruit NeoPixel.
  4. Caută QMI8658 după autorul listat → Instalează.

Cum funcționează Proiectul 4

Senzorul QMI8658C furnizează continuu date de accelerație pe axele X, Y și Z. Pentru acest proiect, folosim doar axele X și Y pentru a decide:

  • Cât de departe să se miște punctul la stânga sau la dreapta (axa X)
  • Cât de departe să se miște punctul în sus sau în jos (axa Y)

Valorile senzorului sunt mapate într-un interval de coordonate de la 0 la 7 (pentru matricea LED 8×8). Poziția punctului este actualizată de multe ori pe secundă, oferind efectul de alunecare lină pe măsură ce înclini modulul.

Proiectul 4 – Setări cod (Punct prin înclinare)

Mai jos sunt setările editabile de utilizator găsite aproape de începutul codului proiectului. Schița completă apare automat mai jos în articol.

Pinul și dimensiunea matricei


// Configurarea matricei RGB 8×8
const int MATRIX_PIN    = 14;   // pin fix pentru această placă
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

Lasă MATRIX_PIN la 14. Este conectat fix la matricea de pe placă.

Luminozitate


// Luminozitate generală (0–255)
uint8_t matrixBrightness = 40;

Crește valoarea dacă este necesar, dar evită luminozitatea extremă când privești de aproape.

Culoarea punctului


// Culoarea punctului (R, G, B)
uint8_t dotRed   = 0;
uint8_t dotGreen = 200;   // verde deschis (implicit)
uint8_t dotBlue  = 0;

Schimbă aceste valori pentru a crea orice culoare. Exemple:

  • Roșu: (255, 0, 0)
  • Galben: (255, 255, 0)
  • Alb: (255, 255, 255)

Sensibilitatea mișcării

Pentru a preveni salturile extreme, valorile accelerometrului sunt de obicei limitate sau scalate. O setare tipică arată astfel:


// Cât de agresiv afectează înclinarea mișcarea
float sensitivity = 4.0f;   // mai mare = mișcare mai rapidă pe ecran

Dacă punctul se mișcă prea lent → crește valoarea. Dacă punctul se mișcă prea brusc → scade valoarea.

Viteza de actualizare (rata de reîmprospătare)

Puteți adăuga o mică întârziere între actualizări pentru a netezi mișcarea:


// Întârziere între actualizările poziției (ms)
int refreshDelayMs = 20;   // mai mic = răspuns mai lin și mai rapid

Valorile între 10–30 ms se simt foarte receptive.

Rezumat

Proiectul 4 aduce la viață accelerometrul QMI8658C integrat al ESP32-S3, permițându-vă să controlați matricea LED cu mișcare fizică. O mică înclinare a plăcii mută punctul în aceeași direcție, făcând acest proiect un pas perfect pentru proiectele mai avansate “Arrow Up” și “Target Game”.

Sketch-ul complet Tilt Dot este încărcat mai jos în acest articol (automat). Pentru o înțelegere mai bună, urmăriți demonstrația de înclinare din videoclip, unde puteți vedea cât de lin se mișcă punctul pe măsură ce placa este rotită. Linkurile pentru achiziționarea modulului ESP32-S3 RGB LED Matrix sunt incluse sub secțiunea de cod.

Imagini

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 displaying rainbow heart
ESP32 S3 Matrix displaying rainbow heart
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3_RGB_8x8_matrix-2
802-ESP32-S3 RGB LED Matrix Project 4 - Tilt dot
Limba: C++
/* 
  Project 4: Tilt Dot – 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/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>   // 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  -> dot on opposite side: USB↔OUSB, 34↔15
// false -> dot on same side as UP
bool useOppositeMapping = false;

// Dot color (0–255 each)
uint8_t dotRed   = 0;
uint8_t dotGreen = 100;
uint8_t dotBlue  = 0;

// Board sides
enum Side {
  SIDE_CENTER = 0,
  SIDE_USB,
  SIDE_OUSB,
  SIDE_15,
  SIDE_34
};

// Smooth dot position (in pixel coordinates, but kept as float for easing)
float dotPosX = 3.0f;   // start at center
float dotPosY = 3.0f;

// Smoothing factor: smaller = slower movement (0.1 very slow, 0.5 faster)
const float dotSmooth = 0.25f;


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 "?";
  }
}

// Detect which side is UP using calibrated axes:
// +X = USB, -X = OUSB, +Y = 34, -Y = 15
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;

  // 1) Prefer Y axis for 15 / 34 if it's clearly tilted
  if (fabs(ay_g) >= tiltThreshY) {
    if (ay_g > 0) {
      return SIDE_15;   // +Y = 34 up
    } else {
      return SIDE_34;   // -Y = 15 up
    }
  }

  // 2) Otherwise, check 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
    }
  }

  // 3) If nothing is strongly tilted, just call it CENTER
  return SIDE_CENTER;
}

// Map from UP side to where the dot should go
Side dotSideFromUpSide(Side upSide) {
  switch (upSide) {
    case SIDE_USB:
      return useOppositeMapping ? SIDE_OUSB : SIDE_USB;

    case SIDE_OUSB:
      return useOppositeMapping ? SIDE_USB : SIDE_OUSB;

    case SIDE_34:
      return useOppositeMapping ? SIDE_15 : SIDE_34;

    case SIDE_15:
      return useOppositeMapping ? SIDE_34 : SIDE_15;

    case SIDE_CENTER:
    default:
      return SIDE_CENTER;
  }
}

// Convert dot side to matrix coordinates
void getDotPixel(Side dotSide, int &px, int &py) {
  // Matrix (0,0) = top-left
  // top center:    (3,0) → USB
  // bottom center: (3,7) → OUSB
  // left center:   (0,3) → 15
  // right center:  (7,3) → 34
  // center:        (3,3)

  switch (dotSide) {
    case SIDE_USB:   px = 3; py = 0; break;
    case SIDE_OUSB:  px = 3; py = 7; break;
    case SIDE_15:    px = 0; py = 3; break;
    case SIDE_34:    px = 7; py = 3; break;
    case SIDE_CENTER:
    default:         px = 3; py = 3; break;
  }
}

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

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

  // IMU: SDA=11, SCL=12 for 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 dotSide = dotSideFromUpSide(upSide);

  int targetX, targetY;
  getDotPixel(dotSide, targetX, targetY);

  // --- Smooth movement toward target ---
  dotPosX += (targetX - dotPosX) * dotSmooth;
  dotPosY += (targetY - dotPosY) * dotSmooth;

  // Convert to integer pixel coordinates
  int px = (int)round(dotPosX);
  int py = (int)round(dotPosY);

  // Clamp just in case
  if (px < 0) px = 0;
  if (px > 7) px = 7;
  if (py < 0) py = 0;
  if (py > 7) py = 7;

  // --- Draw dot ---
  matrix.fillScreen(0);
  uint16_t color = matrix.Color(dotRed, dotGreen, dotBlue);
  matrix.drawPixel(px, py, color);
  matrix.show();

  // 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(" | DOT="); Serial.print(sideName(dotSide));
  Serial.print(" | px=");  Serial.print(px);
  Serial.print(" py=");    Serial.println(py);

  delay(80);
}



Lucruri de care ai putea avea nevoie

Resurse și referințe

Fișiere📁

Fișier Fritzing