【IoT】 ESP8266에서 온습도 취득하여 스마트폰으로 모니터링 제1회

9612 단어 ArduinomqttESP8266

개요



① ESP8266에서 온습도 센서(AM2320)를 사용하여 온습도를 수집하고 MQTT로 데이터를 날린다.
②Xamarin.Android로 만든 Android 앱으로 모니터링.

소개



EPS8266으로 쉽게 IoT를 만들 수 있다는 것을 알고 빠르게 도전해 보았습니다.

모처럼이므로, 수집한 데이터를 스마트폰으로 모니터링하는 앱도 제작했습니다.
투고의 재료가 되도록(듯이), Java가 아니고, 조금이라도 샘플 소스가 증가하면(자) Xamarin.Android C#로 제작해 보았습니다.
개요 ①~②를 완성하기까지 40~50시간 정도 걸리고 있습니다.
(꽤 까다로운 부분이 많았기 때문에 시간이 걸렸습니다.)
또, 최초의 투고 때문에, 투고에 있어서 설명 부족이나 룰이 지키지 않은 곳 등 있으면 지적해 주세요.

전체 구성 및 환경



그림 1은 센서에서 얻은 데이터를 스마트 폰으로 모니터링하는 구성입니다.
Arduino 측도 Visual Studio에서 개발할 수 있음을 알고 모두 Visual Studio 2017 Community에서 개발하고 있습니다.

그림 1. 모니터링

또한 MQTT는 양방향으로 데이터의 송수신이 가능하기 때문에 Android 앱 측에서 ESP8266에 수집주기 설정을 할 수 있도록 해 보았습니다. (그림 2 참조)

그림 2. 주기 변경

환경 설정



여기에서는 환경 설정 절차나 MQTT에 대한 자세한 설명은 하지 않습니다. 참고까지 아래 URL을 확인하십시오.

Visuial Studio 2017 Community 설치



Arduino IDE for Visual Studio 설치



mosquitto 설치



WireShark 설치



WireShark는 필수는 아니지만 MQTT가 있는지 확인하려면 설치하십시오.
ver2 이후로 MQTT 대응하고 있다고 합니다.
ht tp // // 흠 st. 와 tch. 예 mp rs. 이. jp / ぃ b 등 ry / 그 f와 ぁれ / うぃれ rk /

Arduino 구현



그림 3은 제작한 회로입니다.
왼쪽의 검은 직육면체의 물체가 온습도 센서입니다.
Arduino에서 프로그램을 작성할 때 오른쪽의 검은 선을 점퍼 핀 등으로 연결하십시오.

그림 3. 회로

스케치



ssid와 password, 각 IP 주소는 각 환경에 맞게 설정하십시오.
getDateTime() 로 현재 일시를, getCycle 함수로, 수집 주기를 취득합니다.
”if (tm->tm_sec % cycle == 0) {” 부분에서 매 정시일 때만 동작하도록 체크하고 있습니다.
getData 함수로 데이터를 검색하고 client.publish로 데이터를 전송합니다.
callback 함수는, 스마트폰측으로부터 MQTT로 송신된 데이터를 수신했을 때에 불리는 함수로, 수신한 주기를 메모리에 기입하고 있습니다.

mqtt_esp8266.ino
#include <ESP8266WiFi.h>        // WiFiモジュールのライブラリ
#include <DHT.h>                // DHTセンサのライブラリ
#include <Adafruit_Sensor.h>
#include <Arduino.h>
#include <time.h>
#include <ArduinoJson.h>        // JSONライブラリ
#include <EEPROM.h>
#include "PubSubClient.h"       // MQTTのライブラリ

const char* ssid = "XXXXXXXX";              // WiMAXのSSID
const char* password = "XXXXXXX";           // WiMAXのパスワード
//const char* mqtt_server = "broker.mqtt-dashboard.com";
//const char* mqtt_server = "iot.eclipse.org";
const char* mqtt_server = "192.168.179.3";      // ローカルPC
const char* topic  = "thermo";                  // topic
const char* topic2 = "setting";                 // 収集周期変更用のtopic
char message_buff[100];
StaticJsonBuffer<200> jsonBuffer;

#define DHTPIN 4                                // 温湿度計PIN番号
#define DHTTYPE DHT22
#define JST     3600*9


WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
long lastMsg = 0;
char msg[50];
float humidity = 0.0;
float tempC = 0.0;
time_t t;
struct tm *tm;
char *datetime = "2017/01/01 00:00:00";
int cycle = 10;                 // 収集周期(秒)


void setup() {
    //pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
    Serial.begin(115200);
    WiFi.config(IPAddress(192, 168, 179, 200), IPAddress(192, 168, 179, 1), IPAddress(255, 255, 255, 0));
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    client.setCallback(callback);
    // DHT起動
    setup_DHT();
    delay(100);
    configTime(JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
}

/// <summary>
/// WiFiセットアップ
/// </summary>
void setup_wifi() {

    delay(1000);
    // We start by connecting to a WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    // WiFi起動
    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());
    client.subscribe(topic2);
    Serial.print("subscribe:");
    Serial.println(topic2);
}

/// <summary>
/// DHTセットアップ
/// </summary>
void setup_DHT() {
    delay(1000);
    dht.begin();
    delay(2000);
    while (dht.read() == false) {
        dht.begin();
        Serial.println("dht読み込みできません。");
        dht.begin();
        delay(2000);
    }
}

void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    // 初期化
    memset(message_buff, '\0', sizeof(message_buff));
    for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
        message_buff[i] = payload[i];
    }
    Serial.println();

    String msgString = String(message_buff);
    JsonObject& root = jsonBuffer.parseObject(msgString);
    if (root.success() == true) {
        cycle = root["cycle"];
        // 収集周期をメモリに書き込み
        byte b_cycle = (cycle & 0xFF);
        Serial.print("b_cycle=");
        Serial.println(b_cycle);
        EEPROM.write(0, b_cycle);
    }
}

