💫

LED Matrixで砂シミュレーション機をつくろう

2023/10/21に公開

以前、X(旧twitter)でみた砂シュミュレーション機に一目惚れしました。
@witnessmenowさんの公開されているFalling-Sand-Matrixを参考に、
自分でもLED Matrixと加速度センサーを使った砂シュミュレーション機を作りました。


https://twitter.com/tw_kotatu/status/1715605993433002379


参照プロジェクト

https://github.com/witnessmenow/Falling-Sand-Matrix

🔧パーツ一覧

機材名 備考
ESP32 DevKitC 秋月電子
ledマトリックスモジュールパネル屋内rgb 64 x 64ドット Amazonで購入, AliExpress等でも販売
3軸加速度センサー - MPU6050 Amazonで購入
モバイルバッテリ Amazonで購入(cheero Slim 10000mAh IoT機器対応 大容量 モバイルバッテリ)
ジャンパーケーブル 適量
木材・ネジ 適量 - 固定用

接続図

  • LEDマトリクスは、下記のコネクタがあります

ESP32とLEDマトリクス(入力コネクタ、出力コネクタ)

ESP32 LED Mat. IN LED Mat. OUT
- R1 R0
- G0 R1
- G1 G0
- B0 G1
- B1 B0
19 A -
23 B -
18 C -
5 D -
25 LAT -
16 OE -
14 CLK -
13 R0 -
GND GND -

電源周り

モバイルバッテリーからの5V/GNDをLEDマトリクスとESP32に接続します。

ESP32と加速度センサー

ESP32 MPU6050
3V3 VCC
22 SCL
21 SDA
GND GND

💻環境

Arduino IDEを使用します。

  • Arduino IDE
    • Version:2.1.1

ライブラリ

LEDマトリクスのライブラリは、下記となります。

https://github.com/2dom/PxMatrix

また、動作確認した際の各ライブラリのバージョンは以下となります。

Library Version Note
PxMatrix LED MATRIX library 1.8.2 上記のライブラリ
Adafruit BusIO 1.14.3 -
Adafruit GFX Library 1.11.7 -
Arduino-MPU6050 patch-1 witnessmenow/Arduino-MPU6050
修正は後述

📝作業ログ

いくつかハマったので、作業内容を時系列で記載します。

ピン番号の変更

  • fallingSand/fallingSand.inoを上記の接続に修正します
  • ピン番号をこの基板用に変更します
    • failingSand.ino
      #define P_LAT 25 // myboard
      // #define P_LAT 22  //original
      #define P_A 19
      #define P_B 23
      #define P_C 18
      #define P_D 5
      #define P_E 15
      #define P_OE 16 // 2
      
  • また、I2Cのピン設定も接続図に合わせます
    • failingSand.ino
      while (!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_4G, MPU6050_ADDRESS, 21, 22))    //myboard
      // while (!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_4G, MPU6050_ADDRESS, 27, 33)) //original
      

動作確認1 - I2C周りの修正

  • 修正自体は、上記で終わりのため、動作を確認しました。
  • 電源を入れたところ、LEDが光りません。
  • print文で追ったところ、上記のMPU6050初期化のmpu.begin()の処理が抜けないことがわかりました
  • 追うと、I2Cのread処理にて停止していることがわかりました
    • STOP Conditionが発行されていない???
  • Wireライブラリのサンプルコードをもとに修正しました
    • 修正前
    Arduino-MPU6050/MPU6050.cpp(before)
    // Read 8-bit from register
    uint8_t MPU6050::readRegister8(uint8_t reg)
    {
        uint8_t value;
    
        Wire.beginTransmission(mpuAddress);
        Wire.write(reg);
        Wire.endTransmission();
    
        Wire.beginTransmission(mpuAddress);
        Wire.requestFrom(mpuAddress, 1);
        while (!Wire.available())
        {
        };
        value = Wire.read();
        Wire.endTransmission();
    
        return value;
    }
    
    • 修正後
    Arduino-MPU6050/MPU6050.cpp(after)
    // Read 8-bit from register
    uint8_t MPU6050::readRegister8(uint8_t reg)
    {
        uint8_t value;
    
        Wire.beginTransmission(mpuAddress);
        Wire.write(reg);
        Wire.endTransmission();
    
        Wire.beginTransmission(mpuAddress);
        Wire.endTransmission(true);
        uint8_t bytesReceived = Wire.requestFrom(mpuAddress, 1);
        if( bytesReceived )
        {
            Wire.readBytes(&value, bytesReceived);
        }
        Wire.endTransmission();
    
        return value;
    }
    
    • 同じ処理が MPU6050::fastRegister8(uint8_t reg)にもあるため、同じように修正しました
  • 上記の修正に伴い、MPU6050.cpp/hをローカルに移動し、各インクルード文を修正します
    MPU6050.cpp/fallingSandRep.ino
    // #include <MPU6050.h>
    #include "MPU6050.h"
    

