google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

3軸ジャイロ L3GD20 をArduino で動かしてみる

◆まえがき
ちょっとやって見たいことがあるので、昔買ったL3GD20という3軸ジャイロセンサーを、Arduino NANOで動かしてみました。

◆3軸ジャイロ L3GD20
3軸ジャイロL3GD20
STマイクロのセンサーを秋月の接続カードに実装した物です。なお、現在ではこの部品は廃版になっていて、L3GD20Hと言う型番に変わっています。

◆回路図
3軸ジャイロL3GD20の回路図
Arduino NANOに接続した状態です。このジャイロは3.3V動作なので、NANOから出ている3.3V電源を使って動かします。

インターフェイスはI2Cで動かし、そのバスのレベルは3.3Vにします(3.3Vに4.7kΩでプルアップ)。実はこういう接続方法にすると、NANO側の入力のHighレベルが十分確保出来ていないのですが、まあちょっと試すくらいなら大丈夫です。詳しくは、こちらの記事で解説しています。

◆I2Cの波形
ちょっと面白い話があるのでI2Cの波形を見ながら説明します。
・プルアップ抵抗4.7kΩの場合
4.7kΩでプルアップ
下がクロック(SCL)、上がデーター(SDA)です。バススピード100kHzで動いていて、当然ですが振幅は3.3Vです。記事に掲載した回路図通りに作るとこの波形になっています。

・プルアップ抵抗無しの場合
プルアップ抵抗無し(CPU内蔵プルアップのみ)
実は4.7kΩのプルアップ抵抗を外しても回路は正常に動き、その時の波形は上の写真のようになります。

プルアップ抵抗無しにするとバスが動かなくなるかと思ったら、実は大丈夫です。ArduinoのI2C(Wire.h)のライブラリは、I2Cのピン(A4とA5)のCPU内蔵のプルアップ抵抗を有効にするので、約35kΩで5Vへプルアップされた状態になります。つまり弱くプルアップされるので、100kHzくらいの速度なら何とか動きます。

上の波形の立ち上がり部のなまりは、プルアップ抵抗が高いために発生しています。あと、波形の振幅を良く見ると、一つ上の波形より少し大きくなっていますが、これは5Vにプルアップされているためです。(一つ上の波形は3.3Vに4.7kΩでプルアップされています。)

◆ブレッドボード
ブレッドボード

◆プログラム
// File:20220111_L3GD20test.ino
// Arduino で3軸ジャイロ(L3GD20)の値を読む
// 2022/01/11 ラジオペンチ

#include <Wire.h>

#define L3GD20_ADDR 0x6a // I2Cアドレス
#define L3GD20_CTRL_REG1 0x20 //

int rotX, rotY, rotZ; // 現在の角度
int rotX0, rotY0, rotZ0; // ゼロ補正量

void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("x,y,z"); // シリアルデーターの項目名を表示
gyroSetup(); // ジャイロのモード設定
zeroCalib(); // ジャイロのゼロキャリブレーション
}

void loop() {
sensAngle(); // 現在の姿勢を計測
Serial.print(rotX); Serial.print(", "); // 結果を表示
Serial.print(rotY); Serial.print(", ");
Serial.print(rotZ); Serial.println();
delay(30);
}

void sensAngle() { // ジャイロの値を読む
int hi, lo;
lo = L3GD20_read(0x28);
hi = L3GD20_read(0x29);
rotX = ((hi << 8) | lo) - rotX0 ; // X軸
lo = L3GD20_read(0x2A);
hi = L3GD20_read(0x2B);
rotY = ((hi << 8) | lo) - rotY0 ; // Y軸
lo = L3GD20_read(0x2C);
hi = L3GD20_read(0x2D);
rotZ = ((hi << 8) | lo) - rotZ0 ; // Z軸
}

void zeroCalib() { // ジャイロのゼロ点補正
int xs = 0; // sum値用変数
int ys = 0;
int zs = 0;

rotX0 = 0; // ゼロ補正無しにして、
rotY0 = 0;
rotZ0 = 0;
for (int i = 0; i < 100; i++) { // 100回
sensAngle(); // 測定して
xs += rotX; // 値を累積
ys += rotY;
zs += rotZ;
delay(10);
}
rotX0 = xs / 100; // ゼロ補正量を設定
rotY0 = ys / 100;
rotZ0 = zs / 100;
}

void gyroSetup() { // ジャイロのモード設定
Wire.beginTransmission(L3GD20_ADDR);
Wire.write(L3GD20_CTRL_REG1);
Wire.write(0x0f); // 動作モード設定
Wire.endTransmission();
}

byte L3GD20_read(byte reg) { // 指定アドレスの値を読む
Wire.beginTransmission(L3GD20_ADDR);
Wire.write(reg); // レジスタ番号を指定
Wire.endTransmission();
Wire.requestFrom(L3GD20_ADDR, 1);
return Wire.read(); // データーを読んで帰り値にする
}
ネットに転がっていた事例を参考に書き直したもので、ジャイロを使って角速度を測定してシリアルに流すようになっています。

ジャイロの測定結果にオフセットが100くらいあったので、起動時にzeroCalib関数でオフセット量を測定して補正するようにしました。

◆動作例
ジャイロの応答波形

手でジャイロを持っていろいろな向きに傾け、出力をシリアルプロッタで見たものです。動きを3軸に分離して検出出来ています。

◆まとめ
とりあえずこれで動作確認できました。このセンサーはArduinoいじりを始めた頃に倒立振子を作るために買った物で、5-6年ぶりに動かしてみた訳ですが、ちゃんと動いて良かったです。

ジャイロの出力波形がギザギザしているような感じで少し気になるのですが、あまり高い精度が必要なことに使う予定では無いので無視することにします。

これで動き(回転角)の検出ができるようになりました。次は、画面に顔を表示しているプログラム(Arduino NANO アバター)と組み合わせてみたいと思います。触ると表情が変わるような物が作れるはずです。
関連記事

コメントの投稿

管理者にだけ表示を許可する

ジャイロって

空想上の話なんですけど・・。ユーチューブで人が乗ってる4発電動ドローンがありますけど、これを使うと水平飛行を保てるってことになるのでしょうか?

re:ジャイロって

このセンサーのデータシートを読むと、ゲーム機器などでの使用を想定しているようで、ドローンへの使用は書かれてなかったです。でも原理的にはドローンに使うことも可能だと思います。

ただ、人が乗る場合は桁違いの信頼性が必要になるので、このセンサーでは無理だと思います。

No title

ありがとうございます。しかし面白い電子機器(部品?)があるものですね。ジャイロと云えばあのコマ状のものしか思い浮かびませんでした。
カレンダー
05 | 2023/06 | 07
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード