高精度の温湿度センサ AM2302をPythonライブラリでお手軽に動かす

高精度の温湿度センサ AM2302をPythonライブラリでお手軽に動かす

余ったからとDHT11で温度ログを取っていたけれど、やっぱり精度が気になる。かといってI2C対応のAM2320は高いなーと迷っていたら、同じ1-wire(シリアル)通信専用のAM2302がDHT11とほぼ同じ値段だったので買ってみました。

AM2302はAmazonが安い

AM2302はDHT22とも書かれる(完全に同じかは不明)DHT11の上位製品。

  • 湿度精度:±2%(DHT11は±5%)
  • 温度精度:±0.5℃(DHT11は±2℃)
  • 分解能:0.1℃/%(DHT11は1℃/%)

その分秋月電子で買うと3倍もの値段がします。
しかしAmazonでは一個543円しかも送料無料。例によって中国からなので予備も含めて2個購入しました。

基盤に固定済みでプルアップ抵抗付き。ジャンパーワイヤもついてきます。

Pythonで読み取るライブラリ

またCでシリアル通信するコード見るのか・・・と苦労していたら、Electric DIYには有名なAdafruitがPythonライブラリを公開してくれています。ありがたや。

GitHub – adafruit/Adafruit_Python_DHT: Python library to read the DHT series of humidity and temperature sensors on a Raspberry Pi or Beaglebone Black.

Pythonは3系列へ

Pythonは現在の2.7x系が開発終了するとの表示がありました。
今の環境(OpenHabianのフルアプデート済み)ではどちらも利用可能だったので、このセンサーに関してはPython3環境でセットアップしています。

$ python --version
Python 2.7.9

$ python3 --version
Python 3.4.2

$ ls -l `which python`
lrwxrwxrwx 1 root root 9 Mar 28 2015 /usr/bin/python -> python2.7

NodeREDサーバも兼ねてるのでベースのPythonは2のまま。

Adafruit Python DHT Sensor Library

$ sudo git clone https://github.com/adafruit/Adafruit_Python_DHT.git

$ sudo apt-get install python3-pip

$ sudo pip3 install Adafruit_DHT
$ sudo python3 setup.py install

サンプルプログラムを実行してみます。

$ cd Adafruit_Python_DHT/exsample
$ sudo python3 ./AdafruitDHT.py
Usage: sudo ./Adafruit_DHT.py [11|22|2302] <GPIO pin number>
Example: sudo ./Adafruit_DHT.py 2302 4 - Read from an AM2302 connected to GPIO pin #4

パラメータとして1個目にセンサータイプ、2個目にGPIO番号を渡します。

ライブラリはAM2302のみならず、コレまで使ってきたDHT11や別扱いのDHT22も対応。
今回センサーはGPIOヘッダの18ピン目=GPIO24に接続しているので”2302 24″をつけて実行。

 $ sudo python3 ./AdafruitDHT.py 2302 24
Temp=21.1* Humidity=30.1%

あっさり動きました。Cのときと違ってすごく楽。
そして小数点まで表示してくれるのはやっぱりイイ。

M2Xにてプロットする

DHT11のCプログラムと出力フォーマットをあわせ、同じシェルスクリプトでM2Xに投げます。

Raspberry Piとセンサで家の消費電力を測ってM2Xでグラフ化する(設置編) | 徒労日記

カンマ区切りの以下のフォーマットを出力。

HH.H,TT.T

HH.H = 湿度
TT.T = 温度

サンプルプログラムの値決め打ちにして、フォーマットをあわせた”am2302.py”が以下。

$ cat am2302.py
#!/usr/bin/python
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola

import sys
import Adafruit_DHT

sensor_args = Adafruit_DHT.AM2302
pin = 24

humidity, temperature = Adafruit_DHT.read_retry(sensor_args, pin)

if humidity is not None and temperature is not None:
 print('{0:0.1f},{1:0.1f}'.format(humidity, temperature))
else:
 print('Failed to get reading. Try again!')
 sys.exit(1)

上記を実行し、M2Xに投げるシェルスクリプト”am2302_2_m2x.sh”が以下。

#!/bin/sh

humtem=$(python3 /usr/local/etc/Adafruit_Python_DHT/sensor/am2302.py)
echo $humtem