動作確認2-加速度センサー軸の修正

  • 上記の修正を行い、再度動作を確認しました
  • 無事にLEDが点灯しましたが、傾けた方向と逆に砂が転がります
  • 加速度センサーの取り付け方にて、転がる向きが変わってしまうため、下記のコードを追加しました
    fallingSandRep.ino
    ImgBufferGFX imgWrapper(img, WIDTH, HEIGHT);
    
    #define MPU6050_CHANGE_X_Y      1 //add - X/Y軸の入れ替え
    #define MPU6050_CHANGE_SIGN_X   1 //add - X方向の反転
    #define MPU6050_CHANGE_SIGN_Y   0 //add - Y方向の反転
    
    float xOffset = -1350; 
    float yOffset = -2590;void pixelTask(void *param) {#if MPU6050_CHANGE_SIGN_X
      float xOffset = (accelVector.XAxis) * -1;
      #else
      float xOffset = (accelVector.XAxis * -1) * -1;
      #endif
      #if MPU6050_CHANGE_SIGN_Y
      float yOffset = (accelVector.YAxis) * -1;
      #else
      float yOffset = (accelVector.YAxis * -1) * -1;
      #endif
      #if MPU6050_CHANGE_X_Y
      float tmpOffset = xOffset;
      xOffset = yOffset;
      yOffset = tmpOffset;
      #endif
    
    
      while (true) {#if MPU6050_CHANGE_SIGN_X
    float accelX = (accelVector.XAxis) + xOffset;
    #else
    float accelX = (accelVector.XAxis * -1) + xOffset;
    #endif
    #if MPU6050_CHANGE_SIGN_Y
    float accelY = (accelVector.YAxis) + yOffset;
    #else
    float accelY = (accelVector.YAxis * -1) + yOffset;
    #endif
    float accelZ = accelVector.ZAxis;
    #if MPU6050_CHANGE_X_Y
    float accelTmp = accelX;
    accelX = accelY;
    accelY = accelTmp;
    #endif
    
  • 上記の場合、LEDパネルと加速度センサーの位置関係は以下となります
  • 最終的なファイル構成は、下記となります
    • ./fallingSandRep/
      • fallingSandRep.ino
      • imgBufferGFX.h
      • MPU6050.cpp
      • MPU6050.h

以上で、うまく動作することができました🎉。

📄メモ

  • 当たり判定や表示の仕組みは、コメントに詳しく記載されています
  • 気になったことを列挙します

64x32に変更する場合

  • 64x32のLEDパネルにする場合、下記の修正が必要です
  • 該当箇所は、以下です
    • 表示サイズの定義
      fallingSand.ino
      // 64x64
      #define WIDTH 64      // Display width in pixels
      #define HEIGHT 64     // Display height in pixels
      
      // 64x32
      #define WIDTH 64      // Display width in pixels
      #define HEIGHT 32     // Display height in pixels
      
    • PxMATRIXの初期化
      fallingSand.ino
      // 64x64
      PxMATRIX display(64, 64, P_LAT, P_OE, P_A, P_B, P_C, P_D, P_E);
      
      // 64x32
      PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D);
      
    • 行指定
      fallingSand.ino
      // 64x64
      display.begin(32);
      
      // 64x32
      display.begin(16);
      

RGBの順番変更

  • メーカによってRGBの順番が異なるようです
  • 下記にて変更できます
    fallingSand.ino
    // RGB
    display.setColorOrder(RRGGBB);
    
    // GBR
    display.setColorOrder(GGBBRR);
    

mapと当たり判定

  • img[]がmapとなっている
    • uint16_t img[WIDTH * HEIGHT]; // Internal 'map' of pixels
    • 本配列が衝突の判定のmapとなっている
    • imgWrapper経由で描画した文字列を描画した場合、その部分は壁になる
      • 壁 : imgWrapper.print("HI");
      • 表示 : display.print("HI");
    • 例:HIを描画した場合の動作
      • 動画を取る

さいごに

久しぶりに電子工作をして楽しかったです。
目に見えるものは、わかりやすくていいですね。

GitHubで編集を提案

Discussion