見出し画像

ハンダ付けとか工作とかなしで自作トラッカーを作る【SlimeVR-Tracker(1つ)にたくさん(3つ以上)IMUをつける】


各センサーにバッテリー(MPU)つけると充電管理がめんどくさい・・・
1つのバッテリーで複数のセンサー動かしちゃおう

主に必要なものはスイッチサイエンスさんで購入できます。

I2C拡張ハブユニットの1Channelに2つ以上のIMUをつけたいときは下のものも

付属のケーブルが短いので別途購入する必要はあると思います

I2C拡張ハブユニットにが必要なわけ

I2Cは同じアドレスのデバイスを2つつなぐと正常に動作しません。
そのためデバイス自身がアドレスを変更する機能を持っていることが多いのです。IMU PROの場合だと0x68か0x69から選ぶことができるので2つならそのままI2Cに接続して同時に使うことが出来ますが3つ目は別系統のI2Cをつかうか拡張ハブユニットの出番になります。

このユニット自体が0x70のアドレスを持っていてこのアドレスにチャンネル番号を書き込めば最大で6チャンネルまで切り替えれます(チップは8chなので2chぶんもったいない気もするのですが・・・)。

// チャンネルを切り替えるコード
uint8_t ch = 0; // ここは 0ch ~ 5chまで使えます
Wire.beginTransmission(0x70);
Wire.write(1 << ch);
Wire.endTransmission();

正確にチャンネルを切り替えないと操作していI2Cデバイス以外にアクセスしてしまうのでSlimeVR-Trackerのコードを見てどの部分にチャンネル切り替えの処理をいれるかを考えます。
たとえばトラッカーでこれを間違えると右手を動かすと左手も一緒にうごいたら全身荒ぶったりするかもです。
話はそれましたが、これで6チャンネルにそれぞれ2つのIMUを接続できる準備が整いました。12箇所トラッキングできることになります。
胸、腰、右左上腕、前腕、膝、足、これで10箇所です。
もし12箇所で足りたいというのならば拡張ハブユニットを0x70以外で動かせば12個追加(計24個)できるかも(※通信関係や電力が足りるかとか未知数な部分はあるよ)

ファームウェアの変更ポイント

12個モードでやっていきます。

1.define.h のセンサーの設定

もともとの指定方法だとセンサ-2つを前提にしてるのでちょっとゴリ押し気味ですがセンサー種類とアドレスは直接指定しました。
ローテーションも直接指定するほうがいいけど、テストなのでデフォルトのままです。5つ目以降は接続してなくても動かせるようにoptionalをtrueに。

さてここで問題になるのはどのセンサーがどのチャンネルにあるかですね。
1チャンネルに2つと決めてた1つ目2つ目が0チャンネル、3つ目4つ目が1チャンネル以下略、、、、ですね。

#define MAX_IMU_COUNT 12

#define IMU_DESC_LIST \
        IMU_DESC_ENTRY(IMU_BMI270,  0x68,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, PRIMARY_IMU_OPTIONAL,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_BMI270,  0x69,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, PRIMARY_IMU_OPTIONAL,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_BMI270,  0x68,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, PRIMARY_IMU_OPTIONAL,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_BMI270,  0x69,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, PRIMARY_IMU_OPTIONAL,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_BNO085,  0x4A,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_UNKNOWN, 0x69,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_BNO085,  0x4A,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_UNKNOWN, 0x69,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_MPU6500, 0x68,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_MPU6500, 0x69,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_MPU6500, 0x68,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
        IMU_DESC_ENTRY(IMU_MPU6500, 0x69,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, true,   PIN_IMU_INT) \
#endif

2.SensorManager.cppの変更するところ

ソースを見ながら感じセンサーのセットアップx2とデーター取得の3箇所ですね。センサーモジュール毎にライブラリ化してくれてるのでとても扱いやすいです。

まずは【SensorManager::buildSensor】。これがセンサーのセットアップになります。

// swapI2C の次に追記しました。
I2CSCAN::clearBus(sdaPin, sclPin);
swapI2C(sclPin, sdaPin);

Wire.beginTransmission(0x70);
Wire.write(1 << (sensorID / 2));
Wire.endTransmission();

2箇所目は【SensorManager::postSetup】。ここにもswapI2Cがあります。追加するコードはほぼ同じです。

swapI2C(sensor->sclPin, sensor->sdaPin);

Wire.beginTransmission(0x70);
Wire.write(1 << (sensor->getSensorId() / 2));
Wire.endTransmission();

この2箇所でセンサーのセットアップ部分への対応はOKです。
次はデーターを取得する前にチャンネル変更の処理を追加します。

【SensorManager::update】へ追加するコードはpostSetupのコードと同じです。

swapI2C(sensor->sclPin, sensor->sdaPin);

Wire.beginTransmission(0x70);
Wire.write(1 << (sensor->getSensorId() / 2));
Wire.endTransmission();

チャンネルの決定方法は、センサーはセットアップ時にIDを割り当てられます。リストの1つ目から0,1,2,3,・・・・になってるので2で割ってあげるとチャンネル番号になります。0.5とか1.5とかはどうなるのって思うかもしれないけど整数にキャストされて小数部分は無視されるので問題ないです。

以上の部分を変更したファームウェアを書き込めば複数のセンサーを扱えるようになると思います。

所感

センサー自体やすいんだけど数が増えるとそこそこ負担がある。
BMI160をアリエクで買うのなら20個で3000円ちょっとなのでそっちのほうがお得かもです

どうやってセンサーを身につけるか。これはホント悩ましいホットリミットになるしかない。

追伸

もしファームウェアの変更部分、書き込み方わかんない、おすすめの魚卵、なんか要望あればぜひご連絡ください。

この記事が気に入ったらサポートをしてみませんか?