コメを噛め

コメを噛め

rerofumi の電子工作メモ

hatena bookmark

DSC00902
前回 RaspberryPi2 に気圧センサーと気温/湿度センサーを付けて値を読み取れるようにした。
ぱっと見良さそうだったのだけれども、しばらくコレで計測を続けてみるとどうも湿度が正しく変動していない様に見受けられた。

たまたま使った DHT11 の個体不具合っぽい。自分の目的的に湿度はおまけみたいなものだったけれども、計測できないとなるとなんか悔しくなってきたので作り直すことにした。
その際、ワンワイヤーシリアルだった DHT11 の代わりに I2C の AM2310 に変更を行った。これで I2C に統一できる。
気圧センサは手持ち在庫の関係で LPS25H ではなく LPS331AP に、現在は LPS25H の方が在庫品になっているのでそっちで読み替えて貰うとありがたい。


AM2310 のインターフェースは I2C だが、なんとなく扱いはワンワイヤーに近い感じでちょっと変な扱いとなる。具体的にはリクエストコマンドを 3byte 投げた後ストップシーケンスにせずそのままデータを受け取っていく。
この表現が wiringpi のライブラリで上手く呼べなかったので困っていたら、先達が ruby でのコードを公開してくれていた。

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

ありがたいのでこれをそのまま使わせて頂くことにする。
ruby gem の ‘i2c’ パッケージを使っているので、LPS331AP の読み取りも i2c パッケージを使うことにする。

読み取りコードはこんな感じ。

 


#!/usr/bin/ruby

require 'i2c'
require 'net/http'
require 'uri'

DEVICE = "/dev/i2c-1"
HOST = 'http://nanlog.local:8080/'
VERB = false

# -----------------------------
class Lps331ap
def initialize(path, address=0x5d)
@device = I2C.create(path)
@address = address
end

def writeCommand(address, data)
send = [ address, data ].pack("c*")
@device.write(@address, send)
end

def readCommand(address)
# Wake up sensor
begin
writeCommand(0x20, 0x90)
rescue
# ignore
end

begin
s = @device.read(@address, 1, address)
rescue
return nil
end
return s.bytes[0]
end

def init
live = readCommand(0x0f)
if (live != 0xbb) then
return false
end
writeCommand(0x20, 0x90)
sleep(1.5)
end

def pressure
a = readCommand(0x2a)
b = readCommand(0x29)
c = readCommand(0x28)
d = (a * 0x10000) + (b* 0x100) + c
d = d / 4096.0
return d
end

def temp
a = readCommand(0x2c)
b = readCommand(0x2b)
c = (a * 0x100) + b
if c > 0x7fff then
c = c - 65536
end
d = 42.5 + (c / 480.0)
return d
end
end

# -----------------------------
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

# -----------------------------

class IotPost
def initialize(host)
@server = host
end

def post(tag, body)
uri = URI.parse(@server+tag)
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.request_uri)
req.body = body
res = http.request(req)
printf("http request %d\n", res.code) if VERB
end
end



# -----------------------------
# --- main
# -----------------------------

sense = Lps331ap.new(DEVICE)
sense.init
press = sense.pressure
temp = sense.temp
printf("%f hPa\n", press) if VERB
printf("%f *C\n", temp) if VERB

sense2 = AM2321.new(DEVICE).read
printf("%f \%\n", sense2[0]) if VERB
printf("%f *c\n", sense2[1]) if VERB


logger = IotPost.new(HOST)
logger.post('100yo_temp', temp.to_s)
logger.post('100yo_pressure', press.to_s)
logger.post('100yo_temp2', sense2[1].to_s)
logger.post('100yo_humidity', sense2[0].to_s)

コードの中に結果をロガーに向けて POST しているところがあるけれども、この辺は次回の説明にて。

 

Leave a Reply