最近の優秀なセンサーなら地震計作りは簡単そう?とはいえ東西、南北、上下の加速度を50分の1秒以下の単位で、常時正確に記録する装置は工夫のし甲斐がありそう。色々考えたらついハマってしまい、少しずつチャレンジすることにしました。
机上の実験回路で、X、Y、Z方向に軽く揺らすのは意外に難しいものですね^^;
さて、これをArduinoで作る構想が固まり試作回路でのテストを終えた段階です。
この地震計では、開始から終わりまで5分以内の地震の記録を初期微動の前から終わりまで連続3回分は逃さず取れるように考えています。地震があった際はLED表示でわかるようにし、2つ目の地震が来る前までに使った記録媒体1個を交換するか、3つ目の前までに2個を交換することで、いくらでも取れるという方法です。もちろん稼働状態のままで交換できるように考えていますが、万一交換前に4つ目がきてしまったら?1個目の記録が上書きされます?、いやいやローコスト(1つ200円ほど)の記録媒体なので、もっとつないでおけばよいかな?・・^^;
回路は次のように考えました。毎度汚い手書きですみませんが。
左上のPICで正確な20.00mSを作って測定のトリガーにしています。右上の3つは1024KbitSRAM、1個あたり1024x1024ビット=131,072バイトのシリアルRAMです。最終的にはそれぞれボタン電池でバックアップしとり外せるように作ります。つまり書き込み中の1つを避ければ運用中の交換ができるようにする予定。
そのため地震を記録するまでは同じRAMに上書きし続けます。地震が終わったら終了時刻を記録して次のRAMへと移ります。それにより地震の始まり時刻も分かるように記録できます。回路としては上図のままで、I2C接続にRTC(リアルタイムクロック)も追加するわけですが。
まず、プログラムしたPICの出すトリガー信号を確認すると正確な50.00Hzになっています(較正済オシロの写真右下)。
地震計は種類によって記録の対象が揺れ幅、速度、加速度の3種類あるようですが、前の2つは大型になるため難しそう。ところが、建築などに使われる定番の実用地震波データは、20mS単位の縦横上下の加速度(単位:gal ガル)になっています。よって作成の簡単な加速度型だけを考えます。
現代の3軸加速度センサーは超小型なのに測定は精密で正確です。ためしに鉛直軸を測るとどの軸でも正確な1G(約981ガル)が正しく計測されるのに驚きます。スマホに使われて発達したようですが、中に使われているマイクロマシン技術の高さが推察されます。手持ちの加速度センサーICのブレークアウトモジュールは次の4種で、いずれも簡単にI2C接続できるものです。世界にはもっともっとたくさんの種類が出ています。
この中で左下の種類だけは3軸の回転加速度用のジャイロなので使えません。どれもセットアップとして細かい設定が必要です。試しにMPU6050とLSM6DS3を比較してみた結果では、LSM6DS3の方がノイズが小さく、演算すれば有効数字4桁近くの正確なガル値が取れるようなので、これを使ってみることにします。
この場合はブレークアウトモジュールに3.3Vへのレギュレータと信号電圧変換ICが搭載されていますので、電圧は5Vを直接接続できます。
ブレッドボードで次の様に試作しました。
ほぼどのセンサー用にも、汎用のArduinoライブラリーが数種あるようですが、正しく使うには詳しいデータシートとアプリケーションノートを読む必要があります。厚い(合計200頁ほど)のですが、必要な個所を全て読んだらライブラリーを使う必要性がなくなります。I2Cで直接扱うことができるので資源が大幅に節約されます^^;また、好き勝手に使えることで、Arduinoの通常のLoop1サイクル内での測定と記録が悠々と間に合います。
シリアルRAMもライブラリーがありますが、このSPIはそれを使わずに手で書いてもごく単純にできます。SPI設定のDefaultもATmegaと同じだし、Microchip社製品だけあって電圧範囲も5Vまでが広く許されており助かります。
プログラム等の作成方法を含めて、これから何回かにわけて説明して行こうと思います。
とりあえずこの試作状態で、期待通りにきちんと動かすことができましたので、次にLoopのタイミング測定結果を示します。以下、ロジックアナライザーの写真が見えにくい時は写真の上でクリックしてください。
ロジックアナライザーの各チャネルは次のとおりです。
1)I2C接続(A4,A5)
チャネル1:SCL
チャネル2:SDA
2)SPI接続(D11,12,13および使用CSの接続先)
チャネル3:CS(Chip SelectまたはSlave Select)
チャネル4:SPIクロックSCK(ここでは4MHz)
チャネル5:MOSI(Master-Out Slave-In)
チャネル6:MISO(Master-In Slave-Out)
3)Arduino Loop内処理時間
チャネル7:Loop中の空き時間(トリガー待ちの余裕時間)を出力するテスト端子です。
ちょっと余談ですが、このためにdigitalWrite命令でCPUサイクルをかけたくないですから、筆者の常套手段として待ち命令の上下をExclusive ORで挟むことで、ピンを機械語1命令で直接反転させます。まさかと思われるかもしれませんがArduinoではdigitalReadもdigitalWriteも結構CPUサイクルがかかります。つまりトリガー待ち時間がオーバーヘッド最小で計測できるようにしてあります。これで、Arduino Loop内処理にどれだけ時間がかかり、どれだけ待ち時間があるのかが一目瞭然です。この例では次のようコーディングしてあります:
#define Timing 16 // Timing signal(L) at A2=D16
#define testSig B00000100 // test signal at D2 pin
// Wait for 20mS time-trigger (LOW for 50 microseconds)
PORTD = PORTD ^ testSig; // Reverse test signal
while (digitalRead(Timing) == HIGH) {}
PORTD = PORTD ^ testSig; // Reverse test signal
// time to wait for trigger measured at D2 Test pin
測定結果を見ると、今回の試作では20mS単位の処理ならArduinoのLoop処理のなかで余裕しゃくしゃくで処理可能なことが分ります。もちろんプログラミングでは他にもいくつかの工夫をしていますが、回をあらためて説明したいと思います。
さらに短い単位で測定をすることも十分可能ですが、そうするとSRAM1つの記録時間が減ります。地震は最長せいぜい4分のようですが、このしかけですとSRAM1つに5分20秒以上記録できます。とはいえ地震計の記録としては50Hzのサンプリングで大丈夫なので、Simple is the best、これで進めることにします。地震のこない時は1つのSRAMにラップラウンドで書き続け、地震があればその記録と時刻表記は1つのSRAM内に収まり、次のSRAMに書き始めるようにします。
センサー読み込み部分の測定結果を詳しく示すと次のようになっています。
デバイスからのバイト受け取り順序はLSM6DS3のアプリケーションノート(最新版ではAN4650.pdfの102頁中の31頁)Table18に書かれているとおりになります。符号付の値が2バイトにわかれているため、受取順序をビッグエンディアン(方法は3.5.1Big-little endian selection参照)に指定しても、負の場合の値のとりこみには少し工夫が必要です(送出時に上位を右シフト演算する場合ならArduinoでは符号が維持される約束ですが、受信で左シフト演算して下位バイトを加える場合にはそうはいきません。これを間違えると誤った値になります)。いずれどこかの回で説明したいと思います。
SRAM書き込み部分を拡大すると次です。
さらに拡大するとクロックが0.25µ秒周期で、正確な4MHzで動いていることが分ります。
試作では3つのSPIデバイスを浮遊容量の大きいブレッドボード上でつないでいますから、4MHzは少し厳しいかなと思いましたが、なんと全然問題なく動いています。もっとつなぎたいときは、これを1MHz以下に落としても処理タイミングの上では十分にいけますね。
この仕組みでは地震の判定は3軸の平方和の平方根で行いますが、常時連続記録をしているので地震発生の判定は必要なく、地震終了の判定だけが必要です。
加速度データは最初に多数回を測り、以後は各軸をその平均値で相殺することにより地震波だけにしています。器械をきちんと固定した場合には各波の中心がゼロガルになるわけですが、机上の簡単な実験では微妙に動くのでそうはいきません。
簡単なテストの記録ではZが2ガルほど上にあります。詳しく見るとどの軸も2ガル程度のノイズ(か常微動?)があるらしいことがわかります。とりあえずは1ガル単位で記録していたデータなので今後さらに詳しく見ていきたいと思います。
2019年11月3日以後追記:
ノイズ(?)を調べるために次の3つのことをやってみました。①記録を0.1ガル単位に変更、②相殺用の初期値取得間隔を多少長めに変更 ③テスト装置を安定した台に置く。
その結果は次のグラフです。
各軸ともほぼ±1ガル未満の小さくて周波数の高い振れですが、近くの道路を自動車が通ると幅が増えたりします。よって常微動(常時微動)の影響が無視できないと気づきました。テスト中の工作室は2X4木造の3Fにありますから当たり前かも。
1ガル未満の弱い地震まで確実に記録するには、適切な据え付け場所をえらばないといけませんね。本番用を作ったらコンクリートのテラスなどに設置して試そうと思います。
なお、このセンサーの仕様は分解能0.03ガルのようで、正しく使えば0.1ガル単位で記録しても信用できそうです。最大2Gの地震でも1961.3ガル、記録の単位を10倍にしても値は2バイトに収まりちょうどよい感じです。
その後さらに少しずつテストしてみた結果、ODR(出力周波数)とAntiAliasなどの設定の効き目が顕著(もちろん仕様どおりですが^^;)と確認できました。設定を最適にして20mSの1ループで1度だけ測るのがやはり的確という結論になりました。
今後の進捗ペースにあわせて(時間があるときのマイペースですみませんが)、センサーへのパラメータ、SRAMの使い方などプログラム全体を少しずつ説明して行きたいと思います。今回はこのへんで。
©2019 Akira Tominaga, All rights reserved.