気圧高度計(MS5611)をArduinoで使ってみた その1

前回までに以下の様な基板を作っていました。

MPU-6050基板作ってみた(前半)基板設計

MPU-6050基板作ってみた(後半)リフローしてみた

これは加速度ジャイロ地磁気、更に気圧計を載せて10軸の情報を得られるものです。ロケット姿勢・位置の計測用に使う予定です。当初の予定では秋月電子にも売っているMPL115A2というセンサを使う予定でしたが、さらに高精度な気圧計があるということでピンコンパチなこともあって、そちらのセンサを試してみました。

measurement社のMS5611-01BA03というものです。系列としては秋月電子などにモジュールとして売られているパララックス社高度計測モジュールに載っている気圧高度計のセンサ(MS5607)の次世代バージョンのものになります。

高分解で10cmまで測れると宣言していて本当かよ、とにわかに信じがたいので実際の動作を見てみました。

マイコンはArduinoでI2Cで接続しています。SPIでも繋げられるのでSPIの方が良さそうですが、今回の基板がそもそもMPU-6050というI2Cで繋がる基板への追加部品ということでI2Cでつなげています。

写真のように、5VのArduinoと繋がるようにセンサボートの前にI2Cのレベル変換モジュールを入れています、そしてSDカードに記録するために抵抗分圧で3.3Vで駆動するSDカードとつなげています。SDカードはArduinoにライブラリがあるのでそのまま使いました。すごくお手軽にうごくので嬉しいです。

MS5611でも秋月に売っているパララックス社の高度計測モジュールでも動くライブラリは存在しますが、センサがどのように動いているか理解のために自分でコード書いてみました。

Arduinoの既存のライブラリとしては

パララックス社が公開しているものFreeIMUを作っている方のブログに公開されているもの

があります。他にもmbedのライブラリとしてセニオネットワークさんが作っておられるライブラリとサンプルがあります。このmbedのライブラリはプロの仕事なので抽象度も高くキレイにまとまっていて勉強になります。

サンプルライブラリ

上のライブラリの方がオススメですが、自分で作ったものも公開しておきます。今回はシリアル通信でPCに表示させるところまでです。このあと、ログをSDカードに保存したり、生データにフィルタをかませたり、加速度ジャイロと合わせたりします。

/*
MS561101BA用スケッチ
MS5607でも使えるはず(たぶん)
I2Cでセンサデータを取得し、シリアル通信でPCに表示
by ina111
2012/07/16
*/

#include <Wire.h>

//気圧計のアドレス
#define MS5611_ADDR 0x76 //CBR =HIGHの時は0x76,LOWの時は0x77
//#define MS5607_ADDR 0x76

//気圧計で使う変数
uint16_t C_[6] ={40127, 36924, 23317, 23282, 33464, 28312}; //初期値
uint32_t D1=0,D2=0;
int32_t dT,TEMP=0;
int64_t OFF,SENS;
int64_t T2,OFF2,SENS2;
int32_t P=0;
int32_t Height;

unsigned long now;                   //現在時間を入れて変換時間を計算
unsigned long lastD1Conv,lastD2Conv; //最後に変換した時間micros()
unsigned long ConvTime = 10000;      //変換時間[マイクロ秒]
boolean SWD1Conv = true, SWD2Conv = true; //D1,D2どっちを処理しているか
boolean SWD1D2 = true;               //trueでD1の処理,falseでD2の処理

void setup(){
  Wire.begin();
  Serial.begin(9600);
  //Serial.begin(115200);
  delay(100);
  readPROM();
}

void loop(){
  getD1();
  getD2();
  getPressTemp(D1,D2);
  getHeight(P);

  Serial.print(millis());Serial.print("\t");
  Serial.print(TEMP);Serial.print("\t");
  Serial.print(P);Serial.print("\t");
  Serial.println(Height);
}

/*
 * func name  : getD1,getD2
 * processing : MS5611の生データD1,D2を取得
 * param      : 
 * summary    : 後述のstartConvとreadADC使用
 *              変換の時間前だと変換、変換後なら読み出しを行う
 *              D1とD2は交互に読み出されるようにスイッチしている
 * return     : 
 */
