2014/11/23

続06) Arduino始めてみた - 方位センサー (GY-271/HMC5883L)

サッカーでは、自分のゴールと相手のゴールを区別し無くてはならない。でないとオウンゴールを量産する。 ということで、ロボカップジュニアでは、ゴールを青色と黄色に塗り分けて敵と味方を区別している。
ゴールの色を識別する方法が人間のやり方に近いけど、色を認識するセンサーは精度と反応速度の面からあまり主流ではなく、代わりにその場の磁場を読み取ってマシンの向きを検知する方位センサー(地磁気センサー)が主流である。
方位センサーで何が分かるかというと大雑把に言うと、画像のXY軸が地面に平面方向で方角がわかり、Z軸で地面に対する傾きがわかる、でいいかな。
また、現実的には建物内の電力線にから電磁波は撒き散らされているので地磁気センサーから取得したデータをそのまま使うことができない。補正する必要がある。 後述する。

GY-271
私のマシン用には、いくつかの候補の中から安価なGY-271を購入した。
GY-271は3軸の地磁気センサーHMC5833Lに電源チップやI2C通信機能などを加えてコンパクトに使いやすくしたもの。
重要なのはHMC5833Lである。GY-271の中央にある黒い正方形の箱がそれ。
詳しく知りたい場合はこちら(英語)を参照する。
サンプルプログラムを単体試験で使用した。
また、データシートはこちら(PDF/英語)。
データの取得間隔は15Hz (67msec周期)。
1枚目の画像がGY-271を取り付けた図。緑色のボードの裏側に取り付けた。間に合わせのやっつけです。
環境電磁波からの影響を避けるためにもう少し高いところに設置したかったが、手持ちの材料ではこれがイッパイイッパイ。

Arduinoに接続
GY-271には5本の端子が出ている。また、I2C通信なので信号はSCL/SDAに接続する。
それぞれの接続先は次のとおりとなった。
  • VCC → 5V (+)
  • GND → Ground (−)
  • SCL → A5 (SCL)
  • SDA → A4 (SDA)
  • DRDY → 接続しない 
2枚目はGY-271を裏から見た画像。
ボードに端子用の穴を開けている。

方位を知る
GY-271から取得できるデータは、X軸、Y軸、Z軸の値である。
XとYは北を向くと数字が小さくなる。
参考までに、地磁気には偏位があるので(磁気偏角)、地域によって方位が偏る。
国土地理院のページを参照。

さて、方位センサーでXとYの値がわかると、中心(X0,Y0) = (0,0)からの角度が分かる。
(X0,Y0)を基準として、XYの値から角度を求めるには、タンジェントの逆関数を使えばよい。
具体的には次の式となる。
角度(ラジアン) = atan2(y,x);
// atan2(y, x) : arc tangent of y/x
または、角度(°)だと、
角度(°) = atan2(y, x) * (180 / PI);
// PI = π = 3.14159265...
もしくは、Arduinoに用意されている次の定義を使ってもOK。
角度(°) = atan2(y, x) * RAD_TO_DEG;
// RAD_TO_DEG = (180 / PI) : ラジアンから度(°)への変換
地磁気データを補正
しかし、地磁気というのは、周囲に電磁波があると影響される。
建物の中などで電力線が電磁波をまき散らしていると、地磁気センサーで取得する値が大きくずれてくる、というのが現実である。

追記
以下のサイトが非常に参考になった(ほとんど真似っ子である)。
demura.net - e-gadgetやTJ3から使える地磁気センサGY-271(HMC5883L使用)



2枚目の画像が、マシンを回転させて、その時のGY-271の値を読み取り、グラフにプロットしたもの。横軸がXで、縦軸がY軸である。

