見出し画像

【IoT】SORACOM LTE-M Button Plusで機械設備の異常検知と復帰検知を実現する2 〜ソフト設計編〜

SORACOM LTE-M Button Plusに簡単な基板を追加することで、異常検知だけでなく復帰通知とハートビートを実現することができました。本記事ではソフト設計についてまとめます。


背景と目的

設備維持管理の実務において、
・設備異常時に通知を得たい!
・設備復帰時にも通知を得たい!
・IoTデバイス自体の不具合監視のため、一定期間ごとに通知を得たい!
というニーズがあり、これら3つをSORACOM LTE-M Button Plusで実現できれば便利です。便宜上、これらの通知を、①設備異常時、②設備復帰時、③ハートビートと定義します。
構想としては、SORACOM LTE-M Button Plus(以下、ボタン)に、ATtiny13Aマイコンを用いた基板を追加し、ATtiny13Aマイコンに①〜③の状態監視、およびSORACOM LTE-M Button Plusへのパルス波送信の役割を担わせます。
前回の記事では①〜③を実現するためのハード設計についてまとめました。

本記事ではソフト設計についてまとめます。

いかに待機電流を抑えるか?

電池駆動型IoTデバイスを開発する上で、最も重要な点の一つは、いかに待機電流を抑えるかです。
ATtiny13Aの待機電流を抑えるための工夫について整理します。

1. sleep modeを用いる

スリープモードの中でも最も待機電流が低い
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
でスリープモードを定義し、
sleep_mode();
でスリープさせることで、待機電流を抑えることができます。
delay();ではなく、sleep_mode();でスリープさせます。

2. WDTでマイコンを起こす