void getD1(){
  now = micros();
  //SWD1D2==trueだとD1,falseだとD2
  //SWD1Conv==trueだと変換、falseかつ時間経過後は読み出し
  if(SWD1Conv == true && SWD1D2 == true){
    startConv(0x48); //D1のとき0x48,D2のとき0x58,OSRによって変化
    lastD1Conv = micros();
    SWD1Conv = false;
  }else if(now - lastD1Conv >= ConvTime && SWD1D2 == true){
    D1 = readADC();
    SWD1Conv = true;
    SWD1D2 = false;
  }
}

void getD2(){
  now = micros();
  if(SWD2Conv == true && SWD1D2 == false){
    startConv(0x58); //D1のとき0x48,D2のとき0x58,OSRによって変化
    lastD2Conv = micros();
    SWD2Conv = false;
  }else if(now - lastD2Conv >= ConvTime && SWD1D2 == false){
    D2 = readADC();
    SWD2Conv = true;
    SWD1D2 = true;
  }
}

/*
 * func name  : getPressTemp,getHeight
 * processing : MS5611の生データから温度TEMP、気圧P、高度Heightを計算
 * param      : ADC1,ADC2    / getD1,getD2で得られたD1,D2
 *              hPa          / getPressTempで得られたPをhPaにしたもの
 * summary    : MS5611のデータシートによる計算,と高度気圧式から線形化
 * return     : 
 */
void getPressTemp(uint32_t ADC1, uint32_t ADC2){
  dT   = (int32_t)(ADC2 - ((int32_t)C_[4] << 8));
  TEMP = 2000 + ((dT * (int64_t)C_[5]) >> 23);
  OFF  = (((int64_t)C_[1]) << 16) + (((int64_t)C_[3] * dT) >> 7);
  SENS = (((int64_t)C_[0]) << 15) + (((int64_t)C_[2] * dT) >> 8);
  P    = ((ADC1 * SENS) >> 21) - OFF >> 15;

  if (TEMP < 2000) {
    T2    = (dT * dT) >> 31;
    OFF2  = 5 * (TEMP - 2000) * (TEMP - 2000) >> 1;
    SENS2 = 5 * (TEMP - 2000) * (TEMP - 2000) >> 2;
    TEMP = TEMP - T2;
    OFF  = OFF - OFF2;
    SENS = SENS - SENS2;
  }  
}

void getHeight(int32_t hPa){
  //Height = -938.502 * hPa/100.0 + 948697; //t0=30[deg]で1000mまでの線形近似
  float t0 =30.0;float P0 = 1013.25;
  Height = 153.8*(t0+273.2)*(1-pow((hPa/100.0/P0),0.1902));
}

/*
 * func name  : startConv,readADC
 * processing : MS5611の内部ADCの変換開始関数
 *              変換後OSRの時間はアクセス不可
 *              ADCの結果を読み込む関数。returnでuint32_tが出てくる
 * param      : command    / D1,D2,OSRによってアドレスが異なる
 *                         / OSR(Over Sampling Ratio)             
 * summary    : startConv(command) -> delay(10) -> readADC()
 *              変換コマンドを送信
 *              値呼び出しコマンドを送信、受信
 * return     : 
 *              conversion    / ADCした値.D1,D2のこと
 */
void startConv(uint8_t command){
  Wire.beginTransmission(MS5611_ADDR);
  Wire.write(command);
  Wire.endTransmission();
}

uint32_t readADC(){
  uint32_t conversion = 0;
  // start read sequence
  Wire.beginTransmission(MS5611_ADDR);
  Wire.write(0x00);
  Wire.endTransmission();

  Wire.beginTransmission(MS5611_ADDR);
  Wire.requestFrom(MS5611_ADDR, 3); //3byteリクエスト
  if(Wire.available()){
    conversion = Wire.read() * 65536 + Wire.read() * 256 + Wire.read();
  }
  return conversion;
}

