工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

水田の水位をリモートで監視するシステムを作る(4)

概要

ESP-WROOM-32のプログラムを作成した。


背景と目的

前回、回路設計と実装を行って動作を確認した。今回は、ESP-WROOM-32のプログラム実装を行う。


詳細

1.主な仕様

今回作成するプログラムの主な仕様は以下。

  • 水位センサの状態、通信モジュール内蔵の温度センサ値、電源電圧を取得する
  • 取得したデータを送信する
  • 上記処理が終わったら、Deep Sleepモードに移行し、一定時間後に再起動させる

2.実装

2.0 ヘッダ読み込み、定数たち

  • ヘッダは、deep sleepの設定のため、esp_deep_sleep.hが必要。
  • UnaShieldの設定は、unabiz-arduinoのサンプルDemoTestUnaShieldV2SRCZ3に倣う。
  • GPIO番号、スリープ待ち時間などを定義
#include "SIGFOX.h"
#include "esp_deep_sleep.h"

// UnaShieldの設定
static const String device = "NOTUSED";  //  Set this to your device name if you're using UnaBiz Emulator.
static const bool useEmulator = false;  //  Set to true if using UnaBiz Emulator.
static const bool echo = true;  //  Set to true if the SIGFOX library should display the executed commands.
static const Country country = COUNTRY_JP;  //  Set this to your country to configure the SIGFOX transmission frequencies.
static UnaShieldV2S transceiver(country, useEmulator, device, echo);  //  Uncomment this for UnaBiz UnaShield V2S Dev Kit
static String response;  //  Will store the downlink response from SIGFOX.

// GPIO番号
static const int PIN_UNAGND = 32; // UNAGND
static const int PIN_SENSOR11 = 33;
static const int PIN_SENSOR12 = 25;
static const int PIN_SENSOR21 = 26;
static const int PIN_SENSOR22 = 27;

// スリープの待ち時間[hour]
static const int DS_HOUR = 12;


2.1 setup関数

シリアルの初期化、GPIOの設定、deep sleepの設定等を行う。 deep sleepの設定は、こちらを参考にしている。

void setup() {
  
  // シリアルの初期化
  Serial.begin(9600);
  Serial.println(F("Running setup..."));

  // GPIOの設定
  pinMode(PIN_UNAGND, OUTPUT);
  pinMode(PIN_SENSOR11, INPUT);
  pinMode(PIN_SENSOR12, INPUT);
  pinMode(PIN_SENSOR21, INPUT);
  pinMode(PIN_SENSOR22, INPUT);

  // deep sleepの設定
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF);

  Serial.println(F("setup OK."));
}


2.2 loop関数

  • まず、UnaShieldの電源を入れるために、GPIO32をHIGHにして、UnaShieldのGNDラインを導通させる。
  • 通信モジュールを初期化し、温度センサ、電源電圧、センサ値を取得。センサ値は、4つのセンサのHIGH/LOW値を下位4ビットに割り当てているが、後述するように4バイトのfloatが必要のようなので、floatの変数に格納
  • 取得したデータを、msgという変数に格納し、sendMessage関数で送信
  • 送信が終わったら、UnaShieldの電源を遮断するため、GPIO32をLOWに戻す
  • 最後に、ESP-WROOM-32をdeep sleepへ移行し、指定時間後に再起動させる
void loop() {

  // モジュールの電源を入れる
  Serial.println("UnaShield power on");
  digitalWrite(PIN_UNAGND, HIGH);
  delay(1000);
  
  // 通信モジュールの初期化
  if (!transceiver.begin()) stop(F("Unable to init SIGFOX module, may be missing"));

  // 温度を測る
  delay(2000); // よくわからないが入れないとちゃんと計測できない
  float temperature;
  transceiver.getTemperature(temperature);

  // 電源電圧
  float voltage;
  transceiver.getVoltage(voltage);

  // センサの状態を測る
  // 最下位4ビットにセンサ値を入れる
  float leveldata = 0;
  leveldata += digitalRead(PIN_SENSOR11) * 1;
  leveldata += digitalRead(PIN_SENSOR12) * 2;
  leveldata += digitalRead(PIN_SENSOR21) * 4;
  leveldata += digitalRead(PIN_SENSOR22) * 8;

  // データを作成
  Message msg(transceiver);
  msg.addField("lvl", leveldata);  //  4 bytes for the leveldata.
  msg.addField("tmp", temperature);  //  4 bytes for the temperature.
  msg.addField("vlt", voltage);  //  4 bytes for the voltage.
  // Total 12 bytes out of 12 bytes used.

  // 送信
  Serial.print("sendMessage");  
  if (msg.send()) {
    Serial.println("msg.send success!");
  } else {
    Serial.println("msg.send error!");
  }

  // UnaShieldの電源を遮断する
  Serial.println("UnaShield power off");
  digitalWrite(PIN_UNAGND, LOW);

  // スリープに入る
  Serial.println("Going to sleep now");
  esp_deep_sleep_enable_timer_wakeup(DS_HOUR * 60 * 60 * 1000 * 1000);
  esp_deep_sleep_start();
  
}

2.4 2019/05/04追記

esp_deep_sleep_enable_timer_wakeupの引数に、数時間という大きな値を入れると、うまくスリープしなくなる。こちらに解決策が載っていたので、参考にして以下のように修正

  • 修正前
esp_deep_sleep_enable_timer_wakeup(DS_HOUR * 60 * 60 * 1000 * 1000);
  • 修正後
uint64_t sleepTime = uint64_t(DS_HOUR * 60 * 60);
esp_deep_sleep_enable_timer_wakeup(uint64_t(sleepTime * 1000000L));


3.動作確認

上記プログラムを実行し、(スリープ時間は確認のため短め)SORACOMのharvestのコンソールで、送信結果を見たところ、ちゃんと送信されていた! というわけで、プログラムは完成。 ※水位センサはAmazonマーケットプレイスで海外発送のものを注文したところ、通関で没収されるという不運に見舞われ、再購入して配達待ち。ので、センサ値取得部分は適当なのだが。。。

f:id:dekuo-03:20190428220145p:plain


まとめ

プログラムの作成と動作確認ができた。次回は、筐体の設計、実装、そしていよいよ現場に持ち込んで仮稼働させてみたい。