« Googleのエイプリルフールネタだった”物理フリックキーボード”のキット販売 | トップページ | バッテリー不要で電波のみで動作するIoT用超小型コンピュータ「WISP」 »

2016年4月30日 (土)

Raspberry Piで”地震計”作ってみた

この度発生した熊本地震ですが、心よりお見舞い申し上げますとともに一日も早く余震がおさまり復興されることをお祈り致します。

私も住む愛知県も近いうちに大地震に見舞われる危険性が高いとずっと以前から言われてますし、地震国日本に住む限りは決して他人事ではありません。

この地震を受けて、iPhoneで震度を測定できるアプリが無料で提供されておりますが。

6/15まで、iPhoneを震度計に『i震度』が無料配布中・使い方を考える #震災支援

iPhoneでできるくらいなら、Raspberry Piでもできるんじゃないかと思った次第で。

以前6軸加速度&ジャイロセンサー”MPU6050”を購入していたので、これを使って地震計を作れないか、やってみました。

Img_0342

買ったばかりのRaspberry Pi 3を使おうかと思ったんですが、そういえば常時テレビ録画待機で電源つけっぱなしにしているRaspberry Pi B+があるじゃないかと思い

20160426_20_53_01

これを使うことにしました。

mpu6050は

VCC - 1pin

GND - 6 pin

SCL - 5 pin

SDA - 3 pin

に接続。

以下のようなpythonのコード(以下”sindo.py”)を組みました。

# -*- coding: utf-8 -*-
#!/usr/bin/python

import smbus
import math
from time import sleep
import datetime
import logging

# slave address
DEV_ADDR = 0x68         # device address
# register address
ACCEL_XOUT = 0x3b       #
ACCEL_YOUT = 0x3d
ACCEL_ZOUT = 0x3f
TEMP_OUT = 0x41
GYRO_XOUT = 0x43
GYRO_YOUT = 0x45
GYRO_ZOUT = 0x47
PWR_MGMT_1 = 0x6b       # PWR_MGMT_1
PWR_MGMT_2 = 0x6c       # PWR_MGMT_2

bus = smbus.SMBus(1)
bus.write_byte_data(DEV_ADDR, PWR_MGMT_1, 0)

buffa = 0.0
v = 0.0
#
# Sub function
#
# 1byte read
def read_byte(adr):
    return bus.read_byte_data(DEV_ADDR, adr)
# 2byte read
def read_word(adr):
    high = bus.read_byte_data(DEV_ADDR, adr)
    low = bus.read_byte_data(DEV_ADDR, adr+1)
    val = (high << 8) + low
    return val
# Sensor data read
def read_word_sensor(adr):
    val = read_word(adr)
    if (val >= 0x8000):
    # minus
        return -((65535 - val) + 1)
    else:
    # plus
        return val

logging.basicConfig(filename='sindo.log', format='%(levelname)s : %(asctime)s %(message)s',level=logging.INFO)

while True:
    for i in range(1,15):
       x = read_word_sensor(ACCEL_XOUT) / 16384.0 * 980.665
       y = read_word_sensor(ACCEL_YOUT) / 16384.0 * 980.665
       z = read_word_sensor(ACCEL_ZOUT) / 16384.0 * 980.665
       u = math.sqrt(x**2 + y**2 + z**2) - 1071.0
       v = v + u
       sleep(0.02)

    w = math.fabs(v / 10.0)
    v = 0.0

    if w > buffa :
       buffa = w
       logging.info(str(w))

    if w > 400 :
       logging.warning('震度 7 : '+str(w))
    elif w > 250 :
       logging.warning('震度 6 : '+str(w))
    elif w > 80 :
       logging.warning('震度 5 : '+str(w))
    elif w > 30 :
       logging.warning('震度 4 : '+str(w))

    sleep(0.01)


ほとんどmpu6050のサンプルコードを流用してますが、出力値をgal(ガル=cm/s^2)に変換しております。

気象庁の震度測定算出法は以下のサイトにありますが。

気象庁 | 計測震度の算出方法

まず3軸の加速度データをフーリエ変換して周波数ごとに分解、これを3種類のフィルタにかけて逆フーリエ変換し再び時系列データに戻す、0.3秒間ある値以上となる加速度をもとめ、この加速度aを使って次の式(2 log a + 0.94)に代入して、出てきた値から震度を求める(5.2なら”震度5強”、5.6なら”震度6弱” など)・・・

ってそんな複雑なことできるんか!?

ということで、以下を参照にもう少し簡易な判断基準を用いました。

地震の大きさを表す単位

やや古い基準の震度判定(震度5強といった呼び名がない時代)ですが、こちらならgalをそのまま震度に置き換えられます。

ただし、フィルター無しの加速度データの最大値だけで判断すると過剰な震度表示になるため、0.3秒おきの平均値で判断してます。

それでも若干過剰判定気味。あくまでも揺れが起こった時間と、その程度を把握する簡易なものとお考えください。

3軸加速度の合成値で加速度を判定。”1070”を引いてますが、これは重力加速度+αの影響を引いてます。

