0
1

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 3 years have passed since last update.

CO2センサーの値をESP32-WROVER-E経由でAWS IoTに送ってみる

Last updated at Posted at 2021-05-04

はじめに

CO2センサー(MH-Z19C)を購入したので、AWS IoTのお勉強も兼ねて、値を送ってみました。
なお。今回は送った値をS3に保存するようにしました。

準備

ハードウェア

今回使用したハードは以下の通りです。

  • ESP32-WROVER-E開発ボード(8MB)
    • 【注意】ハードウェアシリアルポートが1つしかないため、今回はPWMで接続しています
      ソフトウェアシリアル版はこちら
  • MH-Z19C
  • ブレッドボード
  • ジャンパーケーブル
  • USBケーブル
  • PC(Windows)

ソフトウェア

ArduinoIDEを使用するに当たり、いくつかライブラリをインストールしました。

  • MHZ19(githubからzipをダウンロードし、インストール)
  • ArdionoJson
  • PubSubClient
  • WiFiClientSecure
  • EspSoftwareSerial

配線

ESP32とMH-Z19Cの接続は以下の通りです。

  • ESP32のIO14番をMH-Z19CのPWMに接続
  • ESP32の5VをMH-Z19CのVinに接続
  • ESP32のGNDをMH-Z19CのGNDに接続

image.png

プログラム

まず、MH-Z19ライブラリを修正します。
オリジナルでは、計測範囲が2,000PPM固定になっているため、今回使用するMH-Z19Cに合わせ、5,000PPMまで測れるようにします。

MHZ19.h
(途中省略)

	// Pwm Data Flag
	uint8_t PWM_DATA_SELECT = MHZ19_PWM_DATA::CALC_5000_PPM; // 2000→5000
};

#endif

Ardiono側のプログラムは以下の通りです。

awsiot.ino
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <Arduino_JSON.h>

#include <MHZ19.h>

// WiFi設定情報(自分の無線LAN環境)
const char* SSID = "mySSID";  // 変更すること
const char* PASSWORD = "myPASSWORD";  // 変更すること

// AWS IoT設定情報
const char* AWS_ENDPOINT = "xxx.iot.ap-northeast-1.amazonaws.com";  // 変更すること
const int   AWS_PORT     = 8883;
const char* PUB_TOPIC    = "topic/fromDevice";
const char* SUB_TOPIC    = "topic/fromCloud";
const char* CLIENT_ID    = "esp32";

const char* ROOT_CA = "-----BEGIN CERTIFICATE-----\n" \
"****************************************************************\n" \
"-----END CERTIFICATE-----\n";  // 変更すること

const char* CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" \
"****************************************************************\n" \
"-----END CERTIFICATE-----\n";  // 変更すること

const char* PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" \
"****************************************************************\n" \
"-----END RSA PRIVATE KEY-----\n";  // 変更すること

// MQTT設定
#define QOS 0 // 届こうが届くまいが1回だけメッセージをPublishする(0か1を指定可)
WiFiClientSecure httpsClient;
PubSubClient mqttClient(httpsClient);

// MH-Z19C
const int pwm_pin = 14;
MHZ19* myMHZ19 = new MHZ19(pwm_pin);
char pubMessage[128];

