Search Code

ESP32-S3 آر جی بی ایل ای ڈی میٹرکس پروجیکٹ 5 - تیر ہمیشہ اوپر

ESP32-S3 آر جی بی ایل ای ڈی میٹرکس پروجیکٹ 5 - تیر ہمیشہ اوپر

پروجیکٹ 5 – تیر ہمیشہ اوپر (QMI8658C کا استعمال کرتے ہوئے سمت کا اشارہ)

پروجیکٹ 5 میں QMI8658C موشن سینسر استعمال کیا گیا ہے تاکہ ESP32-S3 RGB LED میٹرکس کی سمت معلوم کی جا سکے اور ہمیشہ کشش ثقل کے نسبت اوپر کی طرف اشارہ کرنے والا تیر دکھایا جا سکے۔ اس سے کوئی فرق نہیں پڑتا کہ آپ بورڈ کو کیسے گھماتے ہیں—USB سائیڈ اوپر، OUSB سائیڈ اوپر، سائیڈ "15"، یا سائیڈ "34"—تیر خود بخود گھوم کر جسمانی طور پر اوپر کی سمت اشارہ کرتا ہے۔

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

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

ESP32-S3 RGB LED میٹرکس ماجیول میں کئی اجزاء شامل ہیں جو اس پروجیکٹ کو ممکن بناتے ہیں:

  • ESP32-S3 مائیکروکنٹرولر — Wi-Fi، BLE فراہم کرتا ہے، اور LED/IMU منطق چلاتا ہے۔
  • 8×8 RGB LED میٹرکس — تیر کو چار سمتوں میں سے کسی ایک میں دکھاتا ہے۔
  • QMI8658C ایکسلرومیٹر — جھکاؤ، حرکت اور سمت کا پتہ لگاتا ہے۔
  • USB-C پورٹ Arduino IDE میں پاور اور پروگرامنگ کے لیے۔
  • ری سیٹ اور بوٹ بٹن اسکیچز اپ لوڈ کرنے کے لیے۔
  • 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. فائل > ترجیحات → ESP32 بورڈ URL شامل کریں
  2. ٹولز > بورڈ > بورڈز مینیجر… → "ESP32" انسٹال کریں
  3. ٹولز > بورڈ کے تحت ESP32-S3 بورڈ منتخب کریں
  4. ٹولز > پورٹ کے تحت درست USB COM پورٹ منتخب کریں

مطلوبہ لائبریریز انسٹال کرنا

پروجیکٹ 5 استعمال کرتا ہے:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (موشن سینسر)
  1. اسکیچ > لائبریری شامل کریں > لائبریریز مینیج کریں…
  2. تلاش کریں: NeoMatrix → انسٹال کریں
  3. ڈیپنڈنسیز انسٹال کریں: NeoPixel + GFX
  4. تلاش کر کے QMI8658 کو اس کے مصنف کے ذریعے انسٹال کریں

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

QMI8658C X، Y اور Z محوروں پر کشش ثقل کی پیمائش کرتا ہے۔ ان اقدار کا موازنہ کرکے، اسکیچ طے کرتا ہے کہ بورڈ کا کون سا جسمانی رخ اوپر کی طرف ہے:

  • USB سائیڈ اوپر
  • OUSB سائیڈ اوپر (USB کے مخالف)
  • سائیڈ "15" اوپر
  • سائیڈ "34" اوپر

ہر سمت 8×8 میٹرکس پر ایک مختلف تیر پیٹرن سے مطابقت رکھتی ہے۔ میپنگ آپ کی پہلے ڈیبگنگ سیشنز سے تصدیق شدہ سمت منطق کی پیروی کرتی ہے۔ بورڈ کی گردش مسلسل پڑھی جاتی ہے، اور اوپر والی سائیڈ بدلتے ہی تیر اپ ڈیٹ ہو جاتا ہے۔

پروجیکٹ 5 – کوڈ سیٹنگز (تیر ہمیشہ اوپر)

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

میٹرکس کنفیگریشن


// میٹرکس کنفیگریشن
const int MATRIX_PIN    = 14;   // اس ماجیول کے لیے فکسڈ
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

// تجویز کردہ سمت: ٹاپ-لیفٹ اوریجن، پروگریسو موڈ
// (اصل کنسٹرکٹر نیچے لوڈ کیے گئے کوڈ کے اندر ہے)

