Zenn
🦴

CXD5602PWBIMU Spresense用の高精度IMU

2025/03/03に公開

この記事は dev.to に投稿された記事の日本語訳となります

https://dev.to/goroman/cxd5602pwbimu-documentation-a-high-precision-imu-for-spresense-52om

CXD5602PWBIMU ドキュメント: Spresense用の高精度IMU

はじめに

CXD5602PWBIMUは、Spresenseボード用のイナーシャル測定ユニット(IMU)センサーです。このセンサーが特別なのは、16個のコンシューマーグレードIMUを搭載しており、それぞれに3軸加速度計と3軸ジャイロスコープがあり、センサーフュージョンを通じて高精度の動き検出と測定が可能になっている点です。さらに注目すべきは、2枚のボードを重ねて合計32個のIMUを実現することも可能です(ただし、価格は約9万円とより高価になります)。


この製品は日本国内市場向けです。輸出貿易管理規制(日本の輸出貿易管理令および外国為替令の第1-15項)の対象となります。この製品を輸出する場合や非居住者に提供する場合は、外国為替法に基づき適切な手続きを行う必要があります。

主な特徴

高精度

  • 低バイアス変動: バイアス安定性0.39度/時以下(16個のIMUを組み合わせた場合)
  • 低ノイズ密度: 1.0 mdps/√Hz以下。地球の回転検出によるジャイロコンパス機能も可能
  • デュアルボードスタッキングによるさらなる精度向上が可能
  • 事前校正済み

高い堅牢性

  • 複数のIMUによる冗長性で高い障害耐性
  • 多数決ロジックによるリアルタイムの外れ値除去

注: SPRESENSEメインボードは含まれていません。

ボードは信号処理用に2つのPSoC6チップを使用しているようです。

IMUの配置は以下のようになっています。

開発環境のセットアップ

  • Spresense開発環境(SDK)をインストール
  • ファームウェアv3.4.0が必要ですが、何らかの理由で公式サイトでまだ入手できません(この問題は解決する必要があります) v3.3.0で問題なく動作するようです
  • Arduinoでも動作するはずですが、執筆時点ではArduino用のサンプルコードは入手できませんでした

基本的な使用方法

デバイスパス

CXD5602PWBIMUセンサーは次のデバイスパスでアクセスできます:

/dev/imu0

APIリファレンス

IOCTLコマンド

コマンド 説明 パラメータ
SNIOC_SSAMPRATE サンプリングレートの設定 int型 (15, 30, 60, 120, 240, 480, 960, 1920)
SNIOC_SDRANGE ダイナミックレンジの設定 cxd5602pwbimu_range_t構造体
SNIOC_SFIFOTHRESH ハードウェアFIFOしきい値の設定 int型 (1-4)
SNIOC_ENABLE センサーの有効化/無効化 int型 (1=有効, 0=無効)

データ構造

// ダイナミックレンジ設定用の構造体
typedef struct {
  int accel;  // 加速度計の範囲 (2, 4, 8, 16)
  int gyro;   // ジャイロスコープの範囲 (125, 250, 500, 1000, 2000, 4000)
} cxd5602pwbimu_range_t;

// センサーデータ構造体
typedef struct {
  uint32_t timestamp;  // タイムスタンプ
  float temp;          // 温度
  float gx;            // ジャイロスコープX軸
  float gy;            // ジャイロスコープY軸
  float gz;            // ジャイロスコープZ軸
  float ax;            // 加速度計X軸
  float ay;            // 加速度計Y軸
  float az;            // 加速度計Z軸
} cxd5602pwbimu_data_t;

コード例

センサーの初期化と設定

#include <nuttx/sensors/cxd5602pwbimu.h>

int fd;
int ret;
cxd5602pwbimu_range_t range;

// デバイスを開く
fd = open("/dev/imu0", O_RDONLY);
if (fd < 0) {
  printf("エラー: デバイスを開けませんでした\n");
  return 1;
}

// サンプリングレートの設定(例: 480Hz)
ret = ioctl(fd, SNIOC_SSAMPRATE, 480);
if (ret) {
  printf("エラー: サンプリングレートの設定に失敗しました\n");
  close(fd);
  return 1;
}

// ダイナミックレンジの設定(例: 加速度=2G, ジャイロ=125dps)
range.accel = 2;
range.gyro = 125;
ret = ioctl(fd, SNIOC_SDRANGE, (unsigned long)(uintptr_t)&range);
if (ret) {
  printf("エラー: ダイナミックレンジの設定に失敗しました\n");
  close(fd);
  return 1;
}

