[3]会議室使用状況センサーの自作 〜ArduinoでESP8266のプログラミング〜

電子工作
スポンサーリンク

前回に、「[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
  2. FT-232RQドライバー
  3. milkcocoa SDK

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_NAMEESP8266のIoTにつける名前AAAAA
MILKCOCOA_APP_IDmilkcocoaでのapp_id値(例:hotjlhxspy2)BBBBB
MILKCOCOA_API_KEYmilkcocoaでのAPI KEY値CCCCC
MILKCOCOA_API_SECRETmilkcocoaでのAPI SERCRT値DDDDD
MILKCOCOA_DATASTOREmilkcocoaでのデータストア名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で簡単なページを作成し、センサーの状態を表示する」サイトを作成していきます。

コメント

タイトルとURLをコピーしました