یہ پروجیکٹ NEO_MATRIX_PROGRESSIVE لے آؤٹ استعمال کرتا ہے تاکہ یہ یقینی بنایا جا سکے کہ تیر اصل حرکت کی بنیاد پر درست سمت اشارہ کرے۔

چمک


uint8_t matrixBrightness = 40;   // 0–255

آپ روشن ماحول کے لیے اس ویلیو کو بڑھا سکتے ہیں۔ اندرونی استعمال کے لیے، 30–60 آرام دہ ہے۔

تیر کا رنگ


// تیر کا رنگ
uint8_t arrowRed   = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue  = 0;

تیر کا رنگ تبدیل کرنے کے لیے ان اقدار کو تبدیل کریں۔ مثال کے طور پر:

  • سبز تیر: (0, 255, 0)
  • نیلا تیر: (0, 0, 255)
  • سفید تیر: (255, 255, 255)

حساسیت اور ہموار کرنا

جھٹکے سے بچنے کے لیے، کوڈ میں ہموار کرنے اور تھریشولڈ منطق شامل ہے۔ سیٹنگز میں آپ کو کچھ اس طرح مل سکتا ہے:


// حساسیت / ہموار کرنے کی ایڈجسٹمنٹ
float tiltThreshold = 0.30f;   // اگر تیر بہت آسانی سے بدلتا ہے تو ایڈجسٹ کریں
  • اگر آپ کا تیر بہت آسانی سے پلٹ جائے → حد (تھریشولڈ) بڑھائیں۔
  • اگر تیر تبدیل ہونے میں بہت سست ہو → حد (تھریشولڈ) کم کریں۔

تیر کے نمونے

اس خاکے میں تیروں کے بٹ میپ نمونے شامل ہیں:

  • ↑ اوپر
  • ↓ نیچے
  • ← بائیں
  • → دائیں

آپ کو ان میں تبدیلی کرنے کی ضرورت نہیں ہے، لیکن اگر آپ مختلف انداز چاہتے ہیں تو آپ کوڈ کے اندر شکلیں تبدیل کر سکتے ہیں۔

خلاصہ

پروجیکٹ 5 ظاہر کرتا ہے کہ ESP32-S3 RGB LED میٹرکس اور QMI8658C ایکسلرومیٹر مل کر کیسے کام کرتے ہیں تاکہ سمت کا پتہ لگا سکیں اور ایک تیر دکھا سکیں جو ہمیشہ اوپر کی طرف اشارہ کرتا ہے۔ یہ پروجیکٹ ٹِلٹ ڈاٹ (پروجیکٹ 4) پر مبنی ہے اور آپ کو پروجیکٹ 6 کے آخری انٹرایکٹو گیم کے لیے تیار کرتا ہے۔

