Help us understand the problem. What is going on with this article?

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

More than 5 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に保存したりするなどの応用に繋げられるようになりました。
繋げられるものを繋いでいって面白いものが作れればと思います。

dr-ubie
病気予測AIによる病院向け問診サービス、及び to C 向け病気予測サービスを運営するスタートアップ
https://ubie.life/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away