前回に、「[2]会議室使用状況センサーの自作 〜milkcocoaの設定〜」でIoTサーバのセットアップを行いました。
これまでIoTセンサーの製作、IoTサーバのセットアップが完了して、今回は三番目の「IoTデバイスのプログラミング」を行います。
1. 会議室使用状況センサーの実装構想(振り返り)
目標は、会議室に自作したIoT人感センサーを設置して、センサー状態を会社のスケジューラーであるサイボウズに表示させる。
実現方法としては以下のように考えて作ります。
1. マイコンと人感センサーを使って電子工作(IoTデバイス製作)
2. センサーデータの保管先IoTサーバのセットアップ
3. IoTデバイスのプログラミング←今回はこちらの話
4. JavaScriptで簡単なページを作成して、IoTサーバの情報を取得し表示
5. サイボウズガルーンに設定
2. IoTデバイスのプログラミングに向けて下準備
① 仕組みとフローチャート
下図の動作内容にもありますが、概要は以下の通り。
- 「センサーONの状態が10秒以上」and「前回IoTサーバへOFFを記録」or「ON状態が1時間以上」の場合:IoTサーバへONを書き込み
- 「センサーOFFの状態が60秒以上」and「前回IoTサーバへONを記録」or「OFF状態が1時間以上」の場合:IoTサーバへOFFを書き込み
② インストールするもの
では、いよいよESP8266でプログラミングを行っていくのですが、初めての場合いくつかインストールしなければいけないものがありますのでまずはここから。(以下が準備できているよという方は飛ばしてください)
1. Arduino IDEのインストール
ESP8266は、Arduino IDEでプログラミングを行って行きます。
Arduino.ccのサイトからArduino IDEをダウンロードしてインストールします。
2. FT-232RQドライバーのインストール
PCからESP8266への接続にはFT-232RQを使ってファームウェアの書き込みを行いますので、FTDI社からドライバーをインストールします。
3. milkcocoa SDKのインストール
最後にIoTサーバに接続するためのSDKをmilkcocoa(正確にはGithub)からダウンロードしておきます。
インストールしたArduinoIDEを起動し、メニューからスケッチ→ライブラリーをインクルード→ZIP形式のライブラリーをインストールを開き、ダウンロードしたzipを選択してインストールして行きます。
インストールが完了すると、ライブラリーをインクルードの中の一覧に「milkcocoa ESP8266 SDK」というものが追加されます。
3. スケッチング(プログラミング)
余談ですが、Arduinoではプログラムをスケッチと呼ぶそうです。
「2. センサーデータの保管先IoTサーバのセットアップ」で保管していた情報を、以下の定数にセットしています。
(AAAAA~EEEEEの部分)
定数 | 値 | 仮定数値 |
---|---|---|
ROOM_NAME | ESP8266のIoTにつける名前 | AAAAA |
MILKCOCOA_APP_ID | milkcocoaでのapp_id値(例:hotjlhxspy2) | BBBBB |
MILKCOCOA_API_KEY | milkcocoaでのAPI KEY値 | CCCCC |
MILKCOCOA_API_SECRET | milkcocoaでのAPI SERCRT値 | DDDDD |
MILKCOCOA_DATASTORE | milkcocoaでのデータストア名 | EEEEEE |
ちょっと長いですが、スケッチの全貌
#include <ESP8266WiFi.h>
#include <Milkcocoa.h>
// Room settings
#define ROOM_NAME "AAAAA"
#define USE 1
#define VACANT 2
// Flag settings
char initial_flg = 0;
char ON_Cnt_Check = 5; // センサーONが5カウントされるとmilkcocoaへ書き込み
char OFF_Cnt_Check = 30; // センサーOFFが30カウントされるとmilkcocoaへ書き込み
int Alive_Check = 60*60/2; // Sensor_ONまたはOFFの状態が続く場合、1時間ごとに実行(/2は、deleyで1s、処理で1sの2秒かかっているため)
int Sensor_ON_Flg = 0;
int Sensor_OFF_Flg = 0;
char SensorStatFlg = 0;
// milkcocoa settings
#define MILKCOCOA_APP_ID "BBBBB"
#define MILKCOCOA_API_KEY "CCCCC"
#define MILKCOCOA_API_SECRET "DDDDD"
#define MILKCOCOA_DATASTORE "EEEEE"
#define MILKCOCOA_SERVERPORT 1883
const char MQTT_SERVER[] PROGMEM = MILKCOCOA_APP_ID ".mlkcca.com";
const char MQTT_CLIENTID[] PROGMEM = __TIME__ MILKCOCOA_APP_ID;
WiFiClient client;
Milkcocoa *milkcocoa = Milkcocoa::createWithApiKey(&client, MQTT_SERVER, MILKCOCOA_SERVERPORT, MILKCOCOA_APP_ID, MQTT_CLIENTID, MILKCOCOA_API_KEY, MILKCOCOA_API_SECRET);
// WiFi AP Settings
const char ssid[] = "FFFFF";
const char pass[] = "GGGGG";
// sensor Pin settings
int SensorPin = 14;
int WifiStatPin = 4;
int SensorStatPin = 5;
void setup() {
// for status check
Serial.begin(115200);
delay(50);
// ESP8266 IO pin setup
pinMode(SensorPin, INPUT);
pinMode(WifiStatPin, OUTPUT);
pinMode(SensorStatPin, OUTPUT);
digitalWrite(WifiStatPin, LOW);
digitalWrite(SensorStatPin, LOW);
// WiFi connecting
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
delay(1000);
// for status check
Serial.println("WiFi Connecting...");
digitalWrite(WifiStatPin, HIGH);
while (WiFi.status() != WL_CONNECTED) {
// for status check
Serial.print(".");
digitalWrite(WifiStatPin, LOW);
delay(300);
digitalWrite(WifiStatPin, HIGH);
delay(1000);
}
// for status check
Serial.println("WiFi Connected!");
}
void loop() {
milkcocoa->loop();
// 起動確認(起動初回時のみ実行)
if(initial_flg == 0){
DataElement elem = DataElement();
elem.setValue("RMname", ROOM_NAME);
elem.setValue("stat", "UpLink");
milkcocoa->push(MILKCOCOA_DATASTORE, &elem);
initial_flg = 1;
}
// Uplode of Sensor Stats for MQTT
SensorStats();
delay(1 * 1000);
}
void SensorStats() {
// センサー状態取得
int SensorStat = digitalRead(SensorPin);
// for status check
Serial.print("Pin out: ");
Serial.println(SensorStat);
if (SensorStat == 1) {
digitalWrite(WifiStatPin, LOW);
digitalWrite(SensorStatPin, HIGH);
// (Sensor_ONが5回カウント&SensorStatFlgが以前と違う値)またはSensor_ONが1時間同じ状態の場合に実行(deley1sの他、処理で1s使用)
if ((Sensor_ON_Flg > ON_Cnt_Check && SensorStatFlg != USE) || Sensor_ON_Flg > Alive_Check) {
send_milkcocoa(USE); // in use
SensorStatFlg = USE;
} else {
if(Sensor_ON_Flg > ON_Cnt_Check){
Sensor_OFF_Flg = 0;
}
Sensor_ON_Flg += 1;
}
} else {
digitalWrite(SensorStatPin, LOW);
digitalWrite(WifiStatPin, HIGH);
if ((Sensor_OFF_Flg > OFF_Cnt_Check && SensorStatFlg != VACANT) || Sensor_OFF_Flg > Alive_Check) {
send_milkcocoa(VACANT); // vacant
SensorStatFlg = VACANT;
} else {
if(Sensor_OFF_Flg > OFF_Cnt_Check){
Sensor_ON_Flg = 0;
}
Sensor_OFF_Flg += 1;
}
}
}
void send_milkcocoa(char Room_Stat){
// for status check
Serial.print("ON_flg: ");
Serial.println(Sensor_ON_Flg);
Serial.print("OFF_flg: ");
Serial.println(Sensor_OFF_Flg);
Sensor_ON_Flg = 0;
Sensor_OFF_Flg = 0;
DataElement elem = DataElement();
elem.setValue("RMname", ROOM_NAME);
switch (Room_Stat) {
case USE:
elem.setValue("stat", "IN USE");
// for status check
Serial.println("Stat: in use");
break;
case VACANT:
elem.setValue("stat", "Vacant");
// for status check
Serial.println("Stat: Vacant");
break;
}
milkcocoa->push(MILKCOCOA_DATASTORE, &elem);
}
ちょっと長くなりましたが、今回はここまで。
次回は、「Javascriptsで簡単なページを作成し、センサーの状態を表示する」サイトを作成していきます。
コメント