Здравствуйте!
この記事は、スタートトゥデイ工務店 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』を選択します。

i2c 有効化 その1
『5 Interfacting Options』を選択し、『P5 I2C』を選択します。

i2c 有効化 その2

i2c 有効化 その3
I2C接続を有効化してもよい?(意訳)と聞かれているので、『はい』を選択し、その後のページも『OK』を選びます。

i2c 有効化 その4

i2c 有効化 その5
その後、一旦、再起動します。(再起動しますか?というダイアログが表示されるので、『はい』を選択します)
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を使って、クラウドへデータを保存するようにします。(えっっっ)
それでは、до свидания!



コメント