Tafuta Msimbo

Mchezo wa Cible wa Mradi wa Matrix ya LED ya RGB ya ESP32-S3 6

Mchezo wa Cible wa Mradi wa Matrix ya LED ya RGB ya ESP32-S3 6

Mradi wa 6 – Mchezo wa Lengo (Tega Ubao Ili Ugonge Mduara)

Mradi wa 6 ni wa mwisho na unaoingiliana zaidi katika mfululizo huu wa ESP32-S3 RGB LED Matrix. Kwa kutumia kihisi cha mwendo cha QMI8658C kilicho ndani, unatega ubao ili kusogeza nukta kwenye matrix ya 8×8. Eneo la “lengo la mduara” liko katikati ya skrini. Nukta yako inapogusa mduara, rangi hubadilika na (kwa hiari) buzzer inalia. Hii inaunda mchezo rahisi lakini wa kufurahisha wa usawa/uratibu.

Miradi yote sita inaonyeshwa kwenye video moja ya YouTube (iliyopachikwa kwenye ukurasa huu). Msimbo kamili wa mchezo umepakiwa kiotomatiki chini ya makala hii, na viungo vya ununuzi vya moduli vinaonekana chini ya sehemu ya msimbo.

Muhtasari wa Moduli ya ESP32-S3 RGB LED Matrix

Moduli hii inajumuisha:

  • Kidhibiti cha ESP32-S3 (Wi-Fi + BLE)
  • Matrix ya RGB LED 8×8 (LED 64 zinazoweza kushughulikiwa)
  • Kipima kasi cha QMI8658C cha kuhisi mwelekeo na utegaji
  • Bandari ya USB-C kwa nishati na upangaji
  • Vifungo vya Boot / Reset
  • Pini za GPIO zinazopatikana kwa viongezi kama buzzer au vihisi

Kwa mchezo huu, kipima kasi ni muhimu—kinaripoti utegaji wa X/Y kila wakati, ikiruhusu nukta kusogea vizuri kulingana na pembe ya ubao. Sehemu ya video ya mradi huu inaonyesha wazi jinsi nukta inavyoteleza na kuitikia unapotega moduli kushoto/kulia/mbele/nyuma.

Miradi Iliyoshughulikiwa kwenye Video (Nyakati)

  • 00:00 – Utangulizi
  • 02:01 – Kusakinisha bodi za ESP32
  • 03:32 – Kusakinisha maktaba
  • 05:32 – Mradi wa 1: Nukta Inayosogea
  • 11:11 – Mradi wa 2: Utelezaji wa Maandishi
  • 12:59 – Mradi wa 3: Maandishi ya HTTP
  • 16:41 – Mradi wa 4: Nukta ya Kutega
  • 18:55 – Mradi wa 5: Mshale Juu
  • 20:02Mradi wa 6: Mchezo wa Lengo (mradi huu)

Sehemu hii ya video inaonyesha mwendo wa nukta na mantiki ya kutambua mduara ikifanya kazi, ikifanya iwe rahisi kuelewa jinsi viwianishi vinavyofanya kazi.

Kusakinisha Bodi za ESP32 kwenye Arduino IDE

Ikiwa tayari umekamilisha miradi ya awali, usakinishaji wa bodi umekamilika. Vinginevyo fuata:

  1. File > Preferences → Ongeza URL ya bodi ya ESP32.
  2. Tools > Board > Boards Manager… → Sakinisha “ESP32”.
  3. Chagua bodi ya ESP32-S3 chini ya Tools > Board.
  4. Chagua bandari sahihi ya COM chini ya Tools > Port.

Kusakinisha Maktaba Zinazohitajika

Mchezo huu unatumia:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (kihisi cha mwendo)

Sakinisha kupitia:

  1. Sketch > Include Library > Manage Libraries…
  2. Tafuta: NeoMatrix → Sakinisha
  3. Sakinisha vitegemezi (GFX + NeoPixel)
  4. Tafuta na usakinishe QMI8658

Jinsi Mchezo wa Lengo Unavyofanya Kazi

Kipima kasi cha QMI8658C kinatoa thamani za utegaji wa X na Y. Hizi zinahusishwa na viwianishi vya LED (0–7 katika pande zote mbili). Nukta yako inasogea kwenye matrix kulingana na pembe ya ubao.

Mduara (au pete) huchorwa kwenye skrini kama “eneo la lengo.” Unapata “kugonga” wakati wowote nukta inapoingiliana na mduara. Wakati huo:

  • Rangi ya lengo hubadilika (nasibu au iliyopangwa)
  • Buzzer ya hiari inalia (ikiwa imeunganishwa)

Kwa kuwa matrix ni ndogo, mduara huchorwa kwa kutumia ukaguzi rahisi wa radius. Mchezo unaendelea kila wakati, kwa hivyo unaweza kutega huku na huku kugonga mduara mara kwa mara.

Mradi wa 6 – Mipangilio ya Msimbo (Mchezo wa Lengo)

Hapo chini ni mipangilio kuu inayoweza kubadilishwa na mtumiaji iliyo juu ya sketch. Msimbo kamili umejumuishwa kiotomatiki chini ya makala hii.

Usanidi wa Matrix


// Usanidi wa matrix
const int MATRIX_PIN    = 14;
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

Matrix ya RGB imeunganishwa kwa GPIO 14—usibadilishe hii.

Mwangaza


uint8_t matrixBrightness = 40;   // 0–255

Kwa matumizi ya ndani, 30–60 ni bora.

Rangi ya Nukta


// Rangi ya nukta (R, G, B)
uint8_t dotRed   = 255;
uint8_t dotGreen = 255;
uint8_t dotBlue  = 255;

Hii ni nukta unayoisogeza kwa kutega ubao.

Rangi ya Mduara (Nasibu au Iliyowekwa)


// Rangi ya mduara (lengo)
uint8_t circleRed   = 0;
uint8_t circleGreen = 0;
uint8_t circleBlue  = 255;

// Ikiwa ni kweli, chagua rangi mpya nasibu kila wakati nukta inapogonga
bool randomCircleColor = true;

Weka randomCircleColor = false; ikiwa unataka rangi isiyobadilika.

Radius ya Mduara


// Ukubwa wa lengo (radius)
int targetRadius = 3;   // 3 inafaa vizuri kwenye matrix ya 8×8

Radiasi kubwa hufanya mchezo kuwa rahisi; ndogo hufanya kuwa mgumu.

Usikivu wa Kutega


// Usikivu wa ramani ya kutega
float tiltScale = 4.0f;   // ongeza = mwendo wa haraka kwenye skrini

Ikiwa nukta inasogea haraka sana au inaruka, punguza nambari hii.

Mipangilio ya Buzzer (Hiari)


// Pini ya buzzer (si lazima)
int buzzerPin = 6;      // unganisha buzzer + kwa pin 6, – kwa GND
bool useBuzzer = true;  // weka false ili uzime sauti

Ikiwa haujaunganisha buzzer, weka tu useBuzzer = false;

Muhtasari

Mradi wa 6 unachanganya kila kitu kilichojifunza kutoka miradi ya awali: kuchora kwenye matrix, kuingiza data kutoka accelerometer, udhibiti wa rangi, laini ya harakati, na sauti ya hiari. Kuinamisha bodi husogeza nukta, na kugonga duara hubadilisha rangi yake na (kwa hiari) husababisha mlio. Ni onyesho la kufurahisha la kuhisi mwendo kwenye skrini ya RGB iliyoshikana.

Msimbo kamili wa “Mchezo wa Lengo” unaonyeshwa kiotomatiki chini ya makala hii. Unaweza pia kutazama sehemu ya Mradi wa 6 ya video ili kuona jinsi nukta inavyosogea na jinsi miguso inavyotambuliwa. Ikiwa ungependa kujenga mchezo wako mwenyewe, viungo vya ushirika vya kununua moduli ya ESP32-S3 RGB LED Matrix vinaonekana chini ya sehemu ya msimbo.