مکمل “تیر ہمیشہ اوپر” خاکہ اس مضمون کے نیچے دستیاب ہے (خودکار طور پر لوڈ ہوتا ہے)۔ ویڈیو کا متعلقہ حصہ دیکھنے کی سختی سے سفارش کی جاتی ہے تاکہ یہ دیکھا جا سکے کہ تیر بورڈ کی گردش پر کتنی فوری ردعمل دیتا ہے۔ اگر آپ یہ پروجیکٹ گھر پر بنانا چاہتے ہیں تو 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 attached with buzzer to pin6 and GND
ESP32 S3 Matrix attached with buzzer to pin6 and GND
ESP32 S3 Matrix displaying red heart
ESP32 S3 Matrix displaying red heart
ESP32 S3 Matrix displaying green heart
ESP32 S3 Matrix displaying green heart
ESP32 S3 Matrix displaying rainbow heart 3
ESP32 S3 Matrix displaying rainbow heart 3
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3-Mtrix - Alway Up
ESP32-S3-Mtrix - Alway Up
803-ESP32-S3 RGB LED Matrix Project 5 - Arrow always up
زبان: C++
/* 
  Project 5: Arrow Always Up – 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/RJT833

  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  -> arrow points to opposite side
//         USB↔OUSB, 34↔15
// false -> arrow points to the same side that is UP
bool useOppositeMapping = false;

// Arrow color (0–255 each)
uint8_t dotRed   = 0;
uint8_t dotGreen = 150;
uint8_t dotBlue  = 0;

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

// Direction for arrow drawing
enum ArrowDir {
  ARROW_CENTER,
  ARROW_UP,
  ARROW_DOWN,
  ARROW_LEFT,
  ARROW_RIGHT
};

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

// -------- ARROW DRAWING (YOUR CODE, UNCHANGED) --------

// Draw a simple arrow on 8x8 matrix pointing in the given direction
void drawArrow(ArrowDir dir, uint16_t color) {
  matrix.fillScreen(0);

  switch (dir) {
    case ARROW_UP:
      // Tip
      matrix.drawPixel(3, 0, color);
      matrix.drawPixel(4, 0, color);
      // Second row
      matrix.drawPixel(2, 1, color);
      matrix.drawPixel(3, 1, color);
      matrix.drawPixel(4, 1, color);
      matrix.drawPixel(5, 1, color);
      // Shaft
      matrix.drawLine(3, 2, 3, 6, color);
      matrix.drawLine(4, 2, 4, 6, color);
      break;

    case ARROW_DOWN:
      // Tip
      matrix.drawPixel(3, 7, color);
      matrix.drawPixel(4, 7, color);
      // Row above tip
      matrix.drawPixel(2, 6, color);
      matrix.drawPixel(3, 6, color);
      matrix.drawPixel(4, 6, color);
      matrix.drawPixel(5, 6, color);
      // Shaft
      matrix.drawLine(3, 1, 3, 5, color);
      matrix.drawLine(4, 1, 4, 5, color);
      break;

    case ARROW_LEFT:
      // Tip
      matrix.drawPixel(0, 3, color);
      matrix.drawPixel(0, 4, color);
      // Column after tip
      matrix.drawPixel(1, 2, color);
      matrix.drawPixel(1, 3, color);
      matrix.drawPixel(1, 4, color);
      matrix.drawPixel(1, 5, color);
      // Shaft
      matrix.drawLine(2, 3, 6, 3, color);
      matrix.drawLine(2, 4, 6, 4, color);
      break;

    case ARROW_RIGHT:
      // Tip
      matrix.drawPixel(7, 3, color);
      matrix.drawPixel(7, 4, color);
      // Column before tip
      matrix.drawPixel(6, 2, color);
      matrix.drawPixel(6, 3, color);
      matrix.drawPixel(6, 4, color);
      matrix.drawPixel(6, 5, color);
      // Shaft
      matrix.drawLine(1, 3, 5, 3, color);
      matrix.drawLine(1, 4, 5, 4, color);
      break;

    case ARROW_CENTER:
    default:
      // Simple plus in the center
      matrix.drawLine(3, 3, 4, 3, color);
      matrix.drawLine(3, 4, 4, 4, color);
      matrix.drawLine(3, 3, 3, 4, color);
      matrix.drawLine(4, 3, 4, 4, color);
      break;
  }

  matrix.show();
}

// -------- IMU → SIDE DETECTION --------
// We calibrated earlier:
//  +X = USB,   -X = OUSB
//  +Y = 15,    -Y = 34    (after your correction)

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;

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

  // Otherwise, use 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
    }
  }

  // Not clearly tilted → treat as center
  return SIDE_CENTER;
}

// Map from UP side to where the arrow should point
Side arrowSideFromUpSide(Side upSide) {
  if (!useOppositeMapping) {
    // Arrow shows the side that is UP
    return upSide;
  }

  // Arrow shows the opposite side
  switch (upSide) {
    case SIDE_USB:   return SIDE_OUSB;
    case SIDE_OUSB:  return SIDE_USB;
    case SIDE_15:    return SIDE_34;
    case SIDE_34:    return SIDE_15;
    case SIDE_CENTER:
    default:         return SIDE_CENTER;
  }
}

// Convert SIDE to ArrowDir
ArrowDir arrowDirFromSide(Side s) {
  switch (s) {
    case SIDE_USB:    return ARROW_UP;
    case SIDE_OUSB:   return ARROW_DOWN;
    case SIDE_15:     return ARROW_LEFT;
    case SIDE_34:     return ARROW_RIGHT;
    case SIDE_CENTER:
    default:          return ARROW_CENTER;
  }
}

// ---------------- SETUP & LOOP ----------------

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

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

  // IMU: SDA=11, SCL=12 on 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 arrowSide  = arrowSideFromUpSide(upSide);
  ArrowDir dir    = arrowDirFromSide(arrowSide);

  uint16_t color = matrix.Color(dotRed, dotGreen, dotBlue);
  drawArrow(dir, color);

  // 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(" | ARROW="); Serial.println(sideName(arrowSide));

  delay(80);
}

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

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

فائلیں📁

فریٹزنگ فائل