void setup_wifi(){
  Serial.print("Connecting to ");
  Serial.println(SSID);

  // ESP32でWiFiに繋がらなくなるときのための対策
  WiFi.disconnect(true);
  delay(1000);

  WiFi.begin(SSID, PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup_awsiot(){
  httpsClient.setCACert(ROOT_CA);
  httpsClient.setCertificate(CERTIFICATE);
  httpsClient.setPrivateKey(PRIVATE_KEY);
  mqttClient.setServer(AWS_ENDPOINT, AWS_PORT);
  mqttClient.setCallback(mqttCallback);
}

void connect_awsiot() {
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (mqttClient.connect(CLIENT_ID)) {
      Serial.println("Connected.");
      mqttClient.subscribe(SUB_TOPIC, QOS);
      Serial.println("Subscribed.");
    } else {
      Serial.print("Failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" Try again in 5 seconds");
      // 5秒後にリトライ
      delay(5000);
    }
  }
}

void mqttCallback (char* topic, byte* payload, unsigned int length) {
    Serial.print("Received. topic=");
    Serial.println(topic);

    char subMessage[length];
    for (int i=0; i < length; i++) {
      subMessage[i] = (char)payload[i];
    }
    Serial.println(subMessage);

    // JSON前提でパースする
    JSONVar obj = JSON.parse(subMessage);
    // 今は受け取っても何も処理しない
}

void setup(){
  Serial.begin(115200);
  delay(100);
  
  setup_wifi();
  setup_awsiot();
}

void loop(){
  // CO2取得
  int CO2 = myMHZ19->getPpmPwm();

  // Publishするメッセージの作成
  sprintf(pubMessage, "{\"co2\": %d}", CO2);
  Serial.print("Publishing message to topic ");
  Serial.println(PUB_TOPIC);
  Serial.println(pubMessage);

  mqttClient.loop();
  while (!mqttClient.publish(PUB_TOPIC, pubMessage)) {
    if (!mqttClient.connected()) {
      connect_awsiot();
    }
    mqttClient.loop();
  }
  Serial.println("Published.");

  delay(1000*60*5); // 5min
}
  • SSIDに、接続するWi-FiのSSIDを設定すること
  • PASSWORDに、接続するWi-Fiのパスワードを設定すること
  • AWS_ENDPOINTに、デバイスデータエンドポイント(後述)を設定すること
  • ROOT_CAに、保存したルートCA(後述)を設定すること
  • CERTIFICATEに、ダウンロードしたxxx.pem.crt(後述の「このモノの証明書」)を設定すること
  • PRIVATE_KEYに、ダウンロードしたxxx-private.pem.key(後述の「プライベートキー」)を設定すること

なお、AWS IoTからのメッセージを受信できるようになっていますが、今は何もしていません。
(将来用です)

AWS IoT Coreの設定

ポリシーの作成

image.png
始めにポリシーを作成します。

image.png
適当な名前を指定し、以下の項目をそれぞれ指定します。

  • アクションに「iot:*」を指定する
  • リソースARNに「*」を指定する
  • 効果を「許可」する

image.png
結果、ポリシーが作成されました。

モノの作成

image.png
次にモノを作成します。

image.png
今回は「単一のモノを作成する」を指定します。

image.png
適当な名前を指定します。

image.png
続いて、1-Click証明書を作成するために「証明書を作成」を選択します。

image.png
作成された証明書をすべてダウンロードします。
また、AWS IoTのルートCAもダウンロードします。

image.png
ルートCAは、この画面の「Amazon Root CA 1」をダウンロードします。

なお、ここでダウンロードしたファイルの中身を、ArduinoIDEで設定します。

また、「有効化」をクリックします。

image.png
「無効化」に表示が変わりました。

image.png
最後に、モノにポリシーを設定します。

image.png
結果、モノが作成されました。

ルールの作成

image.png
最後にルールを作成します。

image.png
まず適当な名前を設定します。

image.png
続けて、ルールクエリステートメントを設定します。
今回は、ESP32から送られてきたメッセージ全部を使用するため、クエリを「SELECT * FROM 'topic/fromDevice'」としました。
(ESP32からMQTTで送るとき、「topic/fromDevice」にpublishしているため)

次に、アクションを設定するため「アクションの追加」を選択します。

image.png
送り先として「S3」を選択します。

image.png
送り先のS3のバケットとキー(ファイル名みたいなもの)を指定します。
今回指定したキーには、モノの名前と時刻を使用して一意になるようにしました。

続けてロールを設定するため、「ロールの作成」を選択します。

image.png
適当な名前を設定します。

image.png
作成したロールがアタッチされます。

image.png
結果、アクションが設定されました。

image.png
結果、ルールが作成されました。

デバイスデータエンドポイントの確認

image.png
ArduinoIDEで設定するデバイスデータエンドポイントの値を確認します。

動作確認

ちゃんと動いているかの確認のため、ESP32からデータを送ってみます。

まず、AWS IoT Coreに届いたかどうかは、テストで確認できます。

image.png
トピックのフィルターに「topic/fromDevice」を指定し、「サスクライブ」を選択すると、届いたメッセージが表示されます。

image.png
また、S3でファイルが保存されているかを確認します。

1620486637323.txt
{"co2": 1470}

テストで受け取った値と同じものが、S3のファイルにも設定されていました。

まとめ

実際に使用する際にはグラフ等で可視化することが多いので、IoT Coreから直接ElasticSearchに送ったり、いったんDynamoDBに入れたりすることになると思います。

参考URL

https://qiita.com/nara256/items/a3cecc5fbf043b2d042c
https://scrapbox.io/kn1cht/MH-Z19_CO2%E3%82%BB%E3%83%B3%E3%82%B5_on_ESP32

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?