Ruby
RaspberryPi
raspbian
I2C

Raspberry PIで温度湿度センサーをRubyで動かす

More than 3 years have passed since last update.


はじめに

この記事では次のようなことをしています。


  • Raspberry Piを使います

  • OSはRaspbianを使います

  • 温度湿度センサーはAM2321を使います

  • AM2321はI2Cで接続します

  • センサーの読み出しにはRubyのコードを使用します

  • 値の読み出しのみでWebに連携するなどは行なっていません

image


AM2321センサー

温度と湿度を同時に測定できるセンサーモジュールです。I2Cの他に1-wireに似た方式で通信できます。

ピンは1.27mmピッチなので汎用のブレッドボードに繋ぐ場合は2.54mmピッチに変換してあげる必要があります。

image


参考サイト


配線

配線は次の図の通りです。

なお、通常I2Cの接続にはプルアップ抵抗が必要ですが、Raspberry Piは標準で入っているため不要です。

image


参考サイト


Raspbianの設定

Raspbianの標準ではi2cが有効になっていないので有効にします。


i2c-toolsのインストール

次のコマンドでインストールされます

$ sudo apt-get install i2c-tools


使用するユーザー(UserId=pi)をi2cのグループに追加する

piユーザーでi2cにアクセスできるようにするため、i2cグループに追加します。

$ sudo adduser pi i2c


/etc/modules

次のコマンドで/etc/modulesを編集します。

$ sudo vi /etc/modules

次の2行を追加します。

i2c-bcm2708

i2c-dev


/etc/modprobe.d/raspi-blacklist.conf

次のコマンドで/etc/modprobe.d/raspi-blacklist.confを編集します。

$ sudo vi /etc/modprobe.d/raspi-blacklist.conf

次の1行をコメントアウトします。

#blacklist i2c-bcm2708


参考サイト


疎通確認

前述でインストールしたi2c-toolsのi2cdetectコマンドを使って疎通確認します。

「i2cdetect -y 1」コマンドで確認できます。

$ 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: -- -- -- -- -- -- -- --

AM2321のアドレスである0x5cが検出されました。

ちなみにAM2321はセンサーが自己発熱による湿度誤差を低減するため、休止状態になるという機構があるそうです。

このため、休止状態のときにi2cdetectコマンドを実行すると検出されないことがります。

この場合、複数回連続で実行すると検出されるようになります。

この休止状態の機構のためか、私の環境ではi2c-toolsのコマンドは全般的に正しく動きませんでした。ちょっと辛いです。


Rubyのコード

Rubyからi2cを操作するため、i2cのGemが必要になるのでインストールします。

sudo gem install i2c

次のコードはi2c経由でAM2321経由でRubyで値を取得するコードです。

- Wake up sensorの箇所は休止状態のセンサーを起こす処理です

- Read sensor valuesの"\x03\x00\x04"は、AM2321固有のコマンドです 参考

- CRC16は自前で計算しています

#!/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')

100.times do
p sensor.read
sleep(0.5)
end


参考サイト


おわりに

AM2321をRaspberryPiで動作させたくて始めたのですが意外にやることが多くて結構嵌りました。

Rubyにしたのは勉強がてらというので特に意味はありません。

とりあえず値が読み出せたので、ここからCrondで定期的に値を読み取り、Webにアップロードしたり、Google Spread Sheetに保存したりするなどの応用に繋げられるようになりました。

繋げられるものを繋いでいって面白いものが作れればと思います。