「ロボット・電子工作・マイコン」カテゴリーアーカイブ

Arduino倒立振子にジャイロセンサーを追加

だいぶ間が開いてしまいましたが、、、Aruduinoで作った倒立振子ジャイロセンサーを搭載して試してみました。
結果は2・3秒は立つようになりましたが、まだまだうまくいきません。
制御のやり方が根本的に間違っているのだと思います。
モータードライバを子供に返さないといけないのと、他にやりたいこともあるので、倒立振子はしばらくお休みします。

ジャイロセンサー

秋月の2軸ジャイロセンサーモジュール(AE-GYRO-SMD)を試してみました。

f:id:studio_k:20100315225047j:image:w240

ジャイロセンサーは回転の角速度が取れるはずなのですが、何かおかしいです。

回転させた後、回転を止めたときに反対向きに回転させた時の値になってしまいます。(うまく説明できませんが。)

WEB上の情報を調べたところ、温度ドリフトの影響を除去するためのハイパスフィルターが影響していることがわかったので、C6, C7をショートしたところ、それらしい値が取れるようになりました。

【参考】http://d.hatena.ne.jp/n-u-ki/20100216/p2

しかし、センサーメーカー(村田製作所)の回路例と同じなのですがね。。。

センサーを温めたりすると、値が変わるようになってしまいましたが、プログラムの工夫でなんとか回避できると思います。

Arduinoで倒立振子に挑戦

これまで実験してきたもので倒立振子を作成してみました。
f:id:studio_k:20100314195551j:image:left:w240

CPU: Arduino
センサー: 加速度センサー(KXM52-1050)のみ
モータードライバ:ダイセン電子工業 モータードライバ
モーター:ダイセン電子工業 ギヤドモーター(30:1)

ハードは子供に作ってもらいました。

結果は。。。写真で手が支えていることから分かるように、うまくいきませんでした。
それらしい動きはするものの1秒も持ちません。

加速度センサーで重力加速度を計測することで傾きが分かるだろうと思いましたが、(懸念はしていましたが)モーターによる動きが加速度センサーに影響を与えてしまっているようです。
倒立振子の制御についてWEBを検索してみたところ、ジャイロセンサーとロータリーエンコーダで制御しているものが多いようです。

手持ちのジャイロセンサーがあるので、次回試してみたいと思います。

Arduino+ダイセンモータードライバー(その3)

f:id:studio_k:20100306175500j:image:w240

いろいろ実験して、前回から分かったこと。

■生AVR+ダイセンモータードライバー

  • ダイセンモータードライバーの6番ポートを使用するとおかしくなる。
  • WinAVRのコンパイルの最適化は関係ない。(-Osでも問題なし)
  • データ送信後の終了処理の前のWAITは少し必要(1msぐらい)。

■Arduino+ダイセンモータードライバー

  • ダイセンモータードライバーの6番ポートを使用しなければ問題なし。
  • スレーブアドレスは1ビット右シフトする。Wire.beginTransmission(0x14>>1);

モータードライバの1ポートが使えないものの、これで万事問題なしでした。

そういえば、以前からこのモータードライバの6番ポートはおかしいとのうわさがあったのですが。

もっとも、今回実験したボードは1年ぐらい前に購入したものですので、今は直っているかもしれません。

また、結局関係なかったのですが、Arduino IDEでコンパイルの最適化オプションは変えられないようです。

Arduino IDEのソースを確認したところ、コンパイルオプションのところがハードコーディングされていました。

pde.jarをjarコマンドで展開して、classファイルをバイナリエディタで変更したところ、

最適化オプションを変更できたことは確認できました。

【最終版スケッチ】

#include <Wire.h>
#define TJ3M_ADDR (0x14>>1)
byte b[6];
int i =0;
void setup()
{
Wire.begin();
pinMode(13, OUTPUT);
delay(100);
}
void loop()
{
Wire.beginTransmission(TJ3M_ADDR);
for (int j=0; j<6; j++) {
if (i==j) b[j] = 50;
else b[j] = 0;
}
b[5] = 0;
Wire.send(b, 6);
Wire.endTransmission();
if ((i&1) == 0)
digitalWrite(13, HIGH);
else
digitalWrite(13, LOW);
delay(10);
i++;
if (i>=6) i=0;
}

b[5] = 0; のところを b[5] = 50; とかにすると、すぐに止まってしまう。