Bilder

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 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
804-ESP32-S3 RGB LED Matrix Project 6 - Cible game
Språk: C++
/* 
  Project 6: Tilt Circle Game – 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

// Buzzer pin – change this to your actual buzzer GPIO.
const int BUZZER_PIN = 6;   // TODO: set to your buzzer pin

// Matrix brightness (0–255)
const uint8_t MATRIX_BRIGHTNESS = 10;

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
  MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
  NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
  NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
  NEO_GRB + NEO_KHZ800
);

// -------- IMU SETUP --------
QMI8658 imu;

// -------- GAME CONFIG --------

// How often the dot is allowed to move (ms).
// Bigger = slower movement.
const uint16_t MOVE_INTERVAL_MS = 150;   // try 120–250

// How much tilt (m/s^2) before the dot moves.
// Increase if it feels too sensitive.
const float ACC_TILT_THRESHOLD = 2.0f;   // about ~0.2 g

// Dot base color (RGB)
const uint8_t DOT_R = 255;
const uint8_t DOT_G = 255;
const uint8_t DOT_B = 255;


// Circle geometry (centered on 8x8)
const float CIRCLE_CENTER_X = (MATRIX_WIDTH - 1) / 2.0f;   // 3.5
const float CIRCLE_CENTER_Y = (MATRIX_HEIGHT - 1) / 2.0f;  // 3.5
const float CIRCLE_RADIUS   = 3.0f;
const float CIRCLE_THICKNESS = 0.8f; // +- thickness around radius

// -------- GAME STATE --------

// Dot position on the 8x8 grid (0..7)
int dotX = 3;
int dotY = 3;

// Colors (16-bit NeoMatrix colors)
uint16_t dotColor;
uint16_t circleColor;

// To detect “just touched circle” vs “still on circle”
bool wasOnCircle = false;

// Timer for rate-limiting movement
unsigned long lastMoveTime = 0;

// -------- HELPER FUNCTIONS --------

// Classic NeoPixel color wheel (0-255 -> rainbow)
uint16_t wheel(byte pos) {
  if (pos < 85) {
    return matrix.Color(pos * 3, 255 - pos * 3, 0);
  } else if (pos < 170) {
    pos -= 85;
    return matrix.Color(255 - pos * 3, 0, pos * 3);
  } else {
    pos -= 170;
    return matrix.Color(0, pos * 3, 255 - pos * 3);
  }
}

// Is a given pixel approximately on the circle?
bool isOnCircle(int x, int y) {
  float dx = x - CIRCLE_CENTER_X;
  float dy = y - CIRCLE_CENTER_Y;
  float d2 = dx * dx + dy * dy;

  float rMin = CIRCLE_RADIUS - CIRCLE_THICKNESS;
  float rMax = CIRCLE_RADIUS + CIRCLE_THICKNESS;

  return (d2 >= rMin * rMin) && (d2 <= rMax * rMax);
}

// Draw circle + dot
void drawScene() {
  matrix.fillScreen(0);

  // Draw circle
  for (int y = 0; y < MATRIX_HEIGHT; y++) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      if (isOnCircle(x, y)) {
        matrix.drawPixel(x, y, circleColor);
      }
    }
  }

  // Draw dot (on top)
  matrix.drawPixel(dotX, dotY, dotColor);

  matrix.show();
}

// Simple blocking beep (short)
void buzzOnce() {
  digitalWrite(BUZZER_PIN, HIGH);
  delay(40);
  digitalWrite(BUZZER_PIN, LOW);
}

// Use accelerometer to decide dot movement
void updateDotFromTilt(float ax, float ay) {
  unsigned long now = millis();
  if (now - lastMoveTime < MOVE_INTERVAL_MS) {
    return; // too soon, wait
  }

  int dx = 0;
  int dy = 0;

  // On this board, Y tilt feels like "left/right" on the matrix,
  // and X tilt feels like "up/down" → so we swap.

  // --- Horizontal movement from AY (tilt left/right) ---
  if (ay > ACC_TILT_THRESHOLD) {
    dx = 1;   // tilt to the right → move dot to the right
  } else if (ay < -ACC_TILT_THRESHOLD) {
    dx = -1;  // tilt to the left → move dot to the left
  }

  // --- Vertical movement from AX (tilt forward/back) ---
  // This was inverted. We flip the signs:
  // ax >  threshold  = tilt "forward" (away)  → move dot UP  (dy = -1)
  // ax < -threshold  = tilt "back"    (toward)→ move dot DOWN(dy =  1)
  if (ax > ACC_TILT_THRESHOLD) {
    dy = -1;  // was +1 before
  } else if (ax < -ACC_TILT_THRESHOLD) {
    dy = 1;   // was -1 before
  }

  if (dx != 0 || dy != 0) {
    dotX = constrain(dotX + dx, 0, MATRIX_WIDTH  - 1);
    dotY = constrain(dotY + dy, 0, MATRIX_HEIGHT - 1);
    lastMoveTime = now;
  }
}


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

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

  // Matrix init
  matrix.begin();
  matrix.setBrightness(MATRIX_BRIGHTNESS);
  matrix.fillScreen(0);
  matrix.show();

  // Buzzer init
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);

  // IMU init
if (!imu.begin(11, 12)) {
    Serial.println("Failed to initialize QMI8658!");
    while (1) {
      delay(100);
    }
  }

  // Use m/s^2 and dps (optional, but nice)
  imu.setAccelUnit_mps2(true);
  imu.setGyroUnit_dps(true);
  imu.setDisplayPrecision(3);

  Serial.println("QMI8658 initialized.");

  // Game initial state
  randomSeed((uint32_t)micros());

  dotX = MATRIX_WIDTH  / 2;
  dotY = MATRIX_HEIGHT / 2;

  dotColor    = matrix.Color(DOT_R, DOT_G, DOT_B);
  circleColor = wheel(random(256));

  drawScene();
}

void loop() {
  // Read accelerometer
  float ax, ay, az;
  if (imu.readAccelMPS2(ax, ay, az)) {
    // Debug if needed:
    // Serial.print("AX: "); Serial.print(ax);
    // Serial.print("  AY: "); Serial.print(ay);
    // Serial.print("  AZ: "); Serial.println(az);

    updateDotFromTilt(ax, ay);
  }

  // Check collision with circle
  bool onCircle = isOnCircle(dotX, dotY);
  if (onCircle && !wasOnCircle) {
    // Just touched circle: change color + beep
    circleColor = wheel(random(256));
    buzzOnce();
  }
  wasOnCircle = onCircle;

  // Redraw
  drawScene();

  // Small delay so we don’t hammer I2C too hard
  delay(10);
}

Tänker att du kanske behöver

Resurser och referenser

Filer📁

Fritzing-fil