3F-1の(青色)と3F-2の(緑色)は自宅の3階のPCデスク上 、2Fの(黄色)はその真下の2階である。
また、取得したXYのそれぞれ最高値と最小値から円の中心を求めてある。
すると、どうでしょう、円の中心は(0,0)ではなく、大きずれているのが分かる。
しかし、このプロットされた値をそのまま使うと角度がおおよそ260°〜315°くらいの範囲となり、マシンがどこを向いても常に一つの方位をむいているように見えて、結局値からはマシンがどこを向いているのか分からない。
よって、中心点を(0,0)に補正する必要がある(引き算ですね)。
角度補正(°) = atan2(y - centerY, x - centerX) * (180 / PI);
また、別の日に取得しした、自宅3階と大会会場の中心点の記録が残っていたのでがプロットする。3階3F-3が(橙色)で、大会会場が(赤色)である。
グラフからも分かるように3F-3と大会会場は3F-1、3F-2と2Fとは中心点がずれている。
その都度場所に合わせた補正が必要になることがわかる。
(HMC5833Lのデータシートを読むと、そもそもこのセンサーの値は大丈夫かという気もするが、実用上はグラフを見ての通り、方位を求められるのでなんとかなると考えている)

実践
以上の準備を経て、マシンを試合コートに設置した時に相手ゴールに正面を向け、電源を入れると、そこを正面=「0°」とするように補正し、常に正面を向くようにスケッチ(プログラム)を仕上げることとした。
まず、試合前の準備として、コート上の地磁気の補正のためにマシンをスピンさせてXYの中心値を求める。
上記の結果、本番のスケッチでは地磁気センサーに関して次の動きを行う。
  1. 宣言
    1. 中心値を定義する 
  2. setup()
    1. 補正1(中心):中心のズレの補正を行う。
    2. 補正2(角度):電源を入れた時(つまり初期値)、正面の角度を「0°」に補正する。
  3. loop()
    1. 正面軸(0°)とのズレを常に監視して、ずれたら「0°」を向くようにマシンを左右にスピンする。

2014/11/20

続05) Arduino始めてみた - モーターシールド (Adafruit (V1) 互換? Duinofun製 Motor Shield)

前回の続き。
ch1のモーターの挙動がおかしい。
でも、モーター自身は正常だ。
となると、モーターシールドが怪しい。
ちなみにArduinoでは、拡張基板のことをシールドと呼ぶ。

コピー製品だった
その前にこのモーターシールドをどうやって使ったか。
って、書く前にもう一度このモーターシールドを眺めてみると、Adafruit (エイダフルート)製だと思っていたのに、どうもDuinofunのコピー製品であった。1枚目の画像の中央と右のICの間にURLが書いてある。
どうしてコピー製品と思うかというと、Duinofunにはライブラリが存在せず、Adafruitのライブラリを使用し参照していて問題なかったから (というのは根拠が弱いのは承知の助)。
以下は、ずっとAdafruit製だと疑いもせずに調べた結果である。
DCモーターの使用が前提である。

使うまで
  1. まず、Overviewがあるので、困ったらここを参照する。V1用V2用
  2. 次に、ライブラリを入手する。V1(IC)とV2(表面実装)ではライブラリが違うらしい。V1用ライブラリV2用ライブラリ
  3. Arduino IDE (アプリ) にライブラリを追加する。(次のAFMotor.hを読み込めるようにするため)
  4. スケッチ(Arduinoのプログラムのこと)の宣言文コーナーに "#include <AFMotor.h>" を追加する。
スケッチ (プログラム)
まずは、AF_DCMotor Classの定義を使うためにここを参照する。V1用V2用
おっと、V1とV2では、ライブラリの構造が大きく違うようだ。ここまで違うと参考にならない。
V1は廃番なので、ここのスケッチの記述ほとんど未来の自分用だな〜。
以下は、V1用の記述である。

