شِفر (کود) جستجو

پروژه ماتریس LED RGB ESP32-S3 ۵ - پیکان همیشه به سمت بالا

پروژه ماتریس LED RGB ESP32-S3 ۵ - پیکان همیشه به سمت بالا

پروژه ۵ - پیکان همیشه به بالا (شاخص جهت‌یابی با استفاده از QMI8658C)

پروژه ۵ از حساس(حس کننده) حرکتی QMI8658C برای تشخیص جهت ماتریس LED RGB ESP32-S3 استفاده می‌کند و همیشه یک پیکان را به سمت بالا نسبت به جاذبه نمایش می‌دهد. فرقی نمی‌کند که برد را چگونه بچرخانید - سمت USB بالا، سمت OUSB بالا، سمت "۱۵" یا سمت "۳۴" - پیکان به طور خودکار می‌چرخد و به سمت بالا به‌صورت فیزیکی اشاره می‌کند.

این یک نمایش قدرتمند از حساس(حس کننده) انحراف در زمان واقعی با استفاده از شتاب‌سنج داخلی است. تمام شش پروژه این ماجیول در یک ویدئوی یوتیوب نمایش داده شده است که همچنین در این صفحه تعبیه شده است. شِفر (کود) کامل پروژه 5 به طور خودکار در زیر مقاله بارگذاری می‌شود و واصل‌های وابسته در زیر بخش شِفر (کود) ظاهر می‌شوند.

مرور کلی ماجیول ماتریس LED RGB ESP32-S3

ماجیول مصفوفه LED RGB ESP32-S3 شامل چندین مؤلفه است که این پروژه را امکان‌پذیر می‌سازد:

  • میکروکنترلر ESP32-S3- وای‌فای، BLE را فراهم می‌کند و منطق LED/IMU را اجرا می‌کند.
  • ماتریس LED RGB 8×8- نشانه را در هر یک از چهار جهت نشان می‌دهد.
  • شتاب‌سنج QMI8658C- تغییر زاویه، حرکت و جهت را تشخیص می‌دهد.:contentReference[oaicite:0]{index=0}
  • پورت USB-Cبرای قدرت و برنامه‌نویسی در IDE آردوینو.
  • کلیدهای بازنشانی و راه‌اندازیبرای بارگذاری طرح‌ها.
  • پایه‌های GPIOدسترس‌پذیر در کل هیئت برای پروژه‌های اضافی.

جهت فلش به طور کامل توسط خوانش‌های شتاب‌سنج تعیین می‌شود. زمانی که تخته چرخانده می‌شود، QMI8658C مقادیر جدید X/Y/Z را حس می‌کند و طرح انتخاب می‌کند که کدام الگوی فلش (↑، ↓، ←، →) باید رسم شود.

پروژه‌های پوشش داده‌شده در ویدیو (زمان‌های مرتبط)

  • ۰۰:۰۰- مقدمه
  • ۲:۰۱- نصب بردهای ESP32
  • 03:32- نصب کتابخانه‌ها
  • ۰۵:۳۲- پروژه ۱: نقطه متحرک
  • ۱۱:۱۱- پروژه ۲: اسکرول متن
  • ۱۲:۵۹- پروژه ۳: متن HTTP
  • 16:41- پروژه ۴: نقطه کج
  • ۱۸:۵۵-پروژه ۵: فلش همیشه به بالا (این پروژه)
  • ۲۰:۰۲- پروژه ۶: بازی هدف

ویدیو به وضوح نشان می‌دهد که چگونه پیکان به طور آنی بر اساس اینکه ماجیول چگونه چرخیده است، جهت خود را تغییر می‌دهد. تماشای این بخش به شدت توصیه می‌شود.:contentReference[oaicite:1]{index=1}

نصب بوردهای ESP32 در Arduino IDE

اگر پروژه قبلی را تمام کرده‌اید، تنظیمات تابلو قبلاً انجام شده است. در غیر این صورت:

  1. File > Preferences→ آدرس بورد ESP32 را اضافه کنید
  2. Tools > Board > Boards Manager…→ نصب "ESP32"
  3. برد ESP32-S3 را انتخاب کنید تحتTools > Board
  4. پورت COM USB صحیح را انتخاب کنید تحتTools > Port

نصب کتابخانه‌های مورد نیاز

پروژه ۵ استفاده می‌کند:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658حساس(حس کننده) حرکتی
  1. Sketch > Include Library > Manage Libraries…
  2. جستجو:نئو ماتریکس→ نصب
  3. نصب وابستگی‌ها:نیوپیکسل+GFX
  4. جستجو و نصبQMI8658توسط نویسنده آن

چگونه پروژه 5 کار می‌کند