ところでこのmpu6050、無振動状態でも±20 gal程度の値を返してくるため、震度3以下が判定できません。30 gal以上の値で震度4以上を判定させてます。

早速コマンドを実行します。

sudo python sindo.py &

後ろに”&”をつけて、バックグラウンド実行。

実行したディレクトリ上に”sindo.log”というファイルができるはずです。これをテキストエディタで開くとこんな感じ。

Img_0583

わざとRaspberry Pi B+ごとゆすって俺的地震でテストしてみましたが

Sindo02

やっぱりやや過剰気味な値を返してきますね。

20160428_7_09_13

なお、上のようにRaspberry Piを載せた収納ボックスをたたいたり、横の机の椅子に思い切りどんっ!と座るだけで”震度5”以上を記録することがあります。

ちょっと過敏すぎますね。時間平均じゃなくて、もうちょっとちゃんとした時系列フィルタが必要な感じ。

また床や壁などある程度硬いところに固定したほうがよさそうです。

とまあ問題だらけな”地震計”ですが、それでもある程度大きながあったときの時刻・回数を自動で記録してくれるため、地震の頻度を把握するという目的程度なら役に立ちそう。

ということで、地デジ録画と地震計を兼ねた我が家のRaspberry Pi B+。

現在、録画と揺れに備えて24時間待機してくれてます。

以下応用編ですが、せっかく地デジ録画できるRaspberry Piなので、NHK総合を10分間自動録画(地震速報の把握)させる、というのもやってみました。

上のコードの4~8行目のあたりに

import commands

を追記

69行目以降の震度判定のところで、震度6、7のif文の中にそれぞれ

       commands.getoutput("recdvb --b25 --strip --sid hd 20 600 TS/jisin.ts")

を追記しておくと、震度6以上でNHK総合を10分間録画してくれます。

(愛知県瀬戸タワーのNHK総合のチャンネルIDは”20”)

またある一定値以上の加速度を検知したらメールを送信。というのもできそう。

カメラをつけて、一定以上の揺れが来た直後の写真を撮影。自宅の様子をメールで送信するというのもやれそう。

震度表示はあてになりませんが、揺れた際に何かをさせるという目的に使えそうです。

いざというときの備えに”地震計”Raspberry Pi、いかがでしょうか?

SODIAL(R)MPU-6050モジュール3軸アナログジャイロセンサ 加速度センサーモジュールMPU 6050用

« Googleのエイプリルフールネタだった”物理フリックキーボード”のキット販売 | トップページ | バッテリー不要で電波のみで動作するIoT用超小型コンピュータ「WISP」 »

Raspberry Pi・Arduino・電子工作」カテゴリの記事

コメント

はじめまして
私もRaspberrypiで地震計作ろうと思って、このサイトにたどり着きました。
ただ、このshindo.py使うと、常時震度7を感知して・・・Σ( ̄ロ ̄lll)
思わず、天井見てしまいました。

違うところとすると、当方ではi2CデバイスをMPU6050含めて4つ接続していることぐらいです。

MPU6050の個体にもよるのでしょうかねぇ(^-^;

こんにちは、パンダさん。

上のコードの中ほどで”u = math.sqrt(x**2 + y**2 + z**2) - 1071.0”というのがあると思いますが、一度後ろの”-1071.0”をなくし、下に”print u”をつけてみてください。

私の環境下では平均で1071という値を返してきた(重力加速度なので、本来は”980.665”くらいのはず)ためこういう式になってますが、これが個体差などで変わってる可能性があります。

なおMPU6050は温度でも変わるらしいので、この”1071”の部分は季節ごとに変わってしまう可能性もあるようです。最近暑いですしねぇ。

こんにちは、arkoujiさん。
早速の回答ありがとうございます。
試してみたところ、私のほうでは1355でした。(気温25.4度)
なんとなく、うまく動いてくれてます。

起動してから、5分程度は不安定な状況でしたが、それ以後はログを見ても"w"の値は安定してくれてます。
これはMPU6050のくせらしいです。

こんにちは、パンダさん。

ずいぶん値が変わりますね。やはり個体差が大きいんでしょうか?今うちも25.2度ですが、値は大体1070程度ですね。

なお、この記事からカメラや温度センサーまでつけて、自宅の様子や温度をメールを送信する仕組みに変わってます。

http://arkouji.cocolog-nifty.com/blog/2016/05/raspberry-pi-de.html

留守の時に地震が発生して、自宅は無事か?火事が発生していないか?を見るためにいじってたんですが、震度6を超えるとけなげに10分間はメールを送り続けてくれる(たとえ誤検知であっても)かわいいやつです。今のところ、Raspberry Piに衝撃がない限りメールは来ませんが。

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/510034/63547998

この記事へのトラックバック一覧です: Raspberry Piで”地震計”作ってみた:

« Googleのエイプリルフールネタだった”物理フリックキーボード”のキット販売 | トップページ | バッテリー不要で電波のみで動作するIoT用超小型コンピュータ「WISP」 »

当ブログ内検索

  • カスタム検索

スポンサード リンク

ブログ村

無料ブログはココログ