Здравствуйте!
この記事は、スタートトゥデイ工務店 Advent Calendar 18日目の記事です。
お約束事ですが、私の個人的な意見・経験に基づくものであり、私の雇用者、所属団体には一切の関係はありませんし、イロイロ気になるところがあるかもしれませんが、そこんとこお察しください。
はじめに
とあるMashup Awardsのとあるハッカソンイベントで作った作品を解体したおかげでRaspberry Pi 3が余ってたり、手元に手頃な温湿度センサーモジュールが転がっていたり、ほんの出来心から、ウェザーステーションを作ってみました。
- Raspberry Pi 3を使って
- Raspibian Jessieを使用しています
- Raspberry Pi のインストール、初期設定については、説明しません
- 温湿度センターには am2320 を使用して、i2c で接続しています
- センサーの読み出しでは Ruby を使っています
- センサーでの測定値は Logger で log に出力しています
使用したもの
- ガジェット
- Raspberry Pi 3
- OS
- Raspbian Jessie
- センサ
- AM2320
温湿度センサーを取り付けて、Raspbianの設定をする
温湿度センサーをブレッドボード上に設置
簡単に示すと、以下のようになっています。
たまたまT型の接続キットを持っていたので使っていますが、ピンから接続しても問題ありません。
Raspbianの設定 – i2c の有効化
Raspberry Piの初期状態ではi2c機能が有効化されていないため、有効化する必要があります。
$ sudo raspi-config
表示されるメニューの『7 Advanced Option』を選択します。
『5 Interfacting Options』を選択し、『P5 I2C』を選択します。
I2C接続を有効化してもよい?(意訳)と聞かれているので、『はい』を選択し、その後のページも『OK』を選びます。
その後、一旦、再起動します。(再起動しますか?というダイアログが表示されるので、『はい』を選択します)
Raspbianの設定 – i2c-tools のインストール
i2c接続するセンサーとの疎通確認を行うために、i2c-toolsというパッケージをインストールします。
$ sudo apt-get install -y i2c-tools
Raspbianの設定 – i2cのグループにユーザーを追加する
ここでは、piユーザ(初期ユーザ)でi2cにアクセスできるように、i2cグループに追加します。
$ sudo adduser pi i2c
Raspbianの設定 - 設定ファイルの修正
/boot/config.txt に以下の内容を追記します。
dtparam=i2c_arm=on
Raspbianの設定 – カーネルモジュールの自動読み込み
起動時にカーネルモジュールに自動的に読み込ませるために、/etc/modulesに以下を追記します。
i2c-bcm2835 i2c-dev
以上、設定したら、再度、再起動します。
再起動後、カーネルモジュールが読み込まれているか確認をします。
$ lsmod Module Size Used by bnep 10340 2 hci_uart 17943 1 btbcm 5929 1 hci_uart bluetooth 326105 22 bnep,btbcm,hci_uart brcmfmac 186403 0 brcmutil 5661 1 brcmfmac cfg80211 427855 1 brcmfmac rfkill 16037 4 cfg80211,bluetooth snd_bcm2835 20447 0 snd_pcm 75762 1 snd_bcm2835 snd_timer 19288 1 snd_pcm snd 51908 3 snd_bcm2835,snd_timer,snd_pcm bcm2835_gpiomem 3040 0 bcm2835_wdt 3225 0 uio_pdrv_genirq 3164 0 uio 8000 1 uio_pdrv_genirq i2c_dev 5859 0 i2c_bcm2708 4834 0 ipv6 347594 34
i2c_bcm2708, i2c_devが存在すればOKです。
疎通確認
先程インストールした i2c-tools の i2cdetect コマンドを利用して、疎通確認を行います。
$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- 5c -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
AM2320のアドレスである 0x5cが検出されました。
ちなみに、AM2320はセンサー自体の発熱による湿度誤差を軽減するために、休止状態になることがあります。
そのため、i2cdetectコマンドをなげても検出されないことがありますが、何度かコマンドを実行すると、検出されます。
温度と湿度を取得するコード
まず、Rubyからi2cを操作するために、i2c Gemをインストール擦る必要があります。
$ sudo gem install i2c
i2c経由でAM2320でデータを取得します
#!/usr/bin/env ruby require 'rubygems' require 'i2c' class AM2321 def initialize(path, address = 0x5c) @device = I2C.create(path) @address = address end def crc16(data) crc = 0xFFFF data.each do |b| crc ^= b; 8.times do if (crc & 0x01) != 0 then crc = crc >> 1 crc ^= 0xA001 else crc = crc >> 1 end end end return crc end def read # Wake up sensor begin @device.write(@address, "") rescue # ignore end # Read sensor values begin s = @device.read(@address, 8, "\x03\x00\x04") rescue return nil end func_code, ret_len, hum_h, hum_l, temp_h, temp_l, crc_l, crc_h = s.bytes.to_a orig_crc = (crc_h << 8) | crc_l hum = (hum_h << 8) | hum_l temp = (temp_h << 8) | temp_l # Calc CRC crc = crc16(s[0,6].bytes) return nil if crc != orig_crc return hum/10.0, temp/10.0 end end sensor = AM2321.new('/dev/i2c-1') temp, hum = sensor.read puts "気温:#{temp.to_s}, 湿度:#{hum.to_s}"
$ sudo ruby test.rb 気温:23.9, 湿度:37.2
Loggerで出力するようにしてみる
Loggerを使い、/var/log/weatherbox/に出力するようにしてみます
#!/usr/bin/env ruby require 'rubygems' require 'i2c' require 'date' require 'json' require 'logger' require 'fileutils' class AM2321 def initialize(path, address = 0x5c) @device = I2C.create(path) @address = address end def crc16(data) crc = 0xFFFF data.each do |b| crc ^= b; 8.times do if (crc & 0x01) != 0 then crc = crc >> 1 crc ^= 0xA001 else crc = crc >> 1 end end end return crc end def read # Wake up sensor begin @device.write(@address, "") rescue # ignore end # Read sensor values begin s = @device.read(@address, 8, "\x03\x00\x04") rescue return nil end func_code, ret_len, hum_h, hum_l, temp_h, temp_l, crc_l, crc_h = s.bytes.to_a orig_cc = (crc_h << 8) | crc_l hum = (hum_h << 8) | hum_l temp = (temp_h << 8) | temp_l # Calc CRC crc = crc16(s[0,6].bytes) return nil if crc != orig_cc return temp/10.0, hum/10.0 end end logdir = "/var/log/weatherbox/" FileUtils.mkdir("#{logdir}") unless FileTest.exist?("#{logdir}") logfile = Logger.new("#{logdir}weatherbox.log", "daily") logfile.formatter = proc do |severity, datetime, progname, message| "#{message}\n" end sensor = AM2321.new('/dev/i2c-1') loop do temp, hum = sensor.read d = Time.now date = d.strftime("%Y-%m-%d %H:%M:%S") data = Hash.new data["Temperature"] = temp data["Humidity"] = hum json = Hash.new json["Time"] = date json["Data"] = data logfile.info(json.to_json) sleep(5) end
このコードを実行すると、/var/log/weatherbox/weatherbox.logに対して、以下のようなデータが出力されます。
# Logfile created on 2016-12-18 22:59:57 +0900 by logger.rb/v1.2.7 {"Time":"2016-12-18 22:59:57","Data":{"Temperature":23.9,"Humidity":36.9}} {"Time":"2016-12-18 23:15:03","Data":{"Temperature":23.7,"Humidity":37.0}} {"Time":"2016-12-18 23:15:08","Data":{"Temperature":23.7,"Humidity":37.0}} {"Time":"2016-12-18 23:15:16","Data":{"Temperature":23.6,"Humidity":37.0}} {"Time":"2016-12-18 23:15:21","Data":{"Temperature":23.6,"Humidity":37.0}} {"Time":"2016-12-18 23:15:26","Data":{"Temperature":23.6,"Humidity":37.0}}
今後の流れ
Raspberry PiでAM2320という温湿度センサーを使って温度と湿度を取得しました。
現時点では、Raspberry Pi内にデータを格納しているので、次回、fluentdを使って、クラウドへデータを保存するようにします。(えっっっ)
それでは、до свидания!
コメント