// FIFOしきい値の設定(例: 1)
ret = ioctl(fd, SNIOC_SFIFOTHRESH, 1);
if (ret) {
  printf("エラー: FIFOしきい値の設定に失敗しました\n");
  close(fd);
  return 1;
}

// センサーの有効化
ret = ioctl(fd, SNIOC_ENABLE, 1);
if (ret) {
  printf("エラー: センサーの有効化に失敗しました\n");
  close(fd);
  return 1;
}

データの読み取り

cxd5602pwbimu_data_t data;
struct pollfd fds[1];

// pollの設定
fds[0].fd = fd;
fds[0].events = POLLIN;

// データが利用可能になるまで待機
ret = poll(fds, 1, 1000); // 1秒のタイムアウト
if (ret > 0 && (fds[0].revents & POLLIN)) {
  // データの読み取り
  ret = read(fd, &data, sizeof(data));
  if (ret == sizeof(data)) {
    // データの処理
    printf("温度: %.2f\n", data.temp);
    printf("加速度 (G): X=%.6f, Y=%.6f, Z=%.6f\n", data.ax, data.ay, data.az);
    printf("ジャイロスコープ (dps): X=%.6f, Y=%.6f, Z=%.6f\n", data.gx, data.gy, data.gz);
  }
}

// 終了時にセンサーを無効化
ioctl(fd, SNIOC_ENABLE, 0);
close(fd);

サンプルアプリケーション

Spresense SDKには、CXD5602PWBIMUセンサーを使用するためのサンプルアプリケーションが含まれています。

基本サンプル(cxd5602pwbimu)

基本的なセンサー使用法を示す簡単なサンプルです。1秒間データを収集し、標準出力に表示します。ビルドとフラッシュ後、UARTからpwbimuコマンドで起動します。

ロガーアプリケーション(cxd5602pwbimu_logger)

長期間のデータ収集と様々な出力形式をサポートするロガーアプリケーションです。

cxd5602pwbimu_logger [-s <rate>] [-a <acc_range>] [-g <gyro_range>] [-f <fifo_num>] [-o <out_dev>] [-d] [-h]

オプション:

  • -s <rate>: サンプリングレート(Hz)。有効値: 15, 30, 60, 120, 240, 480, 960, 1920
  • -a <acc_range>: 加速度計範囲(G)。有効値: 2, 4, 8, 16
  • -g <gyro_range>: ジャイロスコープ範囲(dps)。有効値: 125, 250, 500, 1000, 2000, 4000
  • -f <fifo_num>: FIFOサイズ。有効値: 1, 2, 3, 4
  • -o <out_dev>: 出力デバイス。'uart', 'net', '/path/to/file.bin', '/path/to/file.txt'
  • -d: UARTへのデータ表示を強制
  • -h: ヘルプの表示

用途別の推奨設定

一般的な動き検出

  • サンプリングレート: 60Hz
  • 加速度計範囲: 2G
  • ジャイロスコープ範囲: 250dps
  • FIFOしきい値: 1

スポーツ活動追跡

  • サンプリングレート: 240Hz
  • 加速度計範囲: 8G
  • ジャイロスコープ範囲: 1000dps
  • FIFOしきい値: 2

高精度動作分析

  • サンプリングレート: 960Hz
  • 加速度計範囲: 4G
  • ジャイロスコープ範囲: 500dps
  • FIFOしきい値: 1

バッテリー効率優先

  • サンプリングレート: 30Hz
  • 加速度計範囲: 2G
  • ジャイロスコープ範囲: 125dps
  • FIFOしきい値: 4

トラブルシューティング

データ読み取りエラー

  • デバイスパスが正しいことを確認(/dev/imu0)
  • センサーが有効になっているか確認
  • FIFO閾値設定を確認

不正確なデータ

  • 最初の50msのデータは無視する(初期化ノイズを含む可能性があります)
  • ダイナミックレンジが適切に設定されているか確認
  • サンプリングレートがアプリケーションに適しているか確認

パフォーマンスの問題

  • サンプリングレートを下げてみる
  • データ処理頻度を減らすためにFIFO閾値を上げる
  • 不要なデータ処理を最小限に抑える

アプリケーション

従来の産業用FOG(光ファイバージャイロスコープ)の実装が困難な場面に適しています:

  • 構造物検査用ドローン
  • 小型自律移動ロボット
  • 正確な位置と方向の推定が必要なデバイス
  • 地球の回転検出を利用したジャイロコンパスアプリケーション

参考リンク

SPRESENSE公式

動作例

https://x.com/GOROman/status/1896200165670912331

Discussion

ログインするとコメントできます