まず、include文とクラスの宣言。g_motorNという4つのモーター毎の変数を宣言する。
#include <AFMotor.h>
AF_DCMotor g_motor1(1, MOTOR12_1KHZ);  // MOTOR12_1KHZの引数は省略可能。以下同じ
AF_DCMotor g_motor2(2, MOTOR12_1KHZ);
AF_DCMotor g_motor3(3, MOTOR34_1KHZ);
AF_DCMotor g_motor4(4, MOTOR34_1KHZ);
スケッチでは、"run" と "setSpeed" という2つのメンバで指定された関数でモーターを制御する。
g_motor1.setSpeed(100); // モーター1のスピードを決める。値は 0〜255。255が最大出力。
g_motor1.run(RELEASE);  // モーター1の回転方向を決める。FORWARD (正)、BACKWARD(逆)、RELEASE (解除)
ちなみに run(RELEASE)は、setSpeed(0)と同じ。
また、ダイナミックブレーキは用意していないので、すぐにストップするわけではない、と書いてある。
試しに"AFMotor.h" の中を覗くと、"BREAK"が"FORWARD"などと同じく定数として用意されているようだが、定義はされていないみたい。

外部電源
PCからのUSB接続では、電圧が足りないっぽい。
そのため、電池を外付けする。
電池はリチウム充電池の18650という規格のもの。
3.7Vで保護回路付き。
4個の電池を直列並列の組み合わせでで7.4Vで使う計算になる。
サイズが特殊なので電池ボックスの入手先はほとんど選択肢がなかった。
14500というのが単3サイズなのでお薦め。
モーターシールドからモーター専用の電源を確保するために、画像上真ん中右よりのジャンパーピンを抜く。
ジャンパーピン自体は失くならないように片方のピンだけに挿しておく。
これで、本体の基板(UnoやMEGA)からモーターへの電源が切断される。
電源ボックスとモーターシールドの電源端子間にトグルスイッチもつける。

トラブル:現象
先にも書いたが、ch1のモーターが動かない。
画像をよく眺めてみると、モータードライバー用のICが2個左右に刺さってる。これかなぁ、と疑い、チップをよく見ると「ST L293D」と書いてあるので検索すると、引っかかった。数日後には手に入れて、交換してみる。

トラブル:障害箇所切り分け
L293Dが届くまでの間、同じくArduinoでマシンを組み立てている保護者の方の好意に甘えて、双方のマシンで入れ替え合戦をしてダメそうな箇所を特定してみる。
  • 私のArduino MEGA2560をUnoに変えてみる → NG。
  • 私のモーターシールドを先方のUnoに乗せてみる → OK
ここで時間切れとなった。
MEGAが互換品だし、相性ですかね? ということになったので、Unoを発注する。

トラブル:モータードライバIC(L293D)を交換
Unoが届いたので、MEGA2560をUnoに交換する。
やっぱりNGなので L293Dを2個とも交換してみる。すると、1回目だけは動いた。
おお、これか、と安心したところ、 次からダメ。
L293Dの交換後にいろいろやっていると、これまでに2度ほど超音波センサー(HC-SR04)の裏面をドライバを不用意に接触、ショートさせたことを思い出したので、その時にチップを飛ばしてしまったか、と思いあたり、さらにL293Dを4個発注する。

トラブル:FAQに答えが
ここで、ch1のモーターが正常に動作しないまま、本番の日を迎える。

間に合わず、と思ったが、他にできることもないので会場で何か情報はないかとAdafruitのFAQを眺めていると、あれ? 書いてあるわ、ディジタルピンの10番はch1で使用していると。
えーっと、10番は超音波センサーと干渉しているではないか。
がっくし、だけど、やったー。
時間もないので、超音波センサーのジャンパーワイヤーを11番から9番へ変更して、スケッチも変更してみる。
何事もなかったように動く。
MEGAとモーターシールドとの相性なんかじゃなかった。
あーぁ。

What pins are not used on the motor shield?