スリープさせたマイコンを起こすため、ウォッチドッグタイマー(以下、WDT)を用います。WDTとは、システムが予期せぬ状態に陥った時に自動的にリセットするためマイコン内のタイマーですが、このタイマーを用いてリセットではなく、指定したプログラムを動かします。今回の場合は、設備状態判断のプログラムを動かします。
WDTCR |= (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (1 << WDP0); // 8s
WDTCR |= (1 << WDTIE); // 割り込みモードを有効化
sei(); // グローバル割り込みを有効化

3. ADCをOffにする

この記事を参考にすると、ADCを無効化すると低消費電力になるようです。実際に計測すると、私自身の環境では大きな差はありませんでしたが、今回はADCを無効化コードを追加することにします。
ADCSRA &= ~(1 << ADEN);

4. 外部プルアップ抵抗を用いる

この記事を参考に、内部プルアップ抵抗ではなく、外部プルアップ抵抗を用います。

5. 待機電流が4μAに

私の環境では、待機電流を4μA@2.73V(=10.92μW)まで下げることができました。単3ニッケル水素電池2本で駆動させた場合、電池容量を1900mAとすると、
1900mAh x 1.2V/本 x 2本 = 4560mWh
4560mWh / 10.92μW = 47年
ですね。実際はパルス波生成時に7.5mA程度流れたり、電池の放電もあるため、ここまでは持ちませんが、十分です。単4x2でも大丈夫ですね。

プログラム全文を公開

上記を反映したプログラムを書きました。概要としては、ATtiny13Aを用い、一定期間ごとに設備状態を監視し、①〜③の状態であれば、状態に応じたパルス波をSORACOM LTE-M Button Plus送信しています。このパルス波を受け取ったSORACOM LTE-M Button Plusは、パルス波に応じたclickTypeをクラウドに送信する仕組みです。
下記プログラムでは、8秒ごとに設備状態を監視し、24時間ごとにハートビートを送信しています。なお、ハートビート間隔を1440分で定義すると、実測ベースで1.12倍ほどずれたため、その分補正しています。WDTタイマーの誤差ですかねー。
以下、プログラム全文です。

#define PIN_IN 3   // pin 2
#define PIN_OUT 4  // pin 3

volatile bool last_status = HIGH;
volatile uint16_t count = 0;
volatile uint8_t clickType = 0;

const uint16_t INTERVAL_SEC = 8;  // ★8秒の倍数にすること
const uint16_t HARTBEAT_MIN = 1440;
const float WDT_HOSEI = 1.12;  // ハートビートを60分ごとにした場合67分になる。1.12倍。この分を補正する。
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>

ISR(WDT_vect) {
  // カウントを+1
  count++;

  // 初期値設定
  clickType = 0;

  // INTERVA_SECごとに正常→異常、異常→正常を判断
  if (count % (INTERVAL_SEC / 8) == 0) {

    // 接点がクローズした際、SORACOM LTE-M Button Plusをロングクリックする。3が送信される。
    if (digitalRead(PIN_IN) == LOW && last_status == HIGH) {
      clickType = 3;
      last_status = LOW;
      count = 0;
    }

    // 接点がオープンした際、SORACOM LTE-M Button Plusをダブルクリックする。2が送信される。
    if (digitalRead(PIN_IN) == HIGH && last_status == LOW) {
      clickType = 2;
      last_status = HIGH;
      count = 0;
    }
  }

  // 前回の送信からHARTBEAT_SEC以上経ったとき、SORACOM LTE-M Button Plusをシングルクリックする。1が送信される。
  if (count / 60 * 8 >= HARTBEAT_MIN / WDT_HOSEI) {  // count*6/80だとNG。注意。
    clickType = 1;
    count = 0;
  }
}

void send_clickType1() {
  digitalWrite(PIN_OUT, HIGH);
  delay(500);
  digitalWrite(PIN_OUT, LOW);
}
void send_clickType2() {
  digitalWrite(PIN_OUT, HIGH);
  delay(500);
  digitalWrite(PIN_OUT, LOW);
  delay(500);
  digitalWrite(PIN_OUT, HIGH);
  delay(500);
  digitalWrite(PIN_OUT, LOW);
}
void send_clickType3() {
  digitalWrite(PIN_OUT, HIGH);
  delay(1500);
  digitalWrite(PIN_OUT, LOW);
}

void setup() {
  pinMode(PIN_OUT, OUTPUT);
  pinMode(PIN_IN, INPUT);  // 待機電流低減のため、内部プルアップ抵抗ではなく、外部プルアップ抵抗を使う。

  ADCSRA &= ~(1 << ADEN);  // ADCを無効化
  WDTCR |= (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (1 << WDP0);  // 8s
  WDTCR |= (1 << WDTIE);                                           // 割り込みモードを有効化
  sei();                                                           // グローバル割り込みを有効化
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // 初回はclickType = 3or2を送信
  if (digitalRead(PIN_IN) == LOW) {
    clickType = 3;
  } else if (digitalRead(PIN_IN) == HIGH) {
    clickType = 2;
  } else {
    clickType = 1;  // 1になることはないが念のため
  }
}

void loop() {
  // clickTypeの値に基づいて処理を実行
  if (clickType == 3) {
    send_clickType3();
  } else if (clickType == 2) {
    send_clickType2();
  } else if (clickType == 1) {
    send_clickType1();
  } else {
    // No action
  }

  sleep_mode();  // スリープモードへ
}

Arduino経由でATtiny13Aにプログラムを書き込む

作成したプログラムをATtiny13Aに書き込む方法に関し、この記事を参考にしました。
私が工夫した点は、ATtiny13AとArduinoとをジャンパーピンで接続するのが面倒だったため、プログラム書き込み用に「Arduino Shield for ATtiny13」を作り、この手間を低減させました。これは便利ですよ。

まとめと今後の課題

機械設備の監視にSORACOM LTE-M Button Plusを用いる前提で、記事を書きましたが、
・設備監視だけでなく、開閉検知など何かON/OFFで検知できるものの監視
・設備異常発生時に1回のみクラウドに送信するのではなく、設備異常発生時は定期的にクラウドに送信する
など、設備以外への応用や、柔軟なプログラム設計による応用ができそうだと感じています。可能性が広がります!!!

参考

・ボタンで異常通知する方法についてこちらにまとめています

・ボタンで異常通知/復帰通知/ハートビートを実現する方法(ハード設計編)

・ボタンで設備復帰通知を実現するうえで、非常に参考になった素晴らしい記事!!!

・ATtiny13Aの低消費電力駆動について、これも参考しました

・ライブラリに関する詳細です


この記事が気に入ったらサポートをしてみませんか?