これまで実験してきたもので倒立振子を作成してみました。
CPU: Arduino
センサー: 加速度センサー(KXM52-1050)のみ
モータードライバ:ダイセン電子工業 モータードライバ
モーター:ダイセン電子工業 ギヤドモーター(30:1)
ハードは子供に作ってもらいました。
結果は。。。写真で手が支えていることから分かるように、うまくいきませんでした。
それらしい動きはするものの1秒も持ちません。
加速度センサーで重力加速度を計測することで傾きが分かるだろうと思いましたが、(懸念はしていましたが)モーターによる動きが加速度センサーに影響を与えてしまっているようです。
倒立振子の制御についてWEBを検索してみたところ、ジャイロセンサーとロータリーエンコーダで制御しているものが多いようです。
手持ちのジャイロセンサーがあるので、次回試してみたいと思います。
いろいろ実験して、前回から分かったこと。
■生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; とかにすると、すぐに止まってしまう。
前回、うまくいかなかった、Arduinoでダイセンモータードライバーを動かす実験ですが、少しゴール(スタート?)が見えてきました。
まず、先日の生AVRブレッドボードで動かしてみます。
前回のコメントでぽよこまだんなさんからアドバイスいただいて、SCLとSDAはモータードライバー側でプルアップされているので、直結すれば良く、配線はすっきりです。
プログラムはI2Cのところから作らないといけないので、ここを参考にしました。
最初は一応動くものの、すぐに止まってしまう状態でしたが、以下の2点でだいぶ改善できました。
- WinAVRのコンパイルの最適化を-Osから-O0または-O1にする。
- データ送信後の終了処理の前に少しWAITを入れる。
これで5分ぐらい持つようになりました。
Arduino上での動作は次回へつづく。
AVRをArduino化するための前実験として、ATMEGA168PにLED点滅のプログラムを書き込む実験を行いました。
書き込みはATMEL純正のAVR ISP mkⅡを使用しました。
AVR ISP mkⅡのコネクタは2×3なので、ブレッドボードに接続できません。
なので、変換コネクタを作ってみました。