All 6 analog input pins are available. They can also be used as digital pins (pins #14 thru 19)
Digital pin 2, and 13 are not used.
The following pins are in use only if the DC/Stepper noted is in use:
Digital pin 11: DC Motor #1 / Stepper #1 (activation/speed control)
Digital pin 3: DC Motor #2 / Stepper #1 (activation/speed control)
Digital pin 5: DC Motor #3 / Stepper #2 (activation/speed control)
Digital pin 6: DC Motor #4 / Stepper #2 (activation/speed control)
The following pins are in use if any DC/steppers are used
Digital pin 4, 7, 8 and 12 are used to drive the DC/Stepper motors via the 74HC595 serial-to-parallel latch
The following pins are used only if that particular servo is in use:
Digitals pin 9: Servo #1 control
Digital pin 10: Servo #2 control
DCモーターではデジタルピンの3番(ch2)、5番(ch3)、6番(ch4)、11番(ch1)を使用とのこと。
また、4番、7番、8番、12番もモーターシールドの真ん中に鎮座しているシフトレジスタIC 74HC595 で使用されているとのこと。
9番、10番はステッピングモーターで使用されるとのことだが、DCモーターオンリーなので空きとなる。
0番と1番はArduinoとPCをUSB接続するときに使われるので実質的に使用できない。
となると、UnoでDCモーターを4ch利用する場合、デジタルピンの空きは2番、9番、10番、13番の4本となる。
アナログピンは6本ともオールフリー(使用可能)。 
でもね、FAQ以外に書くところなかったのかよ、が魂の叫びであった(FAQに対する考え方の相違)。

他にもいろいろミスがあって、本番は散々であった。

トラブル:後日談
根本的な原因が判明した3日後にL293Dが 4個 届いた。
基板に刺さっている2個を含めて 合計8個 もある。
つまり、予備が6個。
MEGAも余ったよ(まだUnoから元に戻していない)。
うーむ。

これから
モーターに高周波ノイズキャンセラー(といってもコンデンサ1個だが)を取り付けてみたい。


次回の記事は、方位センサーにしよう。

2014/11/18

続04) Arduino始めてみた - メカナムホイール

通常はオムニホイールを使うのが圧倒的多数なのに、なぜ、メカナムホイールか?
4個で8千円で、オムニとそう変わらず、珍しいから子どもたちも目を引くだろうし、大人が参戦するなら、最高のお手本となるか、もしくは、少しは変わったものがいいだろう、ということで後者となった次第。

ヴィストンのメカナムホイールとダイセンのモーターに固定するにはハブが必要であった。
このハブを連結すると、メカナムホイールを自動車型に配置するとどうしてもサイズが大きくなる。ロボカップジュニアのサッカーのルールに従うと、外形サイズを直径22cmの円内に収める必要が有る。
そのため、1枚目の画像のようにシャーシを凸型にカットして、モーターの配置を工夫した。
通常のメカナムホイールマシンは自動車のように車輪の正回転が前進、逆回転が後進になるが、このマシンは前後を左右に90°ばかり振っている。
この配置は他には見当たらないと思うので、この工夫だけでも作る甲斐があるというもの。

メカナムホイールの特徴として取り付け方向(自動車の車輪の向き)から90℃の方向が一番動きにくい。自動車で言うと横に動く方向である。
このマシンの配置の場合、左右(この画像の上下)には動きやすいが、前後(同じく左右)には動きにくくなる。これを逆手にとって、左右にはよく動いて欲しいけど、あまり前に出る必要がないキーパー専用で使うこととした。
万能選手を作りたいならオムニがいいと思う。
また、ホイールが案外重いというか、スタートダッシュもイマイチなので、モーターのギア比はもう少し大きい方が(トルクが大きい方が)よかったかもしれない(1:15を買ったけど、1:30とか1:100がお薦め)。
2枚目の画像は正面から見たマシン。
プロトタイプなのでやっつけ感満載な気もするが、とりあえず動かす。