void reconnect() {
    // Loop until we're reconnected
    while (!client.connected()) {
        Serial.print("Attempting MQTT connection...");
        // Attempt to connect
        if (client.connect("ESP8266Client")) {
            Serial.println("connected");
            client.subscribe(topic2);
            Serial.print("subscribe:");
            Serial.println(topic2);
        }
        else {
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}


int getCycle() {
    int temp;
    temp = EEPROM.read(0);
    if (temp != 0) {
        cycle = temp;
    }
    Serial.print("収集周期:");
    Serial.println(cycle);
    return cycle;
}


void loop() {

    if (!client.connected()) {
        reconnect();
    }
    client.loop();

    // 時刻取得
    getDateTime();
    // 収集周期取得
    getCycle();

    long now = millis();
    // 毎正時に取得
    if (tm->tm_sec % cycle == 0) {
        // 温度・湿度取得
        getData();
        int retrycount = 0;
        while (isnan(humidity) || isnan(tempC)) {
            getData();
            retrycount++;
            if (retrycount > 2) {
                setup_DHT();
                return;     // loop()の始めに戻る
            }
        }

        String json = buildJson();
        Serial.print("json=");
        Serial.println(json);
        char jsonStr[200];
        json.toCharArray(jsonStr, 200);
        client.publish(topic, jsonStr);
        delay(1000);        // 連続パブリッシュ防止
    }
    else {
        Serial.print("遅延時間=");
        Serial.println(cycle - (tm->tm_sec % cycle));
        delay((cycle - (tm->tm_sec % cycle)) * 1000);
    }
}

String buildJson() {
    String json = "{";
    json += "\"devices\": \"freeboard\"";
    json += ",";
    json += "\"datetime\":\"";
    json += datetime;
    json += "\",";
    json += "\"payload\":";
    json += "{";
    json += "\"humidity\":";
    json += humidity;
    json += ",";
    json += "\"temperature\":";
    json += tempC;
    json += "}";
    json += "}";

    return json;
}

/// <summary>
/// 温度・湿度取得
/// </summary>
void getData() {
    humidity = dht.readHumidity();
    Serial.print("湿度:");
    Serial.println(humidity);
    tempC = dht.readTemperature();
    Serial.print("温度:");
    Serial.println(tempC);
}

/// <summary>
/// 日時取得
/// </summary>
void getDateTime() {
    while (true) {
        t = time(NULL);
        Serial.print("t=");
        Serial.println(t);
        tm = localtime(&t);
        sprintf(datetime, "%04d/%02d/%02d %02d:%02d:%02d",
            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec);
        Serial.println(datetime);
        if (t == 0) {
            delay(1000);
        } else {
            break;
        }
    }
}

문제해결



어려운 점은, 이 회로에서는 센서로부터 온습도를 취득할 수 있거나 할 수 없게 합니다.
아직 해결되지 않았습니다. 원인으로 생각되는 것은
1. 회로가 올바르지 않습니다.
2. 중고로 온습도 센서를 구입한 탓인지 어딘가 파손되고 있다.
3. 프로그램이 올바르지 않습니다.
라고 생각할 수 있습니다.
데이터를 취득할 수 있을 때가 있으므로, 망가지고 있는 것은 없다고 생각합니다만 어떻습니까. 뭔가 트러블이 있을 때 원인을 파악하기에 잘라내기가 어렵습니다.

결론



제1회에서는, 환경 구축과 Arduino의 설명을 했습니다.
Android 앱측은 제2회에 게재했습니다.
여기를 참조하십시오.
ぃ tp // m / pokota 5260 / ms / b2721 2cf69f0 ed2c입니다.
github 링크도 나중에 붙여 넣습니다.

좋은 웹페이지 즐겨찾기