====== ジャイロを使ってみよう ====== ===== ジャイロとは ===== ジャイロ (=Gyroscope) とは、角速度を計測する事ができるセンサーです。角速度は基本的にタイヤの回転数の比に比例しますが、早く曲がろうとするにつれて追従しなくなって行きます。 \\ また、最近流行している変則4輪マウスの場合、根本的にタイヤの回転数の比と車体の角速度が比例しないため、ジャイロがないと超信地旋回すらできません。 デバイスは[[http://www.analog.com/jp/index.html|AnalogDevices]]や、[[http://www.st.com/internet/com/home/home.jsp|STMicroelectronics]]、[[http://www.invensense.com/|InvenSense]]の物が有名です。 ===== ジャイロの種類 ===== ジャイロにはいろいろな種類があります。 ==== 出力の形式 ==== * アナログ * 角速度に比例した電圧出力 * 使いやすい * 好きなタイミングで値を読みに行ける * デジタル * IICやSPIなどの通信で値を読み出す * 出力bit数が大きい(16bitなど) * 通信をするため、値を読むタイミングが難しい 以上のような特徴があります。 ==== 内部の方式 ==== * 圧電振動方式 * 出回っている物は出力の特性が線形でなかったり、左右の回転で特性が異なる等、マウスでは使いにくい * おもちゃを作りたい時には、安くて入手性が良いのでおすすめ * MEMS方式 * 現在主流のセンサ * 温度などによってゼロ点が少しずれる * 出力はほぼ線形 * ぶっちゃけこれ以外を使う事はないです * その他 * 光ファイバジャイロやリングレーザージャイロなど。興味があれば調べてみましょう ==== 出力の感度 ==== 角速度 - 出力特性の傾きです。 \\ データシートを読みましょう。また、関連する基本スペックとして、計測範囲(飽和する所らへん)が書いてあります。 \\ ±1200[deg/s]まで のように書いてあります。 クラシック競技で、±1000[deg/s]、 ハーフ競技では±2000[deg/s]くらいまで計測できるものがあれば良いとされているようです。 あまりにレンジの大きな物を選ぶと、実用する範囲での精度が落ちるので、上記くらいの範囲の物を選ぶのが良いでしょう。 ==== 軸 ==== Yaw, Roll, Pitchの3つの回転軸のうち、どれを計測できるかが示されています。 \\ マウスに必要なのはYaw軸なので、出力にYaw軸が含まれている物を選びましょう。 ===== ジャイロ値の読み出しと積分 ===== まず、[[物理量ベースとは|物理量ベース]]になっていないと、ジャイロを使うのは難しいです。ジャイロを導入しようと思うのであればこちらを先に完成させてください。 まず、ジャイロの出力から実際の角速度[rad/s]に直します。 \\ アナログ出力の場合を示します。デジタル出力の場合は、感度が[deg/s/digit]で与えられているので、それに従って同じ事をするだけです。 /* 外部で、chのAD変換結果を電圧で返す、float get_ad(int ch); や、 AD変換が行われるまで待つ、void wait_next_ad(void);が作成されているとする。 */ #define DEG2RAD(x) (((x)/180.0)*PI) // 度数法からラジアンに変換 #define RAD2DEG(x) (180.0*((x)/PI)) // ラジアンから度数法に変換 // ジャイロ関連マクロ #define GYRO_CH // ジャイロの結果が入っているADのチャンネル #define GYRO_SENSITIVITY (????) // ジャイロの感度[deg/s/V] #define GYRO_REF_NUM (100) // 何回の平均をもってジャイロのリファレンス電圧とするか。 #define GYRO_SIGN (1.0f) // ジャイロの出力の符号。自分の座標系にあった方向に、1.0fか-1.0fを掛けて修正する。 float gyro_ref_volt; // ジャイロのリファレンス電圧をリセットする。 // 単なる平均でなく、メディアンフィルタ等と組み合わせても良い。 void resetGyroReference(void) { int i; gyro_ref_volt = 0.0f; for(i = 0; i < GYRO_REF_NUM; i++) { wait_next_ad(); //次のAD変換が行われるまで待つ関数とする gyro_ref_volt += get_ad(GYRO_CH); } gyro_ref_volt /= GYRO_REF_NUM; } // 角速度を返す float getAngularVelocity(void) { return DEG2RAD( GYRO_SENSITIVITY * ( get_ad(GYRO_CH) - gyro_ref_volt ) ); } 上記のように、簡単に角速度の出力が得られます。 \\ またジャイロの特徴として、高精度なので積分しても生じるずれが少なく、角度も高精度で計測できます。 角度についても、次のように簡単に求められます。 #define SYSTEM_PERIOD (0.001f) // 積分周期[s] float angle; //角度 float angvel; //角速度 /* ジャイロから得た角速度を積分し、角度を得る。 angvelには、他の場所で取得した角速度が入っているとする。 この関数はSYSTEM_PERIOD秒間隔で呼び出されるとする。 */ void integrateGyro(void) { angle += angvel * SYSTEM_PERIOD; } これだけです。が、長い間(回路やジャイロによっても異なるが、数十秒くらい)積分し続けると、ずれが生じてくるので、どこかで積分をリセットする必要があります。 ===== ジャイロを使った制御 ===== ジャイロから得た角速度、角度を使って、実際に制御を行います。 角度をP、角速度をD、角度の積分をIとして普通のPID制御を行うと、綺麗に制御できます。