2015/02/27

Raspberry Piのによる気圧お知らせ

I2Cで気圧センサ(MPL115A2)と接続できたので、気圧の変動によってtwitterで
つぶやくようにしました。

Rubyによるtwitter接続登録

ここに詳しくプログラムによる接続手続きが書かれているので、そちらを見てください。(^^;
簡単に書くと、twitterの開発者向けサイトにログインして、トークンを得るために
アプリケーション名とかを記入します。すると、トークンが表示されますので、コピー
してプログラム中に挿入します。
サンプルプログラムでHello worldが表示できます。

Arduinoプログラムの移植

Arduino + MPL115A2の組み合わせの時のプログラムがありましたので、それをRuby用に
移植します。
そこにtwitterにつぶやく一文も追加しました。

#!/usr/bin/env ruby
#coding: utf-8

require "date"
require "twitter"

class I2CDevice
  # ioctl command
  # Ref. https://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/include/linux/i2c.h
  I2C_RETRIES = 0x0701
  I2C_TIMEOUT = 0x0702
  I2C_SLAVE = 0x0703
  I2C_SLAVE_FORCE = 0x0706
  I2C_TENBIT = 0x0704
  I2C_FUNCS = 0x0705
  I2C_RDWR = 0x0707
  I2C_SMBUS = 0x0720
  I2C_UDELAY = 0x0705
  I2C_MDELAY = 0x0706

  attr_accessor :address
  def initialize(address)
    @address = address
  end

  def i2cget(address, length=1)
    i2c = File.open("/dev/i2c-1", "r+")
    i2c.ioctl(I2C_SLAVE, @address)
    i2c.write(address.chr)
    ret = i2c.read(length)
    i2c.close
    ret
  end

  def i2cset(*data)
    i2c = File.open("/dev/i2c-1", "r+")
    i2c.ioctl(I2C_SLAVE, @address)
    i2c.write(data.pack("C*"))
    i2c.close
  end
end

class MPL115A2 < I2CDevice
  def initialize
    super(0x60)

    coefficient = i2cget(0x04, 8).unpack("n*")

    @a0 = fixed_point(coefficient[0], 12)
    @b1 = fixed_point(coefficient[1], 2)
    @b2 = fixed_point(coefficient[2], 1)
    @c12 = fixed_point(coefficient[3], 0) / (1<<9)
    p [@a0, @b1, @b2, @c12]
  end

  def fixed_point(fixed, int_bits)
    msb = 15
    deno = (1<<(msb-int_bits)).to_f
    if (fixed & (1<<15)).zero?
      fixed / deno
    else
      -( ( (~fixed & 0xffff) + 1) / deno )
    end
  end

  def calculate_hPa
    i2cset(0x12, 0x01) # CONVERT

    sleep 0.003

    data = i2cget(0x00, 4).unpack("n*")

    p_adc = (data[0]) >> 6
    t_adc = (data[1]) >> 6

    p_comp = @a0 + (@b1 + @c12 * t_adc) * p_adc + @b2 * t_adc
    hPa = p_comp * ( (1150 - 500) / 1023.0) + 500;
  end
end

mpl = MPL115A2.new
loopflag = 0 #周回フラグ
press = [0,0,0,0,0,0,0,0,0,0,0,0,0] #気圧データ保存配列
tcount = 0 #3時間計

# Twitter setup
client = Twitter::REST::Client.new do |config|
  config.consumer_key = "******"
  config.consumer_secret = "******"
  config.access_token        = "******"
  config.access_token_secret = "******"
end

loop do
  sec_total = 0
  min_total = 0

  for min_j in 0..14 do
    for sec_i in 0..14 do
      sec_total = sec_total + mpl.calculate_hPa
      sleep 1
    end
    onemin_ave = sec_total / 15
    min_total = min_total + onemin_ave
    sec_total = 0
    sleep 45
  end
  press[tcount] = min_total / 15
  print("tcount = ", tcount, "pressure = ", min_total/15, "\n")

  if tcount > 0  then
    day = Time.now
    daystr = day.strftime("%Y/%m/%d %H:%M:%S ")

    dpdt = (press[tcount] - press[0]) / (tcount * (loopflag + 0.25) * 0.635)
    printf("pressure = %f, dP/dt = %f ,", press[tcount], dpdt)
    if 2.5 <= dpdt then
      printf("急速に気圧が上昇しています \n")
      mess = "急速に気圧が上昇しています。 @横浜南"
      message = daystr + mess
      client.update(message)
    end
    if 0.5 < dpdt && dpdt < 2.5 then
      printf("気圧が緩やかに上昇しています。 \n")
      mess = "気圧が緩やかに上昇しています。 @横浜南"
      message = daystr + mess
      client.update(message)
    end
    if -0.5 <= dpdt && dpdt <= 0.5 then
      printf("気圧の変化はありません。 \n")
    end
    if -2.5 < dpdt && dpdt < -0.5 then
      printf("気圧が緩やかに下降しています。 \n")
      mess = "気圧が緩やかに下降しています。 @横浜南"
      message = daystr + mess
      client.update(message)
    end
    if dpdt <= -2.5 then
      printf("急速に気圧が落ちています。 \n")
      mess = "急速に気圧が落ちています。突然の雨に気をつけてください。 @横浜南"
      message = daystr + mess
      client.update(message)
    end

    if tcount == 8 then
      press[0] = press[4]
    end

    if tcount >= 12 then
      loopflag = 1
      tcount = 1
    else
      tcount += 1
    end

  else
    tcount += 1
  end
end

で、動作させますと、このようにつぶやきます。

今回はつぶやきまで、ということで終わりにしますが、もう少しネタがあるので
頃合いをみて続きます。

2015/02/13

RaspberryPiでI2Cアクセス(その2)

前回は本題に入らず終わってしまいました。。。(^^;
今回こそはRaspberry PiとセンサとがI2Cで接続できるまでを説明します。

I2C接続の準備

Raspberry PiはデフォルトではI2Cが無効化されていますので、有効にするため設定を変更します。
  • /etc/modulesの編集
      $ sudo vi /etc/modules
      i2c-bcm2708
      i2c-dev
    
  • /etc/modprobe.d/raspi-blacklist.confの編集
      $ sudo vi /etc/moduprobe.d/raspi-blacklist.conf
      #blacklist i2c-bcm2708
    
これらの編集が済んだら、Raspberry Piを再起動します。
その後、i2c-toolsをインストールします。
$ sudo apt-get install i2c-tools
これで準備が完了しました。

センサとのI2C接続

Raspberry PiとMPL115A2を接続し、i2cdetectコマンドを実行するとセンサのアドレスが
表示されます。
raspberrypi ~ $ sudo i2cdetect -y 1

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 
この方のRubyプログラムは完璧なので、そのまま使わせていただきました。(ありがとうございます)
http://lowreal.net/2013/12/26/1
これを実行すると0.5秒おきに気圧がSTDOUTに表示されます。
続きます!

2015/02/03

Raspberry PiでI2Cアクセス

Raspberry Piを買って1年以上放置していたのですが、ようやくI2Cでセンサーとお話し
させて何やらやらせようという気になり、インストールしただけのRaspbianを24時間
動作させても安心な設定に変更しました。
という訳で、その備忘録です。
相変わらずですが、詳しい説明は他の方の説明をお読みください。(^^;)
http://qiita.com/makoto_kw/items/393e098f214f81449c9f

Raspbianがインストールされた状態(ssh接続設定できているものとします)から、
・rootのパスワード変更
・新アカウントの作成
・新アカウントでsudoが使えるように、visudoで新アカウントを追加
・新アカウントでssh, sudoが使えるか確認を行った上で、piユーザの削除
を行いました。

さて次はRaspberry Piの延命処置をおこないました。
・Swapの停止
foo@raspberrypi ~ $ free
             total       used       free     shared    buffers     cached
Mem:        448776      59988     388788          0       9528      28348
-/+ buffers/cache:      22112     426664
Swap:       102396          0     102396
foo@raspberrypi ~ $ sudo swapoff --all
[sudo] password for foo: 
foo@raspberrypi ~ $ free
             total       used       free     shared    buffers     cached
Mem:        448776      59988     388788          0       9528      28348
-/+ buffers/cache:      22112     426664
Swap:            0          0          0
foo@raspberrypi ~ $ sudo apt-get remove dphys-swapfile
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  dphys-swapfile
0 upgraded, 0 newly installed, 1 to remove and 64 not upgraded.
After this operation, 69.6 kB disk space will be freed.
Do you want to continue [Y/n]? Y
(Reading database ... 62309 files and directories currently installed.)
Removing dphys-swapfile ...
Stopping dphys-swapfile swapfile setup ..., done.
Processing triggers for man-db ...
foo@raspberrypi ~ $ 
・tmp, logディレクトリのNFS化
Swap以外にも/tmpや/var/tmp, /var/logなど、書き込み頻度が高いディレクトリを退避
します。よく見られるのはRAMディスクを作りそこに書き込む方法ですが、今回私は
ファイルサーバにNFS接続しHDDに書き込む事にしました。
まずはサーバ側:
# aptitude install nfs-kernel-server
# mkdir /var/nfs →NFSで接続するディレクトリの作成
# vi /etc/exports
/var/nfs/tmp 192.168.10.xx(rw,sync,fsid=0,no_subtree_check) の追加(Raspberry Piのみの接続にしました)
# /etc/init.d/nfs-kernel-server start
これでサーバ側の準備が整いました。次にRaspberry Pi側:
portmapやidmapdはrpcbindにあり、既にインストールされているようですので、
$ sudo apt-get install nfs-common
$ sudo mount -t nfs 192.168.10.x:/var/nfs /mnt
$ sudo vi /var/fstab
で、何故かnfs4では接続できませんでした。orz
いえ、理由は分かっておりidmapdがRaspberry Pi側で立ち上がらず、それで
接続できないのですが、何故立ち上がらないのかが分かりません。。。
mountコマンドの実験でnfsの接続ができたので、とりあえずそれで良しとします。(^^;)
続きます。