Cari Kode

Proyek Matriks LED RGB ESP32-S3 4 - Titik miring

Proyek Matriks LED RGB ESP32-S3 4 - Titik miring

Proyek 4 – Titik Miring (Gerakkan Titik dengan Memiringkan ESP32-S3 RGB LED Matrix)

Proyek 4 memperkenalkan sensor gerak yang tertanam di dalam modul ESP32-S3 RGB LED Matrix. Alih-alih menggerakkan titik secara otomatis (seperti Proyek 1) atau menggulir teks (Proyek 2 dan 3), proyek ini memungkinkan Anda mengontrol posisi titik hanya dengan memiringkan papan. Titik bergerak dengan mulus melintasi layar RGB 8×8 berdasarkan pembacaan langsung dari akselerometer QMI8658C di bagian belakang modul.

Keenam proyek dalam seri ini didemonstrasikan dalam satu video YouTube. Video yang sama disematkan di halaman ini, sehingga Anda dapat melihat dengan tepat bagaimana titik bergerak secara real time saat papan dimiringkan. Kode lengkap untuk proyek ini dimuat secara otomatis di bawah artikel, dan tautan pembelian afiliasi untuk modul muncul di bawah bagian kode.

Ikhtisar Modul ESP32-S3 RGB LED Matrix

Proyek ini menggunakan modul ESP32-S3 RGB LED Matrix, yang mencakup:

  • Mikrokontroler ESP32-S3 dengan Wi-Fi dan Bluetooth
  • Matriks LED RGB 8×8 (64 LED yang dapat dialamatkan secara individual)
  • Akselerometer QMI8658C di bagian belakang untuk deteksi kemiringan dan gerakan
  • Port USB untuk pemrograman dan daya
  • Tombol Boot / Reset
  • Pin GPIO yang dapat digunakan untuk ekspansi di masa mendatang

Sensor QMI8658C membaca nilai akselerasi dan orientasi X, Y, dan Z, memungkinkan titik bergerak ke atas/bawah/kiri/kanan berdasarkan cara papan dimiringkan.

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:41Proyek 4: Titik Miring (proyek ini)
  • 18:55 – Proyek 5: Panah ke Atas
  • 20:02 – Proyek 6: Permainan Target

Menonton demonstrasi kemiringan dalam video sangat disarankan, karena Anda dapat melihat bagaimana titik bereaksi dengan mulus terhadap orientasi papan.

Menginstal Papan ESP32 di Arduino IDE

Jika Anda telah menyelesaikan proyek sebelumnya, dukungan papan sudah terinstal. Jika tidak, ikuti langkah-langkah berikut:

  1. Buka File > Preferences → Tambahkan URL Papan ESP32.
  2. Buka Tools > Board > Boards Manager… dan instal ESP32.
  3. Pilih papan ESP32-S3 Anda di bawah Tools > Board.
  4. Pilih port COM yang benar di bawah Tools > Port.

Menginstal Pustaka yang Diperlukan

Proyek ini memerlukan pustaka berikut:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX Library
  • QMI8658 (sensor gerak)

Instal semuanya di Library Manager:

  1. Buka Sketch > Include Library > Manage Libraries….
  2. Cari Adafruit NeoMatrix → Instal.
  3. Izinkan instalasi otomatis Adafruit GFX dan Adafruit NeoPixel.
  4. Cari QMI8658 berdasarkan penulis yang terdaftar → Instal.

Cara Kerja Proyek 4

Sensor QMI8658C secara terus-menerus menyediakan data akselerasi di sepanjang sumbu X, Y, dan Z. Untuk proyek ini, kami hanya menggunakan sumbu X dan Y untuk menentukan:

  • Seberapa jauh titik bergerak ke kiri atau kanan (sumbu X)
  • Seberapa jauh titik bergerak ke atas atau bawah (sumbu Y)

Nilai sensor dipetakan ke rentang koordinat dari 0 hingga 7 (untuk matriks LED 8×8). Posisi titik diperbarui berkali-kali per detik, memberikan efek geser yang mulus saat Anda memiringkan modul.

Proyek 4 – Pengaturan Kode (Titik Miring)

Di bawah ini adalah pengaturan yang dapat diedit pengguna yang ditemukan di dekat bagian atas kode proyek. Sketsa lengkap muncul di bawah artikel secara otomatis.

Pin dan Ukuran Matriks


// Konfigurasi matriks RGB 8×8
const int MATRIX_PIN    = 14;   // pin tetap untuk papan ini
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

Biarkan MATRIX_PIN pada 14. Pin ini terhubung langsung ke matriks di papan.

Kecerahan


// Kecerahan keseluruhan (0–255)
uint8_t matrixBrightness = 40;

Tingkatkan jika perlu, tetapi hindari kecerahan ekstrem saat melihat dari dekat.

Warna Titik


// Warna titik (R, G, B)
uint8_t dotRed   = 0;
uint8_t dotGreen = 200;   // hijau muda (default)
uint8_t dotBlue  = 0;

Ubah nilai-nilai ini untuk membuat warna apa pun. Contoh:

  • Merah: (255, 0, 0)
  • Kuning: (255, 255, 0)
  • Putih: (255, 255, 255)

Sensitivitas Gerakan

Untuk mencegah lompatan ekstrem, nilai akselerometer biasanya dibatasi atau diskalakan. Pengaturan umum terlihat seperti:


// Seberapa agresif kemiringan memengaruhi gerakan
float sensitivity = 4.0f;   // lebih besar = gerakan lebih cepat di layar

Jika titik bergerak terlalu lambat → tingkatkan nilainya. Jika titik bergerak terlalu mendadak → kurangi nilainya.

Kecepatan Pembaruan (Laju Penyegaran)

Anda dapat menambahkan penundaan kecil antara pembaruan untuk memperhalus gerakan:


// Penundaan antara pembaruan posisi (ms)
int refreshDelayMs = 20;   // lebih rendah = respons lebih halus dan cepat

Nilai antara 10–30 ms terasa sangat responsif.

Ringkasan

Proyek 4 menghidupkan akselerometer QMI8658C bawaan ESP32-S3 dengan memungkinkan Anda mengontrol matriks LED melalui gerakan fisik. Kemiringan kecil pada papan menggerakkan titik ke arah yang sama, menjadikan proyek ini batu loncatan sempurna untuk proyek “Arrow Up” dan “Target Game” yang lebih canggih.

Sketsa Tilt Dot lengkap dimuat di bawah artikel ini (secara otomatis). Untuk pemahaman terbaik, tonton demonstrasi kemiringan dalam video, di mana Anda dapat melihat seberapa halus titik bergerak saat papan diputar. Tautan untuk membeli modul ESP32-S3 RGB LED Matrix disertakan 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 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
Bahasa: 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);
}



Hal-hal yang mungkin Anda butuhkan

Sumber daya & referensi

Berkas📁

File Fritzing