QMI8658C نیروی گرانش را در محورهای X، Y و Z اندازه‌گیری می‌کند. با مقایسه این مقادیر، طرح می‌تواند تعیین کند که کدام سمت فیزیکی برد رو به بالا است:

  • USB به سمت بالا
  • سمت OUSB رو به بالا(معکوس USB)
  • سمت "۱۵" به بالا
  • طرف "۳۴" بالا

هر جهت به یک الگوی تیرک مختلف در ماتریس ۸×۸ مربوط می‌شود. نگاشت طبق منطق جهت‌گیری تأیید شده شما از جلسات عیب‌یابی قبلی دنبال می‌شود. چرخش تخته به طور پیوسته خوانده می‌شود و تیرک به محض تغییر طرف بالا به‌روزرسانی می‌شود.

پروژه ۵ - تنظیمات شِفر (کود) (فلش همیشه رو به بالا)

در زیر مقادیر قابل تنظیم کاربر از بخش پیکربندی آمده است. شِفر (کود) کامل پروژه به صورت خودکار زیر مقاله ظاهر می‌شود.

تنظیمات ماتریس


// Matrix configuration
const int MATRIX_PIN    = 14;   // fixed for this module
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

// Recommended orientation: Top-Left origin, progressive mode
// (actual constructor is inside the code loaded below)

این پروژه از استفاده می‌کندNEO_MATRIX_PROGRESSIVEطراحی برای اطمینان از اینکه فلش به درستی بر اساس حرکت واقعی اشاره می‌کند.

درخشندگی


uint8_t matrixBrightness = 40;   // 0–255

شما می‌توانید این مقدار را برای محیط‌های روشن‌تر افزایش دهید. برای استفاده در داخل، ۳۰-۶۰ راحت است.

رنگ فلش


// Arrow color
uint8_t arrowRed   = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue  = 0;

این مقادیر را تغییر دهید تا رنگ پیکان را تغییر دهید. به عنوان مثال:

  • فلش سبز:(0, 255, 0)
  • پیکان آبی:(0, 0, 255)
  • پیکان سفید:(255, 255, 255)

حساسیت و نرم‌کنندگی

برای جلوگیری از لرزش، شِفر (کود) شامل منطق هموارسازی و آستانه است. در تنظیمات ممکن است چیزی شبیه به این پیدا کنید:


// Sensitivity / smoothing adjustment
float tiltThreshold = 0.30f;   // adjust if arrow changes too easily
  • اگر تیر شما خیلی راحت بچرخد →افزایشآستانه.
  • اگر فلش слишком медленно сменится →کاهشآستانه.

الگوهای فلش

این طراحی شامل الگوهای تصویر پیکانی برای:

  • ↑ بالا
  • پائین
  • ← چپ
  • → راست

شما نیازی به تغییر این موارد ندارید، اما می‌توانید اشکال داخل شِفر (کود) را اگر سبک متفاوتی می‌خواهید تغییر دهید.

خلاصه

پروژه 5 نشان می‌دهد که چگونه ماتریس LED RGB ESP32-S3 و شتاب‌سنج QMI8658C با هم کار می‌کنند تا جهت‌گیری را شناسایی کرده و پیکانی را نمایش دهند که همیشه به سمت بالا اشاره می‌کند. این پروژه بر مبنای پروژه 4 با عنوان Tilt Dot ساخته شده و شما را برای بازی تعاملی نهایی در پروژه 6 آماده می‌کند.

پرتره کامل "Arrow Always Up" در زیر این مقاله (به‌طور خودکار بارگذاری می‌شود) موجود است. مشاهده قسمت مربوطه از ویدیو به شدت توصیه می‌شود تا ببینید چگونه فلش به‌طور آنی به چرخش تخته پاسخ می‌دهد. اگر می‌خواهید این پروژه را در خانه بسازید، واصل‌های وابسته برای ماجیول ماتریس LED RGB ESP32-S3 در زیر بخش شِفر (کود) ظاهر می‌شود.

