Search Code

Проект 4 со RGB LED матрица на ESP32-S3 - Тилт точка

Проект 4 со RGB LED матрица на ESP32-S3 - Тилт точка

Проект 4 – Тилт точка (Поместете ја точката со навалување на ESP32-S3 RGB LED матрицата)

Проектот 4 го воведува сензорот за движење вграден во ESP32-S3 RGB LED матрица модулот. Наместо автоматско движење на точката (како во Проект 1) или лизгање текст (Проекти 2 и 3), овој проект ви овозможува да ја контролирате позицијата на точката едноставно со навалување на плочката. Точката се движи непречено низ 8×8 RGB екранот врз основа на живи читања од QMI8658C акцелерометарот на задниот дел од модулот.

Сите шест проекти во оваа серија се демонстрирани во едно YouTube видео. Истото видео е вградено на оваа страница, па можете точно да видите како точката се движи во реално време додека плочката се навалува. Целосниот код за овој проект се вчитува автоматски подолу во статијата, а affiliate линкови за купување на модулот се појавуваат под делот со код.

Преглед на ESP32-S3 RGB LED матрица модулот

Овој проект го користи ESP32-S3 RGB LED матрица модулот, кој вклучува:

  • ESP32-S3 микроконтролер со Wi-Fi и Bluetooth
  • 8×8 RGB LED матрица (64 индивидуално адресирани LED диоди)
  • QMI8658C акцелерометар на задниот дел за детекција на навалување и движење
  • USB порт за програмирање и напојување
  • Boot / Reset копчиња
  • Корисни GPIO пинови за идно проширување

QMI8658C сензорот чита X, Y и Z вредности на забрзување и ориентација, овозможувајќи и на точката да се движи горе/долу/лево/десно врз основа на тоа како плочката е навалена.:contentReference[oaicite:0]{index=0}

Проекти покриени во видеото (Временски ознаки)

  • 00:00 – Вовед
  • 02:01 – Инсталирање на ESP32 плочки
  • 03:32 – Инсталирање на библиотеки
  • 05:32 – Проект 1: Движечка точка
  • 11:11 – Проект 2: Лизгање текст
  • 12:59 – Проект 3: HTTP текст
  • 16:41Проект 4: Тилт точка (овој проект)
  • 18:55 – Проект 5: Стрелка нагоре
  • 20:02 – Проект 6: Игра со цел

Гледањето на демонстрацијата со навалување во видеото е препорачливо, бидејќи можете да видите како точката реагира непречено на ориентацијата на плочката.:contentReference[oaicite:1]{index=1}

Инсталирање на ESP32 плочки во Arduino IDE

Ако сте завршиле некој претходен проект, поддршката за плочката е веќе инсталирана. Во спротивно, следете ги овие чекори:

  1. Отворете File > Preferences → Додадете ESP32 Boards URL.
  2. Одете на Tools > Board > Boards Manager… и инсталирајте ESP32.
  3. Изберете ја вашата ESP32-S3 плочка под Tools > Board.
  4. Изберете ја точната COM порта под Tools > Port.

Инсталирање на потребните библиотеки

Овој проект ги бара следниве библиотеки:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX Library
  • QMI8658 (сензор за движење)

Инсталирајте ги во Library Manager:

  1. Отворете Sketch > Include Library > Manage Libraries….
  2. Пребарајте Adafruit NeoMatrix → Инсталирајте.
  3. Дозволете автоматска инсталација на Adafruit GFX и Adafruit NeoPixel.
  4. Пребарајте QMI8658 од наведениот автор → Инсталирајте.:contentReference[oaicite:2]{index=2}

Како функционира Проект 4

QMI8658C сензорот континуирано обезбедува податоци за забрзување долж X, Y и Z оските. За овој проект, ги користиме само X и Y оските за да одлучиме:

  • Колку далеку да се движи точката лево или десно (X оска)
  • Колку далеку да се движи точката горе или долу (Y оска)

Вредностите на сензорот се мапираат во координатен опсег од 0 до 7 (за 8×8 LED матрицата). Позицијата на точката се ажурира многу пати во секунда, давајќи го мазниот ефект на лизгање додека го навалувате модулот.:contentReference[oaicite:3]{index=3}

Проект 4 – Поставки на кодот (Тилт точка)

Подолу се поставките што може да ги уредува корисникот, кои се наоѓаат близу врвот на кодот на проектот. Целосната скица се појавува автоматски подолу во статијата.

Пин и големина на матрицата


// 8×8 RGB матрица конфигурација
const int MATRIX_PIN    = 14;   // фиксен пин за оваа плочка
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

Оставете го MATRIX_PIN на 14. Тој е жично поврзан со вградената матрица.

Осветленост


// Целокупна осветленост (0–255)
uint8_t matrixBrightness = 40;

Зголемете ја ако е потребно, но избегнувајте екстремна осветленост кога гледате одблиску.

Боја на точката


// Боја на точката (R, G, B)
uint8_t dotRed   = 0;
uint8_t dotGreen = 200;   // светло зелена (стандардно)
uint8_t dotBlue  = 0;

Променете ги овие вредности за да креирате било која боја. Примери:

  • Црвена: (255, 0, 0)
  • Жолта: (255, 255, 0)
  • Бела: (255, 255, 255)

Чувствителност на движење

За да се спречат екстремни скокови, вредностите на акцелерометарот обично се ограничуваат или скалираат. Типична поставка изгледа вака:


// Колку агресивно навалувањето влијае на движењето
float sensitivity = 4.0f;   // поголемо = побрзо движење низ екранот

Ако точката се движи премногу бавно → зголемете ја вредноста. Ако точката се движи премногу нагло → намалете ја.

Брзина на ажурирање (Стапка на освежување)

Можете да додадете мало задоцнување помеѓу ажурирањата за да го измазните движењето:


// Задоцнување помеѓу ажурирањата на позицијата (ms)
int refreshDelayMs = 20;   // помало = помазно и побрзо реагирање

Вредностите помеѓу 10–30 ms се чувствуваат многу одговорно.

Резиме

Проектот 4 го оживува вградениот QMI8658C акцелерометар на ESP32-S3, овозможувајќи ви да ја контролирате LED матрицата со физичко движење. Мало навалување на плочката го поместува точката во иста насока, што го прави овој проект совршен одѕив за понапредните проекти “Arrow Up” и “Target Game”.

Целосната скица за Tilt Dot е вчитана под оваа статија (автоматски). За најдобро разбирање, погледнете ја демонстрацијата на навалување во видеото, каде што можете да видите колку мазно се движи точката додека плочката се ротира. Линкови за купување на ESP32-S3 RGB LED Matrix модулот се вклучени под делот со кодот.

Images

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



Things you might need

Resources & references

Files📁

Fritzing File