Search Code

ESP32-S3 RGB LED میټرکس پروژه ۴ - ټیلټ ډاټ

ESP32-S3 RGB LED میټرکس پروژه ۴ - ټیلټ ډاټ

پروژه ۴ – ټیلټ ډاټ (د ESP32-S3 RGB LED میټرکس په ټیلټولو سره ډاټ حرکت کړئ)

پروژه ۴ د ESP32-S3 RGB LED میټرکس ماډل کې جوړ شوی حرکت سینسر معرفي کوي. د دې پر ځای چې ډاټ په اتوماتيک ډول حرکت وکړي (لکه د پروژې ۱) یا متن سکرول شي (پروژې ۲ او ۳)، دا پروژه تاسو ته اجازه درکوي چې د بورډ په ټیلټولو سره د ډاټ موقعیت کنټرول کړئ. ډاټ د ماډل په شا اړخ کې د QMI8658C اکسلرومیټر له ژوندی لوستلو پر بنسټ په ۸×۸ RGB ښودونکي کې په نرمۍ سره حرکت کوي.

د دې لړۍ ټول شپږ پروژې په یوه YouTube ویډیو کې نندارې ته وړاندې شوي. همدا ویډیو په دې پاڼه کې ځای پر ځای شوې ده، نو تاسو کولی شئ په ریښتیني وخت کې وګورئ چې ډاټ څنګه د بورډ په ټیلټولو سره حرکت کوي. د دې پروژې بشپړ کوډ د مقالې لاندې په اتوماتيک ډول بار شوی، او د ماډل لپاره د اړوند پیرود لینکونه د کوډ برخې لاندې ښکاري.

د ESP32-S3 RGB LED میټرکس ماډل عمومي کتنه

دا پروژه د ESP32-S3 RGB LED میټرکس ماډل کاروي، چې پدې کې شامل دي:

  • ESP32-S3 مایکروکنټرولر د Wi-Fi او Bluetooth سره
  • ۸×۸ RGB LED میټرکس (۶۴ انفرادي پتې لرونکي LEDs)
  • QMI8658C اکسلرومیټر په شا اړخ کې د ټیلټ او حرکت کشف لپاره
  • USB بندرګاه د پروګرام کولو او بریښنا لپاره
  • بوټ / ریسیټ تڼۍ
  • د کارولو وړ GPIO پنونه د راتلونکي پراختیا لپاره

د QMI8658C سینسر د X، Y او Z سرعت او سمت ارزښتونه لولي، چې ډاټ ته اجازه ورکوي چې د بورډ د ټیلټ پر بنسټ پورته/ښکته/کیڼ/ښي حرکت وکړي.

په ویډیو کې پوښل شوي پروژې (وختونه)

  • 00:00 – پیژندنه
  • 02:01 – د ESP32 بورډونو نصبول
  • 03:32 – د کتابتونونو نصبول
  • li>05:32 – پروژه ۱: حرکت کوونکی ډاټ
  • 11:11 – پروژه ۲: د متن سکرول
  • 12:59 – پروژه ۳: HTTP متن
  • 16:41پروژه ۴: ټیلټ ډاټ (دا پروژه)
  • 18:55 – پروژه ۵: پورته تیر
  • 20:02 – پروژه ۶: هدف لوبه

په ویډیو کې د ټیلټ نندارې لیدل خورا سپارښتنه کیږي، ځکه چې تاسو کولی شئ وګورئ چې ډاټ څنګه د بورډ سمت ته په نرمۍ سره غبرګون ښیې.

په Arduino IDE کې د ESP32 بورډونو نصبول

که تاسو کوم مخکینی پروژه بشپړه کړې وي، د بورډ ملاتړ دمخه نصب شوی. که نه، دا ګامونه تعقیب کړئ:

  1. File > Preferences خلاص کړئ → د ESP32 بورډونو URL اضافه کړئ.
  2. Tools > Board > Boards Manager… ته لاړ شئ او ESP32 نصب کړئ.
  3. د Tools > Board لاندې خپل ESP32-S3 بورډ غوره کړئ.
  4. د Tools > Port لاندې سم COM بندرګاه غوره کړئ.

د اړینو کتابتونونو نصبول

دا پروژه لاندې کتابتونونو ته اړتیا لري:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX Library
  • QMI8658 (د حرکت سینسر)

دوی د کتابتون مدیر کې نصب کړئ:

  1. Sketch > Include Library > Manage Libraries… خلاص کړئ.
  2. د Adafruit NeoMatrix لټون وکړئ → نصب کړئ.
  3. د Adafruit GFX او Adafruit NeoPixel اتوماتیک نصب ته اجازه ورکړئ.
  4. د QMI8658 لټون د هغه د لیکوال له مخې وکړئ → نصب کړئ.

پروژه ۴ څنګه کار کوي

د QMI8658C سینسر په دوامداره توګه د X، Y او Z محورونو په اوږدو کې د سرعت معلومات چمتو کوي. د دې پروژې لپاره، موږ یوازې د X او Y محورونه کاروو ترڅو پریکړه وکړو:

  • ډاټ څومره کیڼ یا ښي خوا ته حرکت وکړي (X محور)
  • ډاټ څومره پورته یا ښکته حرکت وکړي (Y محور)

د سینسر ارزښتونه د ۰ څخه تر ۷ پورې په یوه همغږي سلسله کې نقشه کیږي (د ۸×۸ LED میټرکس لپاره). د ډاټ موقعیت په هر ثانیه کې څو ځله تازه کیږي، چې د ماډل په ټیلټولو سره نرم سلایډینګ اغیز ورکوي.

پروژه ۴ – د کوډ ترتیبات (ټیلټ ډاټ)

لاندې د کارونکي لخوا د سمون وړ ترتیبات دي چې د پروژې د کوډ په پورتنۍ برخه کې موندل کیږي. بشپړ سکیچ د مقالې لاندې په اتوماتيک ډول ښکاري.

د میټرکس پن او اندازه


// د ۸×۸ RGB میټرکس ترتیب
const int MATRIX_PIN    = 14;   // د دې بورډ لپاره ټاکل شوی پن
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

MATRIX_PIN په 14 پریږدئ. دا په بورډ کې میټرکس ته په کلکه تړلی دی.

روښانتیا


// ټوله روښانتیا (۰–۲۵۵)
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;   // لوی = په سکرین کې ګړندی حرکت

که ډاټ ډیر ورو حرکت کوي → ارزښت زیات کړئ. که ډاټ ډیر ناڅاپي حرکت کوي → کم کړئ.

د تازه کولو سرعت (ریفریش ریټ)

تاسو کولی شئ د تازه معلوماتو ترمنځ یو کوچنی ځنډ اضافه کړئ ترڅو حرکت نرم شي:


// د موقعیت د تازه معلوماتو ترمنځ ځنډ (ملی ثانیه)
int refreshDelayMs = 20;   // ټیټ = نرم او ګړندی غبرګون

د 10–30 ملی ثانیو ترمنځ ارزښتونه ډېر ځواب ویونکي احساس کیږي.

لنډیز

پروژه 4 د ESP32-S3 جوړ شوی QMI8658C اکسلرومیټر ژوندی کوي تاسو ته اجازه درکوي چې د 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