Search Code

Proyek Matriks LED RGB ESP32-S3 5 - Panah selalu ke atas

Proyek Matriks LED RGB ESP32-S3 5 - Panah selalu ke atas

Proyek 5 – Panah Selalu Menunjuk ke Atas (Indikator Orientasi menggunakan QMI8658C)

Proyek 5 menggunakan sensor gerak QMI8658C untuk mendeteksi orientasi ESP32-S3 RGB LED Matrix dan selalu menampilkan panah yang menunjuk ke ATAS relatif terhadap gravitasi. Tidak peduli bagaimana Anda memutar papan—sisi USB di atas, sisi OUSB di atas, sisi “15”, atau sisi “34”—panah secara otomatis berputar dan menunjuk ke arah fisik yang mengarah ke atas.

Ini adalah demonstrasi yang kuat tentang penginderaan orientasi waktu nyata menggunakan akselerometer internal. Semua enam proyek untuk modul ini didemonstrasikan dalam satu video YouTube, yang juga disematkan di halaman ini. Kode lengkap untuk Proyek 5 dimuat secara otomatis di bawah artikel, dan tautan afiliasi muncul di bawah bagian kode.

Ikhtisar Modul ESP32-S3 RGB LED Matrix

Modul ESP32-S3 RGB LED Matrix mencakup beberapa komponen yang memungkinkan proyek ini berjalan:

  • Mikrokontroler ESP32-S3 — menyediakan Wi-Fi, BLE, dan menjalankan logika LED/IMU.
  • Matriks LED RGB 8×8 — menampilkan panah dalam empat orientasi.
  • Akselerometer QMI8658C — mendeteksi kemiringan, gerakan, dan orientasi.:contentReference[oaicite:0]{index=0}
  • Port USB-C untuk daya dan pemrograman di Arduino IDE.
  • Tombol Reset dan Boot untuk mengunggah sketsa.
  • Pin GPIO tersedia di sekitar papan untuk proyek tambahan.

Arah panah sepenuhnya ditentukan oleh pembacaan akselerometer. Saat papan diputar, QMI8658C merasakan nilai X/Y/Z baru, dan sketsa memilih pola panah mana (↑, ↓, ←, →) yang harus digambar.

Proyek yang Dicakup dalam Video (Stempel Waktu)

  • 00:00 – Pendahuluan
  • 02:01 – Menginstal papan ESP32
  • 03:32 – Menginstal pustaka
  • 05:32 – Proyek 1: Titik Bergerak
  • 11:11 – Proyek 2: Gulir Teks
  • 12:59 – Proyek 3: Teks HTTP
  • 16:41 – Proyek 4: Titik Miring
  • 18:55Proyek 5: Panah Selalu Menunjuk ke Atas (proyek ini)
  • 20:02 – Proyek 6: Permainan Target

Video dengan jelas menunjukkan bagaimana panah berubah arah secara instan berdasarkan cara modul diputar. Menonton segmen ini sangat disarankan.:contentReference[oaicite:1]{index=1}

Menginstal Papan ESP32 di Arduino IDE

Jika Anda telah menyelesaikan proyek sebelumnya, pengaturan papan sudah selesai. Jika tidak:

  1. File > Preferences → Tambahkan URL papan ESP32
  2. Tools > Board > Boards Manager… → Instal “ESP32”
  3. Pilih papan ESP32-S3 di bawah Tools > Board
  4. Pilih port USB COM yang benar di bawah Tools > Port

Menginstal Pustaka yang Diperlukan

Proyek 5 menggunakan:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (sensor gerak)
  1. Sketch > Include Library > Manage Libraries…
  2. Cari: NeoMatrix → Instal
  3. Instal dependensi: NeoPixel + GFX
  4. Cari dan instal QMI8658 oleh penulisnya

Cara Kerja Proyek 5

QMI8658C mengukur gravitasi pada sumbu X, Y, dan Z. Dengan membandingkan nilai-nilai ini, sketsa menentukan sisi fisik mana dari papan yang menghadap ke atas:

  • Sisi USB di atas
  • Sisi OUSB di atas (kebalikan dari USB)
  • Sisi “15” di atas
  • Sisi “34” di atas

Setiap orientasi sesuai dengan pola panah yang berbeda pada matriks 8×8. Pemetaan mengikuti logika orientasi yang Anda konfirmasi dari sesi debugging sebelumnya. Rotasi papan dibaca secara terus-menerus, dan panah diperbarui segera setelah sisi atas berubah.

Proyek 5 – Pengaturan Kode (Panah Selalu Menunjuk ke Atas)

Di bawah ini adalah nilai yang dapat disesuaikan pengguna dari area konfigurasi. Kode proyek lengkap muncul secara otomatis di bawah artikel.

Konfigurasi Matriks


// Konfigurasi matriks
const int MATRIX_PIN    = 14;   // tetap untuk modul ini
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

// Orientasi yang disarankan: Asal Kiri-Atas, mode progresif
// (konstruktor sebenarnya ada di dalam kode yang dimuat di bawah)

Proyek ini menggunakan tata letak NEO_MATRIX_PROGRESSIVE untuk memastikan panah menunjuk dengan benar berdasarkan gerakan sebenarnya.

Kecerahan


uint8_t matrixBrightness = 40;   // 0–255

Anda dapat menaikkan nilai ini untuk lingkungan yang lebih terang. Untuk penggunaan di dalam ruangan, 30–60 sudah nyaman.

Warna Panah


// Warna panah
uint8_t arrowRed   = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue  = 0;

Ubah nilai-nilai ini untuk memodifikasi warna panah. Misalnya:

  • Panah hijau: (0, 255, 0)
  • Panah biru: (0, 0, 255)
  • Panah putih: (255, 255, 255)

Sensitivitas dan Penghalusan

Untuk menghindari getaran, kode menyertakan logika penghalusan dan ambang batas. Dalam pengaturan, Anda mungkin menemukan sesuatu seperti:


// Penyesuaian sensitivitas / penghalusan
float tiltThreshold = 0.30f;   // sesuaikan jika panah berubah terlalu mudah
  • Jika panah Anda terlalu mudah berbalik → naikkan ambang batas.
  • Jika panah terlalu lambat berubah → turunkan ambang batas.

Pola Panah

Sketsa ini menyertakan pola bitmap panah untuk:

  • ↑ atas
  • ↓ bawah
  • ← kiri
  • → kanan

Anda tidak perlu mengubah ini, tetapi Anda dapat mengubah bentuk di dalam kode jika ingin gaya yang berbeda.

Ringkasan

Proyek 5 menunjukkan bagaimana ESP32-S3 RGB LED Matrix dan akselerometer QMI8658C bekerja sama untuk mendeteksi orientasi dan menampilkan panah yang selalu menunjuk ke atas. Proyek ini dibangun berdasarkan Tilt Dot (Proyek 4) dan mempersiapkan Anda untuk permainan interaktif terakhir di Proyek 6.

Sketsa lengkap “Arrow Always Up” tersedia di bawah artikel ini (dimuat otomatis). Menonton bagian video yang sesuai sangat disarankan untuk melihat seberapa cepat panah merespons rotasi papan. Jika Anda ingin membangun proyek ini di rumah, tautan afiliasi untuk modul ESP32-S3 RGB LED Matrix muncul di bawah bagian kode.

Gambar

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

Hal-hal yang mungkin Anda butuhkan

Sumber daya & referensi

Berkas📁

File Fritzing