/*
 * func name  : readPROM
 * processing : MS5611の工場校正値を読み込み
 * param      : 
 * summary    : C_[i]に0~5読み込む(C1~C6とは一つズレている)
 * return     : 
 */
void readPROM(){ 
  for(int i=0; i<6; i++){
    Wire.beginTransmission(MS5611_ADDR);
    Wire.write(0xA2 + i*2); //PROMの最初 データシートでは0xA0に見えるが0xA2から   
    Wire.endTransmission();

    Wire.beginTransmission(MS5611_ADDR);
    Wire.requestFrom(MS5611_ADDR,2);
    if(Wire.available() >= 2){
      C_[i] = Wire.read() * 256 + Wire.read();
    }
  }
}

 

人力飛行機が飛ぶところを360度カメラで撮ってみた

正確には自分はカメラを貸しただけで『撮ってもらった』ものです。

googleストリートビューみたいな360度方向が見れるものが大好きで胸がワクワクします。ストリートビュー見ていて一日が終わったとかそういう感じで毎日を過ごしています()。そんなこともあってソニーのカメラでBloggieという360度レンズを付けることのできるカメラを持っています。


http://www.sony.jp/bloggie/

ソニー公式サイトの作例もあるように、360度動画の画質はかなり悪いです。ナチュラルモザイクな雰囲気で怪しげな動画が撮れます(笑)。

今回は人力飛行機の方のサークル(東京工業大学”Meister”)の後輩にお願いして、鳥人間コンテストに向けて最終調整している試験飛行の様子を動画に撮ってもらいました。動画はソニー純正の画像ソフトPMBというソフトを使うことで、マウスを動かすとそっちの方向を向くことが出来る360度動画を作ることができます。PMB上でマウスグリグリして遊んでいるところをキャプチャーして動画にしてみました。エンコードやyoutubeにアップロードしての画質の劣化は最小限にしました。撮影の段階でこの程度のモザイク画質です。

まるで自分が(視力が悪い状態で)パイロットになったかのような迫力のある動画ができて楽しいし、飛行の軌跡もわかります。何かトラブルがあった場合も検証用動画として有効じゃないかと思いました。

 

 

ダイダロス研究その2

以前に飛行距離世界記録を記録した人力飛行機のDaedalusについてのことをまとめていました。

ダイダロス研究

そのDaedalusの当時の記録映像が「The Light Stuff」(映画の「The Right Stuff」が元ネタ笑)っていう題名でまとまっていてyoutubeに上がっていました。
面白かったので止まってしまった前回の更新を引き継ぐ形でまとめておこうかなと思います。

元映像



 

記録飛行

1988年4月23日にギリシャのクレタ島を出発して飛んでいるDaedalus。美しい飛行機は性能がいいという言葉の通り、かっこよく綺麗に飛んでいます。

出発の瞬間。滑走路に沢山の人が集まってお祭り騒ぎのようです。

飛び出しも横顔もため息出るほど美しい。

パイロット

オリンピック出場クラスの人を5人集めて正式なパイロットにしました。世界記録を狙うにしても贅沢な話です。

パイロットがどのぐらいの出力と時間焦げるのか、出力、酸素量、心拍数を計測したようです。

設計

マーク・ドレラ先生によってこのプロジェクトのためにXFOILとXROTORというソフトが作られ、設計に生かされました。XFOIL(XFLR5)やXROTORについてはこのブログでいくつか記事書いています。

XFOILは低レイノルズ数領域での翼型の解析ソフト。XROTORはプロペラの設計ソフト。Daedalusプロジェクトはパイロットを豪華にするだけではなく、合理的な設計にするための工夫がすごく多いのが自分の中の魅力です。

制作

カーボンのシート(CFRPのプリプレグシート)を芯に巻きつけているところ。手に付いている油がつかないように手袋して丁寧に貼っているのがわかります。この後樹脂が硬化する温度まで焼いて主翼の1次構造材にしているはずです。1980年代になって初めて産業用として使われたCFRPを使っている、当時としては最先端を行く構造設計です。

飛行機の格納庫で制作している様子。日本の鳥人間のチームと違って広々作業しているのがわかります。

