検索コード

ESP32-S3 RGB LEDマトリックスプロジェクト5 - 矢印は常に上向き

ESP32-S3 RGB LEDマトリックスプロジェクト5 - 矢印は常に上向き

プロジェクト5 - 矢印は常に上(QMI8658Cを使用した方向指示器)

プロジェクト5では、QMI8658Cモーションセンサーを使用してESP32-S3 RGB LEDマトリックスの向きを検出し、常に重力に対して上向きの矢印を表示します。ボードをどのように回転させても - USB側が上、OUSB側が上、側面「15」、または側面「34」としても - 矢印は自動的に回転し、物理的な上向きの方向を指します。

これは、オンボードの加速度計を使用したリアルタイムの方向感知の強力なデモです。このモジュールのすべての6つのプロジェクトは、1つのYouTube動画で示されており、その動画はこのページにも埋め込まれています。プロジェクト5の完全なコードは記事の下に自動的に読み込まれ、コードセクションの下にはアフィリエイトリンクが表示されます。

ESP32-S3 RGB LEDマトリックスモジュールの概要

ESP32-S3 RGB LEDマトリックスモジュールには、このプロジェクトを可能にするいくつかのコンポーネントが含まれています:

  • ESP32-S3マイクロコントローラー- Wi-Fi、BLEを提供し、LED/IMUロジックを実行します。
  • 8×8 RGB LEDマトリックス- 矢印を4つの方向のいずれかで表示します。
  • QMI8658C加速度計傾き、動き、向きを検出します。:contentReference[oaicite:0]{index=0}
  • USB-CポートArduino IDEでのパワーとプログラミングのために。
  • リセットおよびブートボタンスケッチをアップロードするために。
  • GPIOピン追加プロジェクトのためにボード全体で利用可能です。

矢印の方向は完全に加速度計の読み取りによって決まります。ボードが回転すると、QMI8658Cは新しいX/Y/Zの値を検出し、スケッチはどの矢印のパターン(↑、↓、←、→)を描画するかを選択します。

動画で紹介されたプロジェクト(タイムスタンプ)

  • 00:00- はじめに
  • 02:01ESP32ボードのインストール
  • 03:32ライブラリをインストールしています
  • 05:32- プロジェクト 1: 動くドット
  • 11:11- プロジェクト2:テキストスクロール
  • 12:59プロジェクト3:HTTPテキスト
  • 16:41- プロジェクト4:ティルトドット
  • 18:55-プロジェクト5:矢印は常に上向き(このプロジェクト)
  • 20:02- プロジェクト6:ターゲットゲーム

このビデオは、モジュールの向きに応じて矢印がどのように瞬時に方向を変えるかを明確に示しています。このセグメントを見ることは強く推奨されます。:contentReference[oaicite:1]{index=1}

Arduino IDEにESP32ボードをインストールする

以前のプロジェクトを完了していれば、ボードのセットアップはすでに完了しています。それ以外の場合:

  1. File > Preferences→ ESP32ボードのURLを追加する
  2. Tools > Board > Boards Manager…「ESP32」をインストールする
  3. ESP32-S3ボードを選択します。Tools > Board
  4. 正しいUSB COMポートを選択してください。Tools > Port

必要なライブラリのインストール

プロジェクト5の利用方法:

  • 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側を上にしてください(opposite USB)
  • 側面「15」を上に
  • 面 "34" 上

各方向は8×8のマトリックス上の異なる矢印パターンに対応しています。このマッピングは、以前のデバッグセッションで確認されたあなたの方向ロジックに従っています。ボードの回転は継続的に読み取られ、上向きの側が変わるとすぐに矢印が更新されます。

プロジェクト5 - コード設定 (矢印は常に上)

以下は、設定エリアからユーザーが調整可能な値です。記事の下にプロジェクトの完全なコードが自動的に表示されます。

マトリックス設定


// 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)

このプロジェクトは使用しますネオマトリックスプログレッシブ実際の動きに基づいて矢印が正しく指すようにレイアウトします。

明るさ


uint8_t matrixBrightness = 40;   // 0–255

明るい環境ではこの値を上げることができます。屋内での使用においては、30-60が快適です。

矢印の色


// 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では、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++
/*
 * プロジェクト5:矢印常に上 - ESP32-S3 RGB LEDマトリックス(Waveshare)  
 * このスケッチはQMI8658C IMUから傾きを読み取り、基板の向きに基づいて8×8 RGB LEDマトリックス上の点を滑らかに移動させます。
 * 
 * ▶️ ビデオチュートリアル:  
 * 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
);

 // -------- QMI8658 IMU セットアップ --------
QMI8658 imu;
QMI8658_Data imuData;

 // -------- ユーザー設定 --------

 // 真 -> 矢印は反対側を指す
 // USB↔OUSB、34↔15
 // 偽 -> 矢印は上向きの同じ側を指している
bool useOppositeMapping = false;

 // 矢印の色 (0-255 各)
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 "?";
  }
}

 // -------- 矢印描画 (あなたのコード、変更なし) --------

 // 与えられた方向を指す簡単な矢印を8x8のマトリックスに描いてください。
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
 // +Y = 15、-Y = 34(あなたの修正後)

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軸を15 / 34で優先してください。
  if (fabs(ay_g) >= tiltThreshY) {
    if (ay_g > 0) {
      return SIDE_34; // +Y = 34 上昇
    } else {
      return SIDE_15; // -Y = 15 上昇
    }
  }

 // それ以外の場合、USB / OUSBにはX軸を使用してください。
  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);
}

必要かもしれないもの

リソースと参考文献

ファイル📁

フリッツィングファイル