Search Code

ESP32-S3 RGB LED-matriksprojek 4 - Kantelkolletjie

ESP32-S3 RGB LED-matriksprojek 4 - Kantelkolletjie

Projek 4 – Kantelkolletjie (Beweeg die Kolletjie deur die ESP32-S3 RGB LED-matriks te Kantel)

Projek 4 stel die bewegingsensor bekend wat in die ESP32-S3 RGB LED-matriksmodule ingebou is. In plaas daarvan om die kolletjie outomaties te beweeg (soos in Projek 1) of teks te laat rol (Projekte 2 en 3), laat hierdie projek jou toe om die posisie van die kolletjie te beheer deur bloot die bord te kantel. Die kolletjie beweeg glad oor die 8×8 RGB-skerm gebaseer op lewendige lesings van die QMI8658C-versnellingsmeter aan die agterkant van die module.

Al ses projekte in hierdie reeks word in een YouTube-video gedemonstreer. Dieselfde video is op hierdie bladsy ingebed, sodat jy presies kan sien hoe die kolletjie in reële tyd beweeg soos die bord kantel. Die volledige kode vir hierdie projek word outomaties onder die artikel gelaai, en geaffilieerde aankoopskakels vir die module verskyn onder die kode-afdeling.

ESP32-S3 RGB LED-matriksmodule Oorsig

Hierdie projek gebruik die ESP32-S3 RGB LED-matriksmodule, wat die volgende insluit:

  • ESP32-S3-mikrobeheerder met Wi-Fi en Bluetooth
  • 8×8 RGB LED-matriks (64 individueel adresseerbare LED's)
  • QMI8658C-versnellingsmeter aan die agterkant vir kantel- en bewegingsdeteksie
  • USB-poort vir programmering en krag
  • Boot / Reset-knoppies
  • Bruikbare GPIO-penne vir toekomstige uitbreiding

Die QMI8658C-sensor lees X-, Y- en Z-versnelling- en oriëntasiewaardes, wat die kolletjie in staat stel om op/af/links/regs te beweeg gebaseer op hoe die bord gekantel word.

Projekte wat in die Video Gedek word (Tydstempels)

  • 00:00 – Inleiding
  • 02:01 – Installeer ESP32-borde
  • 03:32 – Installeer biblioteke
  • 05:32 – Projek 1: Beweeg Kolletjie
  • 11:11 – Projek 2: Teksrol
  • 12:59 – Projek 3: HTTP-teks
  • 16:41Projek 4: Kantelkolletjie (hierdie projek)
  • 18:55 – Projek 5: Pyl Op
  • 20:02 – Projek 6: Teiken-speletjie

Dit word sterk aanbeveel om die kanteldemonstrasie in die video te kyk, aangesien jy kan sien hoe die kolletjie glad reageer op die oriëntasie van die bord.

Installeer ESP32-borde in Arduino IDE

As jy enige vroeëre projek voltooi het, is die bordondersteuning reeds geïnstalleer. Andersins, volg hierdie stappe:

  1. Maak Lêer > Voorkeure oop → Voeg ESP32-borde-URL by.
  2. Gaan na Gereedskap > Bord > Bordbestuurder… en installeer ESP32.
  3. Kies jou ESP32-S3-bord onder Gereedskap > Bord.
  4. Kies die korrekte COM-poort onder Gereedskap > Poort.

Installeer Vereiste Biblioteke

Hierdie projek vereis die volgende biblioteke:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX Library
  • QMI8658 (bewegingsensor)

Installeer hulle in die Biblioteekbestuurder:

  1. Maak Skets > Sluit Biblioteek in > Bestuur Biblioteke… oop.
  2. Soek vir Adafruit NeoMatrix → Installeer.
  3. Laat outomatiese installasie van Adafruit GFX en Adafruit NeoPixel toe.
  4. Soek vir QMI8658 deur die gelyste outeur → Installeer.

Hoe Projek 4 Werk

Die QMI8658C-sensor verskaf deurlopend versnellingdata langs die X-, Y- en Z-asse. Vir hierdie projek gebruik ons slegs die X- en Y-asse om te besluit:

  • Hoe ver om die kolletjie links of regs te beweeg (X-as)
  • Hoe ver om die kolletjie op of af te beweeg (Y-as)

Die sensorwaardes word in 'n koördinaatreeks van 0 tot 7 (vir die 8×8 LED-matriks) gekarteer. Die kolletjieposisie word baie keer per sekonde opgedateer, wat die gladde gly-effek gee soos jy die module kantel.

Projek 4 – Kodestellings (Kantelkolletjie)

Hieronder is die gebruikersredigeerbare instellings wat naby die bokant van die projek se kode gevind word. Die volledige skets verskyn outomaties onder die artikel.

Matrikspen en -grootte


// 8×8 RGB-matrikskonfigurasie
const int MATRIX_PIN    = 14;   // vaste pen vir hierdie bord
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

Los MATRIX_PIN op 14. Dit is vasbedraad aan die aanboord-matriks.

Helderheid


// Algehele helderheid (0–255)
uint8_t matrixBrightness = 40;

Verhoog indien nodig, maar vermy uiterste helderheid wanneer jy van naby kyk.

Kolletjiekleur


// Kolletjiekleur (R, G, B)
uint8_t dotRed   = 0;
uint8_t dotGreen = 200;   // liggroen (verstek)
uint8_t dotBlue  = 0;

Verander hierdie waardes om enige kleur te skep. Voorbeelde:

  • Rooi: (255, 0, 0)
  • Geel: (255, 255, 0)
  • Wit: (255, 255, 255)

Bewegingsensitiwiteit

Om uiterste spronge te voorkom, word versnellingsmeterwaardes gewoonlik geknip of geskaal. 'n Tipiese instelling lyk so:


// Hoe aggressief kantel beweging beïnvloed
float sensitivity = 4.0f;   // groter = vinniger beweging oor skerm

As die kolletjie te stadig beweeg → verhoog die waarde. As die kolletjie te skielik beweeg → verlaag dit.

Opdateringspoed (Ververstempo)

Jy kan 'n klein vertraging tussen opdaterings byvoeg om beweging gladder te maak:


// Vertraging tussen posisie-opdaterings (ms)
int refreshDelayMs = 20;   // laer = gladder en vinniger reaksie

Waardes tussen 10–30 ms voel baie responsief.

Opsomming

Projek 4 bring die ESP32-S3 se ingeboude QMI8658C-versnellingsmeter tot lewe deur jou toe te laat om die LED-matriks met fisiese beweging te beheer. 'n Klein kanteling van die bord beweeg die kol in dieselfde rigting, wat hierdie projek 'n perfekte springplank maak vir die meer gevorderde “Pyl Op” en “Teiken Speletjie”-projekte.

Die volledige Tilt Dot-kode word onder hierdie artikel gelaai (outomaties). Vir die beste begrip, kyk na die kantel-demonstrasie in die video, waar jy kan sien hoe glad die kol beweeg terwyl die bord geroteer word. Skakels om die ESP32-S3 RGB LED-matriksmodule te koop, word onder die kode-afdeling ingesluit.

Beelde

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
Taal: 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);
}



Goedere wat jy dalk nodig het

Hulpbronne en verwysings

Lêers📁

Fritzing-lêer