当時としては新しい技術なのかわからないが、翼の2次構造材であるリブの材料である発泡剤はコンピュータ制御の熱線で切り出しているようです。CNCのワイヤーフォームカッターというジャンルになると思います。必要なところには人と手間をかけて、省力化できるところは省力化するっていう(その技術力と)合理的な考え方が素敵です。

CNCフォームカッターで切った翼型の発泡材は治具を作って丸鋸でスライスしているようです。日本の鳥人間チームからすると珍しいかと思います。

主翼が必要な荷重に耐えられるかどうかの試験をしている様子。主翼を逆さまにぶら下げてペットボトルで揚力の代わりにしています。

足を漕いだ時の根本になるクランクを繋げるボトムブラケット。これも軽量化を極めるようなアルミニウム合金を使って十分な剛性があるようなギアボックスにしているようです。

プロペラを取り付ける部分(プロペラハブ)。カーボンを多用し軽量化に務めているのがわかります。

手で回してみて駆動系の動きを確認している。

マークドレラ先生が(ラフな格好で笑)プロペラの取り付けをしているところ。XROTORというソフトを作って設計していたみたいです。その解説などこのブログで以前に書いています。

駆動系とプロペラを合わせて回転試験をしているところ。音や振動などで駆動系とプロペラが正常かどうか判断しているのだと思います。

主翼と胴体をくっつけている部分。荷重的に一番シビアになる部分でここの構造も面白いです。

試験飛行をしているところ。砂漠地帯で広々行なっています。

設計変更で主翼の長さを伸ばすために最外の翼を付け替えられるようにしたようです。

主翼の表面あらさによって性能が変わるからだろうか、リブ部分が多少膨らむからだろうか、主翼の表面の前縁材をヤスっています。

接着剤の量も厳しく軽量されていて、刷毛で丁寧に塗っています。

フライトコンピュータを設置しています。超音波高度計やケイデンス計などを搭載してたようだが、試験飛行だとさらにセンサーを増やしているようです。

足回り。狭いようだが、透明フィルムによってパイロットの視界は十分に確保されいるようです。

試験飛行

試験飛行で一度大きなクラッシュをした。危険なクラッシュだったが、パイロットには大きな怪我はなかったようでした。これによって多少の設計変更を迫られたようです。

パイロットには心拍数を測れるようにしています。エンジンのチェックをしているようなイメージでしょうか。

記録

記録本番。風の弱い日を待ってのフライト。

ボトルいっぱいの特別なカロリーなどを調整したドリンクを積んでいます。4時間の運動に耐えられるように専門家が考えて調合しているようです。論文も出ています。

船で追いかけつつ、軍艦が周りにいるところを飛んだりしながら到着予定のサントリニ島に到着したが、目前になって横からの突風によって桁が折れて墜落しました。

記録を求める機械構造物はその役目が終わった瞬間に崩れるぐらいの攻めの設計製作が究極(良いかどうかは知らないが)だと言われるが、まさにその通りの結果になったことも含めて、ドラマチックな世界記録です。

昔、所属サークルで擦り切れたVHSでこの動画を見たような記憶があるのですが、改めてキレイな動画を見ると、ダイダロスプロジェクトが当時としては最先端で合理的で人的・資金的資本を存分に投入した興味深いプロジェクトなのがよくわかります。

リンク

http://web.mit.edu/drela/Public/web/hpa/

Mark Drela先生のホームページですが、ここの中のPDFが非常に綺麗にまとまっています。ここにあるものを読むとだいたい人力飛行機の考え方とか勉強になるかと思います。このブログの記事も多くをこれから引っ張ってきたものです。

 

 

就活思い出し1

就職活動っていう「一生を決めるイベント」とも「茶番で不毛な時間」とも取れるのを去年12月頃から5月頃までしたのでその思い出のまとめを忘れないように書き留めておこうと思います。