モーターの制御、および、各センサーの単体試験用プログラムを用意してセンサー値が確実に取得できることまで確認したところで、本番用の結合プログラムを書いたところ、どうも、ch1のモーターがちゃんと動かない。モーターを入れ替えしたりしてもモーター自体は問題なさそうである。
となるとモーターシールドが疑われる。
うむ。

=====
この記事はArduinoとは関係ないですね。

2014/11/17

続03) Arduino始めてみた - パーツリスト

大会に間に合うように超特急でロボカップジュニアのルールに準ずるサッカーマシンを仕上げてみた。
使ったパーツは以下のとおり。

本体
センサー
足回り
その他
  • ピンヘッダ用ジャンパワイヤ オスーオス、メスーメス 各20本
  • 単3乾電池2個用電池ボックス x1
  • 18650充電池4個用電池ボックス  x1
  • DCコネクタ(内径2.1mm、外形5.5mm) x1
  • 撚り線ワイヤー(電池ボックス〜電源部間用) 3m
  • トグルスイッチ (基板用、モーター用) x2
  • M3ネジ、M3ねじ用ナット、ワッシャー x?
  • スペーサー(M3ネジ付き) x6
振り返ってみると、いろいろ買ってるなぁ。

2014/11/11

MAGIC! - "Rude"

車を運転しながら米軍のFM放送を聞いているとキャッチーなレゲェベースの曲が流れて来た。面白いなと思ったので、家に戻って調べてみた。MAGIC!というカナダのバンドの"Rude"という曲だった。
"rude" とは日本語で、失礼な、無礼な、不躾な、無作法な、などという意味。

古いタイプの父親に、彼女との結婚の許可をもらおうとするが、門前払いにされる、というのが大まかなストーリー。主人公がその父親に向かって叫んでいる場面でタイトルの"rude"が出てくる。
Why you gotta be so rude?  (なんでそういう失礼な態度をとるんだ?)
Don't you know I'm human too  (僕も人間だっていうことを知らないのかい)
Why you gotta be so rude?  (なんでそんなに失礼なんだい?)
I'm gonna marry her anyway  (どのみち彼女と結婚するよ)
父親が古風だと知っていたからこそ、いい服も着てわざわざ許可を取るという手順を踏まえて礼も尽くしたのにその言い草は無いだろう、こっちも同じ人間だぜ! という誰も誰かの所有物ではないしひとりひとりが尊重されるべき、というところが新しなと思った。
同じ人間だぜ!
ついでにいうとプロモーションビデオで最後は主人公の元へ寄って行く彼女のスタイルもそうだ。




メロディも歌詞もカバーしたくなるようでいくつか面白いカバーを紹介。
カバーだけでなくパロディもたくさんある。

1950年台スタイル風。
アレンジもバンドも面白い。特にボーカルとピアノが良かった。
お薦め。


女性バージョン。
歌詞も「彼女の側」からの視点に変更されている。


女性&ウクレレバージョン。時々こぶしが入るw


10才の子どもによる子犬を飼いたいバージョン。
歌詞もわからず屋の父親に対して「なんでダメなの〜!」って感じで訴えている。


パロディーはこちら、ストーカーバージョン。

2014/11/08

続02) Arduino始めてみた

Arduinoで作成中のプログラムを同じフォルダの中に「別名で保存」しようとすると、画像のような警告が出た。
[ それはムリです ]
自らのスケッチのフォルダの中にスケッチを保存することなんてできません。無限ループになっちゃいます。
[ OK ]

くだけていて面白い。
Arduinoでは、スケッチ(← プログラムファイル)は、拡張子を除いた部分の同じ名前のフォルダの中に存在しないといけない、というルールがあるので、指摘されたらしい。
しかたがないので、新規のフォルダを作成して、同じ名前のファイル名で保存した。

メカナムホイールを使ったサッカーマシンを制作しているのだけど、いろいろつまづいた点をおさらいして後の記事にしたい。

zenback