5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Arduinoで温度と湿度を測ってシリアル通信

Last updated at Posted at 2019-01-21

なにがやりたいのか

簡単にいうと
Arduino Unoで室内の温度と湿度を測ってそれをブラウザ上で表示させたい。

とりあえずブラウザ上で表示させるのはNode.jsかなんかに任せるとして、
今回は**DHTセンサーなるものを使ってArduinoで回路を組み、計測した温度と湿度をJSON形式で送ろうとおもう。**

DHTセンサーにはメジャーなものとしてDHT11DHT22があるようですが、
今回は精度がDHT11より高い**DHT22**を使用します。Amazonで750円ぐらいで売っているのでよかったら試してみてください。

JSONデータを送る方法はシリアル通信にします。
ほんとうはシリアル通信じゃなくてHTTPあたりで通信したいけどEthernetシールド付きのArduinoの購入は
現在諸事情によりお金がなく、お値段的に憚れるので今回はシリアル通信で我慢する。
というより純正品に関しては日本のスイッチサイエンス社はもう販売していない?
HTTP通信についてはお金に余裕ができたら試してみようとおもいます。

Arduinoで使用するライブラリ

  • DHT-sensor-library
    • 簡単にDHTから値を読み取ることができるようになる。
    • Adafruit Unified Sensor Libraryをインクルードしないとダメとあるが多分今回使う部分の程度なら必要なさそう。
  • ArduinoJson
    • JSONのシリアライズに使用する。
    • 2019/01/21の時点ではバージョン6はベータ版なので注意。

回路を組む

以下の画像がわかりやすいと思います。
回路図
ブレッドボード図はこちら
board付き回路図
画像元のURL

Arduinoのコードを書く

コード例
# include <ArduinoJson.h>
# include <DHT.h>

constexpr uint8_t dhtPin = 2;       // DHTセンサーが刺さっているピン
constexpr uint8_t dhtType = DHT22;  // 今回使うのはDHT22
DHT dht{dhtPin, dhtType};

void setup() {
  Serial.begin(9600);
  dht.begin();
}

void loop() {
  // 10秒待機(DHT22は最低でも2秒は遅延させたい)
  delay(10000);

  // JsonObjectの生成。
  StaticJsonBuffer<200> jsonBuffer;
  auto& root = jsonBuffer.createObject();

  // 読み取った温度をJsonObjectにセットする。
  const auto temperature = dht.readTemperature();
  if (isnan(temperature)) {
    setError(root, "Error reading temperature!");
  }
  else {
    root["temperature"] = temperature;
  }
  
  // 読み取った湿度をJsonObjectにセットする。
  const auto humidity = dht.readHumidity();
  if (isnan(humidity)) {
    setError(root, "Error reading humidity!");
  }
  else {
    root["humidity"] = humidity;
  }

  // Jsonのシリアライズ。
  root.printTo(Serial);
  Serial.print("\n");  // 改行文字をデリミタとして使う。
}
シリアルモニタを覗くとこんな感じのJSONが確認できる
{"temperature":20.6,"humidity":54.4}

簡単な解説

DHTの初期化
# include <ArduinoJson.h>
# include <DHT.h>

constexpr uint8_t dhtPin = 2;       // DHTセンサーが刺さっているピン
constexpr uint8_t dhtType = DHT22;  // 今回使うのはDHT22
DHT dht{dhtPin, dhtType};

constexpr uint8_t dhtType = DHT22;とありますが、DHT22DHT.hに定義されています。

C++11以降のC++にあまり馴染みがない方なら**constexpr**ってなんやねん!って思ったかもしれません。
この部分に関してはconstとあまり変わらないので気にする必要はなさそうです。
**constexpr**に対してまともに解説するとそれだけで長い記事になるほど奥が深いので気になった方はぜひ調べてみてください。

DHT dht{dhtPin, dhtType}ではDHTのコンストラクタを呼び出しています。
ArduinoでC++11以降の記述ができるんだと知り、ビビってしまったためここでもC++11の記法を使っています。:sweat:

setup部分
void setup() {
  Serial.begin(9600);
  dht.begin();
}

シリアル通信のデータ転送レートの指定とDHTのセットアップをしています。
DHT::begin()の中身はメンバ変数とピンモードの初期化となっているようです。(2019/1/21時点)
ちなみにArduinoではSetup()は電源を入れたときやリセットしたときに、一度だけ呼ばれる関数となっています。

loop部分はじめ
void loop() {
  // 10秒待機(DHT22は最低でも2秒は遅延させたい)
  delay(10000);

Arduinoではloop()Setup()のあとに繰り返し呼ばれます。
とりあえず10秒間隔でシリアル通信を行うことにしました。

JsonObjectの生成
  // JsonObjectの生成。
  StaticJsonBuffer<200> jsonBuffer;
  auto& root = jsonBuffer.createObject();

StaticJsonBufferはメモリプールで、StaticJsonBuffer<200> jsonBufferでは200bytesのメモリを確保しています。
ちなみにおもいっきりStackにのっているのでHeapから確保したい場合はDynamicJsonBufferを使えばいいそうです。

また、auto& root = jsonBuffer.createObject();でさきほどのjsonBufferからJsonObjectへの参照を得ていますが、この参照の寿命はjsonBufferがスコープから抜けるまでのようです。
なので今回で言えばloop()内では参照可能ということになります。

温度の読み取り
  // 読み取った温度をJsonObjectにセットする。
  const auto temperature = dht.readTemperature();
  if (isnan(temperature)) {
    setError(root, "Error reading temperature!");
  }
  else {
    root["temperature"] = temperature;
  }

DHT::readTemperature()でセンサーが計測した温度を受け取ることができます。
失敗した場合はNANが返ってきます。
ここではNANを捉えたらsetError()rootにerror関連の値をセットしています。error値のセット方法は人によって実装方法がいろいろあると思うので実装は載せていません。

返り値がNANではなかった場合、JsonObjectrootkey=temperature,value=読み取った温度を追加しています。
例えば、読み取った温度が25.5°Cだった場合は{"temperature"=25.5}のような感じになります。

湿度も同じことやっているので省略。

Jsonデータを送る
  // Jsonのシリアライズ。
  root.printTo(Serial);
  Serial.print("\n");  // 改行文字をデリミタとして使う。
}

JsonObject::printTo()の引数はJsonの書き込み先を指定します。今回はシリアル通信を行いたいのでSerialを指定します。
データを受信する際に改行文字あったほうが楽そうだったので今回は改行文字もシリアルポートへ出力しています。

つぎにやること

TypeScript + Node.jsでJSONデータを受け取ってブラウザで表示させるところまでは記事にしたい。
本当はそれも含めた記事にしたかったのですが、そろそろ真面目に就職活動を行おうと思うので、ちょっと後回しになってしまう形に。
キチンと書き終えるのがいつになるのかわからなかったのでとりあえず一区切りとしてここでいったん投稿することにします。:fist:

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?