特に誰に対して有意義な記事にしようとか、どこかの企業を陥れたいという意図は全く無くて、ただ単に個人的な思い出です。受けようと思った企業は適度に悩んだ末に、自分の人生をかけても良いと思えるような企業だと思って受けました。それに、このブログに書こうと思ったのも、それぞれ自分の意識を変えるほど大きく影響を受けた”人”や”製品”があるところを名前上げてみたいと思ったまでです。自由応募では全滅だったので失敗談として書くつもりです。

続きを読む

AVRライターでArduinoのスケッチを書き込む

 

組み込みのプログラムはArduinoやってて、それ以外のマイコンを勉強するのは面倒くさくて、でも小さいマイコンを安く使いたいなぁというズボラでケチな発想で色々いじったことの自分用メモです。

Arduinoはいいんだけど大きすぎるということで、表面実装のATmega328-Pを使いたいと考えています。Arduino miniだかproだかを買えばすごく簡単だけど、値段が高いのでただのチップにAVRライターで書き込もうと考えました。

  1. AVRにブートローダだけライターで書き込んで、USB-シリアル変換基板でプログラムは書き込むという方法
  2. ライターだけでArduino IDEを使って書き込む。

 

1の欠点は変換基板買わないといけないし、外にシリアル変換基板と繋げやすい配線つくらないといけないのがめんどくさい。2には欠点はないと思ったのが大間違い、いくつかひっかかった。

 

ブートローダの書き込み

この記事の最後に書いてるやり方だとブートローダは必要ないけど、手続きがほぼ同じなのでまとめておきます。

AVRにArduinoブートローダーを焼き込み成功までの過程」「ATMEGA328P の Arduino化まとめ」「本家」とか参考にしました。ただ、チップが違ったりソフトがAVR Studioから新しいAtmel Studioになってたりするので変更部分だけまとめ。

Atmel Studio 6を起動して、「ツール」→「Device programing」。左上の「Tool Device Interface」をそれぞれ「AVRISP mkⅡ Atmega328P ISP」に設定。Apply押すと画面のようなものが出てくる。書き込み速度などはいじらず、ブートローダを書き込みました。ヒューズはチットと設定によって変えなければならないが、今回はAtmega328-Pの最初のままのものにしましした。

EXTENDED:0xFD
HIGH:0xDA
LOW:0xFF
Lock bits:0xFF

ライターを使ってArduinoIDEから書き込めない

Arduino IDEで書いたスケッチ(プログラム)はライターを使って「書込装置を使って書き込む」でOKだと思ったら、「avrdude: usbdev_open(): did not find any USB device "usb"」というエラーを吐いてしまう。Atmel Studioで使っているAVR ISP mk2のドライバとArduino IDEで使っているドライバが違く、しかも共存できないのが原因でした。しかも自分の環境だとArduino IDEの方のドライバを認識してくれないというトラブルがあって、方針変更しました。参考:「AVRISP mkII とAVR StudioとArduinoIDE

Arduino IDEでスケッチを書き、書き込み用のファイルであるHEXファイルを出力させてAVRライターを使ってAtmel Studioで書き込む。

HEXファイルの出力とライターで書き込み

Arduino IDEからHEXファイルを作るためには以下を参考にさせてもらった。

Arduinoのスケッチを買ってきたマイコンに書き込む

Arduino1.0だとC:\$$!User]\AppData\Roaming\Arduino\preferences.txtに設定ファイルがあるのでそのtxtファイルに

preproc.save_build_files = true
build.path = build

と追記した。変更したら、Arduino.exeがあるフォルダにbuildフォルダを作る。フォルダ作り忘れるとIDEでエラーが出る。

ここまでくれば簡単で、Ardino IDEでターゲットとなるマイコンボードの種類と書込装置の設定を確認して、コンパイル(「検証」ボタン)するとArduino.exeの中のbuildフォルダに沢山のファイルができる。この[プロジェクト名].cpp.hexファイルをブートローダを書き込んだのと同様に「ツール」→「Device Programming」→「Memories」の中のFlashに書き込むHEXファイルを参照して「Program」ボタンを押す。

これで無事動きました。

先にブートローダのことを書きましたが、この方法だとブートローダは必要無いです。色々と遠回りをしてるような気がして滅入りぎみ・・・