r_temp=$( echo $humtem | cut -f2 -d',')
curl -i -X PUT http://api-m2x.att.com/v2/devices/XXXXXXXXXXXXX/streams/2_temp/value -H "X-M2X-KEY: XXXXXXXXXXXXX" -H "Content-Type: application/json" -d "{ \"value\": \"$r_temp\" }"

r_humi=$( echo $humtem | cut -f1 -d',')
curl -i -X PUT http://api-m2x.att.com/v2/devices/XXXXXXXXXXXXX/streams/2_humi/value -H "X-M2X-KEY: XXXXXXXXXXXXX" -H "Content-Type: application/json" -d "{ \"value\": \"$r_humi\" }"

テスト実行の結果。いい感じです。

$ sudo ./am2302_2_m2x.sh
30.0,22.1
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=UTF-8
X-M2X-VERSION: v2.112.2
Vary: Accept-Encoding
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9
X-RateLimit-Reset: 1552707468
Content-Length: 21

{"status":"accepted"}HTTP/1.1 202 Accepted
Content-Type: application/json; charset=UTF-8
X-M2X-VERSION: v2.112.2
Vary: Accept-Encoding
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 8
X-RateLimit-Reset: 1552707469
Content-Length: 21

あとはこれを10分毎に実行するようCrontabに書いて完成。

$ sudo crontab -e
#h dom mon dow command
*/10 * * * * /usr/local/etc//Adafruit_Python_DHT/sensor/am2302_2_m2x.sh 2>&1 | logger -t am2302_2_m2x -p local0.info

余談

実行パスの謎

最初のうち、しばらく謎の現象に悩まされました。
それは「exsampleディレクトリからサンプルプログラムを移動させるとエラーになる」というもの。

まず実行するカレントディレクトリは結果に影響しないことを確認。

:/Adafruit_Python_DHT/examples$ python3 AdafruitDHT.py 2302 24
Temp=21.9* Humidity=30.0%
:/Adafruit_Python_DHT/examples$ cd ..
:/Adafruit_Python_DHT$ python3 examples/AdafruitDHT.py 2302 24
Temp=22.0* Humidity=30.0%

その後、サンプルプログラムをAdafruit_Python_DHTにコピーしてから実行してみます。

:/Adafruit_Python_DHT$ sudo cp examples/AdafruitDHT.py .
:/Adafruit_Python_DHT$ python3 AdafruitDHT.py 2302 24
Traceback (most recent call last):
File "AdafruitDHT.py", line 41, in <module>
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
File "/usr/local/etc/Adafruit_Python_DHT/Adafruit_DHT/common.py", line 94, in read_retry
humidity, temperature = read(sensor, pin, platform)
File "/usr/local/etc/Adafruit_Python_DHT/Adafruit_DHT/common.py", line 80, in read
platform = get_platform()
File "/usr/local/etc/Adafruit_Python_DHT/Adafruit_DHT/common.py", line 55, in get_platform
from . import Raspberry_Pi_2
File "/usr/local/etc/Adafruit_Python_DHT/Adafruit_DHT/Raspberry_Pi_2.py", line 22, in <module>
from . import Raspberry_Pi_2_Driver as driver
ImportError: cannot import name 'Raspberry_Pi_2_Driver'
:/Adafruit_Python_DHT$

途端に謎のImportErrorが発生します。
特に各.pyを見ても相対パスなどは書かれていません。なぜに??

フォーラムに答えが

いろいろ探すと同じ様なハマりかたしてる人がいて、そこにこんなリプが

For anyone else facing the same issue that @TiagoGouvea mentioned.
Try to run your program from outside the Adafruit_DHT directory that was cloned.
It happens because when you run –
import Adafruit_DHT
It imports the Adafruit_DHT folder in your current directory instead of the one installed in your site-packages directory.
When run from anywhere else, it is working fine.
Hope this helped.

あなたが神か。

展開したAdafruit_Python_DHT配下で実行すると、インストールしたsite-packagesディレクトリではなく、直下にあるAdafruit_DHT ディレクトリを参照してしまいエラーになるよ、との事です。

確かに/tmpにコピーして使ったら普通に動きました。
構築中ってつい解凍フォルダ配下で作業したくなるから、そこで見事はハマったわけです。

Raspberry Piカテゴリの最新記事