کوڈ تلاش کریں

ESP32-S3 آر جی بی ایل ای ڈی میٹرکس پروجیکٹ 4 - جھکاؤ ڈاٹ

ESP32-S3 آر جی بی ایل ای ڈی میٹرکس پروجیکٹ 4 - جھکاؤ ڈاٹ

پروجیکٹ 4 – ٹِلٹ ڈاٹ (ESP32-S3 RGB LED میٹرکس کو جھکا کر ڈاٹ کو حرکت دیں)

پروجیکٹ 4 ESP32-S3 RGB LED میٹرکس ماجیول میں شامل موشن سینسر متعارف کراتا ہے۔ ڈاٹ کو خود بخود حرکت دینے (جیسے پروجیکٹ 1) یا ٹیکسٹ اسکرول کرنے (پروجیکٹس 2 اور 3) کے بجائے، یہ پروجیکٹ آپ کو بورڈ کو صرف جھکا کر ڈاٹ کی پوزیشن کنٹرول کرنے دیتا ہے۔ ڈاٹ ماجیول کے پچھلے حصے پر موجود QMI8658C ایکسلرومیٹر کی لائیو ریڈنگز کی بنیاد پر 8×8 RGB ڈسپلے پر آسانی سے حرکت کرتا ہے۔

اس سیریز کے تمام چھ پروجیکٹس ایک YouTube ویڈیو میں دکھائے گئے ہیں۔ وہی ویڈیو اس صفحے پر ایمبیڈڈ ہے، تاکہ آپ دیکھ سکیں کہ بورڈ جھکنے پر ڈاٹ حقیقی وقت میں کیسے حرکت کرتا ہے۔ اس پروجیکٹ کا مکمل کوڈ مضمون کے نیچے خود بخود لوڈ ہوتا ہے، اور ماجیول کے لیے ایفیلی ایٹ خریداری لنکس کوڈ سیکشن کے نیچے ظاہر ہوتے ہیں۔

ESP32-S3 RGB LED میٹرکس ماجیول کا جائزہ

یہ پروجیکٹ ESP32-S3 RGB LED میٹرکس ماجیول استعمال کرتا ہے، جس میں شامل ہیں:

  • ESP32-S3 مائیکروکنٹرولر Wi-Fi اور بلوٹوتھ کے ساتھ
  • 8×8 RGB LED میٹرکس (64 انفرادی طور پر ایڈریس ایبل LEDs)
  • QMI8658C ایکسلرومیٹر پچھلے حصے پر جھکاؤ اور موشن کا پتہ لگانے کے لیے
  • USB پورٹ پروگرامنگ اور پاور کے لیے
  • بوٹ / ری سیٹ بٹن
  • استعمال کے قابل GPIO پنز مستقبل کی توسیع کے لیے

QMI8658C سینسر X، Y، اور Z ایکسلریشن اور اورینٹیشن ویلیوز پڑھتا ہے، جس سے ڈاٹ بورڈ کے جھکاؤ کی بنیاد پر اوپر/نیچے/بائیں/دائیں حرکت کر سکتا ہے۔

ویڈیو میں شامل پروجیکٹس (ٹائم اسٹیمپس)

  • 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: ٹارگٹ گیم

ویڈیو میں ٹِلٹ ڈیموسٹریشن دیکھنے کی سختی سے سفارش کی جاتی ہے، کیونکہ آپ دیکھ سکتے ہیں کہ ڈاٹ بورڈ کی اورینٹیشن پر کیسے آسانی سے رد عمل ظاہر کرتا ہے۔

Arduino IDE میں ESP32 بورڈز انسٹال کرنا

اگر آپ نے کوئی پہلے پروجیکٹ مکمل کیا ہے، تو بورڈ سپورٹ پہلے سے انسٹال ہے۔ بصورت دیگر، ان مراحل پر عمل کریں:

  1. File > Preferences کھولیں اور ESP32 Boards 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 کو اس کے درج کردہ مصنف کے ذریعے تلاش کریں اور انسٹال کریں۔

پروجیکٹ 4 کیسے کام کرتا ہے

QMI8658C سینسر مسلسل X، Y، اور Z محوروں کے ساتھ ایکسلریشن ڈیٹا فراہم کرتا ہے۔ اس پروجیکٹ کے لیے، ہم صرف X اور Y محور استعمال کرتے ہیں تاکہ فیصلہ کیا جا سکے:

  • ڈاٹ کو بائیں یا دائیں کتنا منتقل کرنا ہے (X محور)
  • ڈاٹ کو اوپر یا نیچے کتنا منتقل کرنا ہے (Y محور)

سینسر ویلیوز کو 0 سے 7 تک کے کوآرڈینیٹ رینج میں میپ کیا جاتا ہے (8×8 LED میٹرکس کے لیے)۔ ڈاٹ کی پوزیشن فی سیکنڈ کئی بار اپڈیٹ ہوتی ہے، جس سے ماجیول کو جھکانے پر ہموار سلائیڈنگ اثر ملتا ہے۔

پروجیکٹ 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;   // بڑی ویلیو = اسکرین پر تیز حرکت

اگر ڈاٹ بہت آہستہ حرکت کرتا ہے تو ویلیو بڑھائیں۔ اگر ڈاٹ بہت اچانک حرکت کرتا ہے تو اسے کم کریں۔

اپڈیٹ اسپیڈ (ریفریش ریٹ)

آپ اپڈیٹس کے درمیان ایک چھوٹی تاخیر شامل کر سکتے ہیں تاکہ حرکت ہموار ہو:


// پوزیشن اپڈیٹس کے درمیان تاخیر (ملی سیکنڈ)
int refreshDelayMs = 20;   // کم = زیادہ ہموار اور تیز ردعمل

10–30 ملی سیکنڈ کے درمیان اقدار بہت ذمہ دار محسوس ہوتی ہیں۔

خلاصہ

پروجیکٹ 4 ESP32-S3 کے بلٹ ان QMI8658C ایکسلرومیٹر کو زندہ کرتا ہے جس سے آپ LED میٹرکس کو جسمانی حرکت کے ذریعے کنٹرول کر سکتے ہیں۔ بورڈ کا ہلکا سا جھکاؤ نقطہ کو اسی سمت میں حرکت دیتا ہے، جس سے یہ پروجیکٹ زیادہ جدید “Arrow Up” اور “Target Game” پروجیکٹس کے لیے ایک بہترین قدم ہے۔

مکمل Tilt Dot اسکیچ اس مضمون کے نیچے (خودکار طور پر) لوڈ کیا گیا ہے۔ بہترین سمجھ کے لیے، ویڈیو میں جھکاؤ کا مظاہرہ دیکھیں، جہاں آپ دیکھ سکتے ہیں کہ بورڈ گھومنے پر نقطہ کتنی ہمواری سے حرکت کرتا ہے۔ ESP32-S3 RGB LED میٹرکس ماجیول خریدنے کے لنکس کوڈ سیکشن کے نیچے شامل ہیں۔

تصاویر

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
زبان: 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);
}



آپ کو جن چیزوں کی ضرورت ہو سکتی ہے

وسائل اور حوالہ جات

فائلیں📁

فریٹزنگ فائل