تصاویر

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++
/*
 * پروژه ۵: فلش همیشه به بالا - ماتریس LED RGB ESP32-S3 (Waveshare)  
 * این طرح از QMI8658C IMU شیب را خوانده و یک نقطه را به صورت نرم و هماهنگ بر اساس جهت‌گیری برد روی ماتریس LED RGB ۸×۸ حرکت می‌دهد.  
 * 
 * ▶️ آموزش ویدئویی:  
 * https://youtu.be/JKLuYrRcLMI  
 * 
 * 📚⬇️ منابع و صفحه شِفر (کود):  
 * 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> // توسط لَهَاو گاهالی

 // -------- تنظیم ماتریس LED --------
#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
);

 // -------- تنظیم IMU QMI8658 --------
QMI8658 imu;
QMI8658_Data imuData;

 // -------- تنظیمات کاربر --------

 // واقعی -> فلش به طرف مقابل اشاره می‌کند
 // USB↔OUSB، ۳۴↔۱۵
 // نادرست -> پیکان به سمت همان طرفی که بالا است اشاره می‌کند
bool useOppositeMapping = false;

 // رنگ پیکان (۰-۲۵۵ هر کدام)
uint8_t dotRed   = 0;
uint8_t dotGreen = 150;
uint8_t dotBlue  = 0;

 // کناره‌های تخته
enum Side {
  SIDE_CENTER = 0,
  SIDE_USB,
  SIDE_OUSB,
  SIDE_15,
  SIDE_34
};

 // راهنمایی برای ترسیم فلش
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 "?";
  }
}

 // -------- کشیدن پیکان (شِفر (کود) شما، بدون تغییر) --------

 // در یک ماتریس ۸x۸ یک پیکان ساده رسم کنید که در جهت داده شده اشاره کند.
void drawArrow(ArrowDir dir, uint16_t color) {
  matrix.fillScreen(0);

  switch (dir) {
    case ARROW_UP:
 // نکته
      matrix.drawPixel(3, 0, color);
      matrix.drawPixel(4, 0, color);
 // ردیف دوم
      matrix.drawPixel(2, 1, color);
      matrix.drawPixel(3, 1, color);
      matrix.drawPixel(4, 1, color);
      matrix.drawPixel(5, 1, color);
 // میله
      matrix.drawLine(3, 2, 3, 6, color);
      matrix.drawLine(4, 2, 4, 6, color);
      break;

    case ARROW_DOWN:
 // نکته
      matrix.drawPixel(3, 7, color);
      matrix.drawPixel(4, 7, color);
 // رشد بالاتر از نوک
      matrix.drawPixel(2, 6, color);
      matrix.drawPixel(3, 6, color);
      matrix.drawPixel(4, 6, color);
      matrix.drawPixel(5, 6, color);
 // میله
      matrix.drawLine(3, 1, 3, 5, color);
      matrix.drawLine(4, 1, 4, 5, color);
      break;

    case ARROW_LEFT:
 // نکته
      matrix.drawPixel(0, 3, color);
      matrix.drawPixel(0, 4, color);
 // ستون بعد از انعام
      matrix.drawPixel(1, 2, color);
      matrix.drawPixel(1, 3, color);
      matrix.drawPixel(1, 4, color);
      matrix.drawPixel(1, 5, color);
 // میله
      matrix.drawLine(2, 3, 6, 3, color);
      matrix.drawLine(2, 4, 6, 4, color);
      break;

    case ARROW_RIGHT:
 // نکته
      matrix.drawPixel(7, 3, color);
      matrix.drawPixel(7, 4, color);
 // ستون قبل از انعام
      matrix.drawPixel(6, 2, color);
      matrix.drawPixel(6, 3, color);
      matrix.drawPixel(6, 4, color);
      matrix.drawPixel(6, 5, color);
 // میله
      matrix.drawLine(1, 3, 5, 3, color);
      matrix.drawLine(1, 4, 5, 4, color);
      break;

    case ARROW_CENTER:
    default:
 // ساده بعلاوه در مرکز
      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 → تشخیص سمت --------
 // ما قبلاً کالیبره کردیم:
 // +X = USB، -X = OUSB
 // +ی = ۱۵، -ی = ۳۴ (بعد از تصحیح شما)

Side detectSideUp(float ax_g, float ay_g, float az_g) {
 // تشخیص مسطح
  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;

 // آستانه‌ها برای گفتن "این محور واقعاً کج است"
  const float tiltThreshY = 0.5f;
  const float tiltThreshX = 0.5f;

 // محور Y را برای ۱۵ / ۳۴ ترجیح دهید
  if (fabs(ay_g) >= tiltThreshY) {
    if (ay_g > 0) {
      return SIDE_34; // +Y = ۳۴ بالا
    } else {
      return SIDE_15; // -Y = ۱۵ بالا
    }
  }

 // در غیر این صورت، از محور X برای USB / OUSB استفاده کنید.
  if (fabs(ax_g) >= tiltThreshX) {
    if (ax_g > 0) {
      return SIDE_USB; // +X = USB بالا
    } else {
      return SIDE_OUSB; // -X = OUSB بالا
    }
  }

 // به وضوح کج نیست → به عنوان مرکز در نظر گرفته شود
  return SIDE_CENTER;
}

 // نقشه از طرف بالای UP به جایی که فلش باید اشاره کند
Side arrowSideFromUpSide(Side upSide) {
  if (!useOppositeMapping) {
 // فلش سمت بالا را نشان می‌دهد
    return upSide;
  }

 // فلش طرف مقابل را نشان می‌دهد
  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;
  }
}

 // SIDE را به 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;
  }
}

 // ---------------- راه‌اندازی و حلقه ----------------

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

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

 // IMU: SDA=11, SCL=12 روی 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);

 // اشکال‌زدایی
  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);
}

مواردی که ممکن است به آن‌ها نیاز داشته باشید

منابع و مراجع

فایل‌ها📁

فایل فریزینگ