読者です 読者をやめる 読者になる 読者になる

Lambdaカクテル

ソフトウェア開発者です.玉石混淆です.

Raspberry Pi 2で無人飛行機の進捗

加速度計が動かない、GPSが喋らない

Raspberry Piで無人飛行機を作るプロジェクトを勝手に一人で始めたのだけれど、まずは各種メトリクスの収集が必要なのでセンサモジュールを購入して弄っている。

前回の記事はこちら。

windymelt.hatenablog.com

ジャイロモジュール

飛行機の回転を検出するジャイロセンサモジュールはスイッチサイエンスから購入。

www.switch-science.com

I2Cを叩くと素直に動く。Raspberry Pi 2でI2Cを弄るにあたって『最近の Raspberry Pi で I2C を有効化する方法 - Rabbit Note』あたりを参考にした。I2Cの実際の操作はPythonSMBusというライブラリを使った*1

ほとんどのコードは素直に書くことができたが、「2の補数」の扱いに苦労した。Pythonは動的型付けなので符号付き8ビット整数を明示的に宣言できないことが災いした。I2Cを使うような低レベルなモジュールでは、各種センサ数値は8ビットにつき1つのレジスタアドレスを割り当てるので、8ビットを超えるようなデータはユーザが逐一読み取りと結合を行う必要がある。

例えばこのIC【L3GD20H】では、X軸回りの角速度(signed 16bit int)は2つのレジスタOUT_X_L (28h)OUT_X_H (29h)に分割して格納されており、OUT_X_Lが下位8ビットでOUT_X_Hが上位8ビットである。ユーザはまず(OUT_X_H << 8) | OUT_X_Lを求め、さらにこのビット列のMSBが1の場合、ビット列を2の補数として解釈しなければならない。この2の補数として解釈する処理が非常に面倒だった。静的に型が付けられるような場合は、あらかじめ16ビット符号付き整数として宣言した変数にビット列を投げ込めばよいのだが、Pythonは勝手に32ビットに拡張するので符号が付かない。

いろいろググって結局次のようなコードになった。0xffffとXORするというのは考え付かなかった。

dataLow = smbus.SMBus(self.channel).read_byte_data(self.address, 0x28)
dataHigh = smbus.SMBus(self.channel).read_byte_data(self.address, 0x29)
if dataHigh & 0x80 == 0x80: # If MSB is 1
  data = - ((dataHigh << 8 | dataLow - 1) ^ 0xffff)
else:
  data = (dataHigh << 8) | dataLow
return data

気圧計

海面気圧と現在気圧が分かれば高度を求めることができる。家で発見したSparkfun製のモジュールを利用した。おそらくこれもスイッチサイエンスで購入したもの。今はもっと使い易いモジュールが出ているはず。

www.sparkfun.com

このテのモジュールには割とよくある話だが、気圧を計測する前に色々と面倒な処理が必要だ。工場出荷時のキャリブレーションデータをまず読み出し、そして生の気圧センサの値を読み取り、よくわからない校正処理を行う。ここでも2の補数が登場するので厄介だった。

f:id:Windymelt:20150525214641p:plainよくわからない校正処理はこちら。

ソケット

取得したメトリクスはソケット経由で操作用端末で走っているProcessingが取得し、各種の描画を行う。そのうちWebカメラとか付けて遊びたい。

GPS

現在位置を知るために秋月電子通商GPSモジュールを購入。ところがうまく動かない。

akizukidenshi.com

シリアルポートとして認識こそしているものの、全く文字が送られてこない。GPS電波を受信していないのではないかと疑ったりもしたが、仮にそうだとしても何らかの情報は出て来るはずだ。baud rateも設定済みなのでモジュールの機嫌の問題だと思っている。ごくまれに突然受信してNMEAフォーマットの文字列が吐き出されるのだが、思い通りに動かないのが悲しい。GPS電波を受信し、GPS衛星情報を取得すればインジケータランプが点滅する筈だが、ずっと点灯したままだ。

GPSデータの処理はgpsdを使う。sudo gpsd /dev/ttyACM0などと打てばデーモンが走り、各種のプログラムからライブラリを介して情報を取得できるようになる。Pythonでの扱いはhttp://www.stuffaboutcode.com/2013/09/raspberry-pi-gps-setup-and-python.htmlなどを参考にした。

加速度・地磁気センサ

これもおそらくスイッチサイエンスで買ったもの。モジュールが1.8Vを利用するのでI2Cも1.8Vプルアップで利用しなければならない。Raspberry Piをはじめとして他のモジュールは3.3V駆動なので現在接続できない。素直にI2Cレベル変換モジュールを買うか、FETやバイポーラトランジスタで変換する*2しかない。

今回はここまで。また進捗があったら書きます。