加速度計が動かない、GPSが喋らない
Raspberry Piで無人飛行機を作るプロジェクトを勝手に一人で始めたのだけれど、まずは各種メトリクスの収集が必要なのでセンサモジュールを購入して弄っている。
前回の記事はこちら。
ジャイロモジュール
飛行機の回転を検出するジャイロセンサモジュールはスイッチサイエンスから購入。
I2Cを叩くと素直に動く。Raspberry Pi 2でI2Cを弄るにあたって『最近の Raspberry Pi で I2C を有効化する方法 - Rabbit Note』あたりを参考にした。I2Cの実際の操作はPythonでSMBusというライブラリを使った*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製のモジュールを利用した。おそらくこれもスイッチサイエンスで購入したもの。今はもっと使い易いモジュールが出ているはず。
このテのモジュールには割とよくある話だが、気圧を計測する前に色々と面倒な処理が必要だ。工場出荷時のキャリブレーションデータをまず読み出し、そして生の気圧センサの値を読み取り、よくわからない校正処理を行う。ここでも2の補数が登場するので厄介だった。
よくわからない校正処理はこちら。
ソケット
取得したメトリクスはソケット経由で操作用端末で走っているProcessingが取得し、各種の描画を行う。そのうちWebカメラとか付けて遊びたい。
GPS
現在位置を知るために秋月電子通商でGPSモジュールを購入。ところがうまく動かない。
シリアルポートとして認識こそしているものの、全く文字が送られてこない。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しかない。
今回はここまで。また進捗があったら書きます。