LTE-M通信できなくなった時に確認したい7つの大罪

IoTデバイスを開発していると、NB-IoT, LTE-M, Sigfoxなど、様々な通信形式で取得データを送信したくなることがあります。

ファームウェアを書き込んで、**いざ通信！**と期待したものの、データがうまくクラウドに送信されていない。。。

ソースを読み直しても、正しく処理されているはずのに、どうして送ってくれないの？！！！

なんでぇぇぇーーーーー。

という状態に、一度ならず何度でも直面するかもしれません。

そんな時の簡易的なトラブルシューティングを、私の経験をもとに作ってみました。

なお、本記事ではLTE-M通信を対象にしているため、BG96モジュールにATコマンドを送ることを前提としております。


# LTE-M通信、不通時の7つの大罪
1. BG96へのUARTピンの接触不良
2. SIMカードが刺さっていない
3. 電波強度不足
4. 基地局との高い頻度での通信
5. 電源電力不足
6. バッファーオーバーフロー
7. スタックオーバーフロー


# BG96へのUARTピンの接触不良

BG96の開発ボードを使うにしろ、BG96モジュールを回路に組み込んで基板を起こすにしろ、メインCPUとBG96モジュールは基本的にはUARTで通信すると思います。

BG96へのUARTピンに関して、物理的に断線していたり、TXとRXを逆に接続していると、

**メインCPU: AT**
**BG96: (反応なし)**
**メインCPU: AT(あら、BG96君、生きてる？)**
**BG96: (反応なし)**

みたいなことが余裕で発生します。

ちなみに、**AT**がBG96に到達すると、**RDY**や**OK**と応答してくれます。

また、何かの弾みで、信号にノイズが乗って波形が鈍っても、うまく**AT**を認識してくれなくなります。


# SIMカードが刺さっていない

SIMカードを刺し忘れたり、SIMカードのソケットの配線が断線していると発生します。

LTE-M通信などは、Byteあたりの通信料金が高いので出来るだけ通信したくないんですよねーーーー。

そんな理由で、SIMカードを抜いておくと、こういう事態が余裕で発生します。

```
16:25:44.182 -> <- AT+CPIN?
16:25:44.182 -> -> 
16:25:44.182 -> -> +CPIN: READY
16:25:44.182 -> -> 
16:25:44.182 -> -> OK
```

というように、**AT+CPIN?**コマンドで、BG96がSIMカードを認識しているかどうか確認すれば、原因を切り分けることができます。

ちなみに、SIMカードを挿し忘れると、**+CME ERROR: 10**というレスが返ってきます。


# 電波強度不足

RSSI（Received Signal Strength Indicator）という指標で定量的に評価できます。

私がLTE-M通信していた環境（オフィスビル）では、だいたい -51dBmという結果で通信は安定していました。

しかし、バッグの中に入れて電車に乗った時や、モバイルルーターの電波が極端に入らない家などでは、-70dBmよりも悪い結果となり、あまり良いとはいえない通信環境もありました。

[電波強度の指標](https://www.metageek.com/training/resources/understanding-rssi.html
)を参考にして、通信環境の良し悪しを判断してみると良いでしょう。


# 基地局との高い頻度での通信

いやぁ、これが一番キツかった。

ずーっとうまく通信していたのに、突然1分間くらい、通信できなくなるのですから。

この大罪に遭遇したのは、LTE-M通信でのOTA-DFUを実装していた時です。

遠隔地にあるnRF52840のファームウェアを、LTE-M通信でアップデートするというアレです。

ファームウェアのサイズが、約90kBあり、一度にダウンロードするなんてできないので、512Byteずつ分割ダウンロードしていました。

ダウンロードしては外部のFlash ROMに書き込むという作業を繰り返していると、突然1分間くらい、うんともすんとも言わなくなるのです。

よく見ても、リセットはかかっていないからスタックオーバーフローではなさそうです。

その時は、1分以上待っていると、なぜか突然通信が再開されました。

各分割ダウンロード間のインターバルを2.5秒（省電力との兼ね合い）とかに設定を変えても、通信の中断は発生しました。

SORACOMさんのLTE-M通信を利用していたので、あまり通信を占領するのもよくないから仕方ないとは思います。

ただ、何も知らない状態で遭遇すると、マジで焦ります。


# 電源電力不足

IoTデバイスですから、バッテリ駆動としましょう。

ある環境のCO2濃度を測定してクラウドに送りたいとします。

CO2センサの電源を切ってから、BG96を起動してデータを送信すれば良さそうですが、何らかの制約があってCO2センサの電源を切るとBG96の電源も落ちてしまうとしましょう。

平均的な消費電力もあまり高くなさそうなので、データの送信には成功しそうです。

でも、データを送信しようとするとリセットがかかってしまうことがあります。

もしかしたら、データ送信のソースコードにバグがあったと思い、調べてみます。

でも、バグらしい部分はなく、電源をUSB給電に変えると安定しています。

ますます原因がわからなくなってきました。

そこで、バッテリの残量を調べてみると、3.7V出力のLiPoバッテリの出力が3.3Vしかありません。

充電してみると、送信に失敗することがなくなりました。

。。。
実はこれ、バッテリ残量の下限を何Vに定めるかということに関わってきます。

3.7V出力のLiPoバッテリでは、フル充電では4.2Vとか出ていたりします。

そして、使い続けてへたってくると、3.3Vとかにまで出力が落ちます。

遠隔地に置いたデバイスのバッテリ残量を知るために、出力電圧をADコンバーターで読み取った際に、**3.3Vあるからまだ大丈夫かな**なんて思っていると、突然消息が途絶えます。

BG96でLTE-M通信を行う際に、瞬間的に消費電力が大きくなります。

この時の消費電力をバッテリで賄えないと、リセットがかかってしまうのです。

対処法としては、バッテリ残量の下限に余裕を持たせることです。


# バッファーオーバーフロー

来ました。

組み込みの王道ですね。

バッファーオーバーフローに陥ると、後述するスタックオーバーフローと同様にリセットがかかります。

LTE-M通信時の受信データのサイズを少なめに見積もってしまい、小さめに配列を確保してしまうと発生します。

心に余裕を持ちましょう。


# スタックオーバーフロー

バッファーオーバーフローに並び、組み込みの王道ですね。

こちらは、LTE-M通信時の受信データを格納する配列を、極端に大きなサイズで確保した場合に発生します。

何も知らずに、

```
char buf[2048]
```

とかやっていたら、リセットがかかったことがあります。


# まとめ

このようにトラブルシューティングをある程度、型に落とし込めていると、問題が起きた時に対応しやすくなりますね。

7つの大罪をいい感じに避けて、良い組み込みライフを謳歌しましょう！