【SALZmini2022作製日誌】もういっそこのままの状態が長く続けばよいのに。。。
はじめに
まずはじめにお断りしておきますが、今回の記事で目新しい進展はとくにありませんでした。自動水やり装置の作製の過程を記録する内容となっているため、毎回同じようなことでつまづいたり、ふりだしに戻ったりしています。もちろん装置がうまくできた暁には完成記事を書きたいという気持ちは持っています。
ですが、今のこの状況こそが一番幸福な時間だと思っています。
考えたことがうまく行ったら喜ぶし、ダメならなにくそと思い改善策を練る。このサイクルがうまく回っている時が、ものづくりの醍醐味だと思います。
今回も楽しみながら、もがいてみようと思います。
前回の記事
もうそろそろ完成してもよいと思われるSALZmini2022ですが、細かい不具合や気に入らない所が多くなかなか完成に至りません。
現時点での課題をまとめてみます。
管理関係の動作が不安定
水分量のチェック水やり動作についてはまだあまりチェックできていませんが、おそらく正常に動いていそうです。問題はSMGatewayのログが、半日程度でデータが途切れてしまうことです。思い付きの産物なのできちんとソースを見ていないのも問題ですが、装置の状態が今一つ掴みにくいのも原因です。
シリアルモニタをずっと挟めていればたくさんの情報を得られるのですが、屋外の環境にモニタ装置となるPCやスマホを長時間置くことに抵抗があります。本当に必要ならば考えますが今の所は何かいい方法がないか検討中です。ひとつずつ問題点を確認しながら直していきたいと思います。
レシーバーが今一つ
もう少し、機能を持たせることはできないだろうか?
現在、SALZmini2022、BOWL、SMGatewayの三つ巴でシステムを回していますが、可用性の観点から、SALZmini2022、BOWLで完結し、SMGatewayは補助的に利用したいです。
ただ、時系列データの管理を考えたとき、Ambientサービスを用いれば、難しいことを考えることはなくデータを定期的に送信するだけで実装できるので、まずは実績のあるこの方法を用いていました。
まだ色々調べていない状態で、この問題に対する課題は
過去データの保持、送信
タイムスタンプの管理
であると思います。
受け側のBOWLは常時起動しておらず、必要な時に情報を取得したり設定したりします。
このため上記データの保持はできません。
となると、データはSALZmini2022側で管理することになります。
BLEのnotify信号で過去データを送れるかどれぐらいの内容をどんなふうに送るのか調べてみなければなりません。
また、タイムスタンプ機能についてはSALZmini2022側で時計の管理をするかどうかを考える必要があります。
一般的にM5Stackのようなマイコンで時間の管理をするにはどうすればよいでしょうか?
真っ先にひらめくのはmills()関数を使うことです。mills()関数は、装置が起動してからの時間をミリ秒で保持しています。サイズはunsigned longなので、約50日ぐらいカウントできる仕様となっています。
最終的には50日以上稼働させる装置を目指していますが、カウントは50日あれば十分です。
プログラマの性として50日目でカウンタがリセットされてしまった場合の回り込み処理がとても気になります。
ならば、無視する。もしくは、上記条件で別処理をする。で何とかなりそうです。
mills()の値、水分量%ほかデータを一定間隔で保持しておき、リクエストに応じてBOWLに流します。
BOWLではこのデータを受けて、グラフを表示します。
という構想が思い浮かびました。
そういえば、クラゲさんのブログに、グラフに関する情報がありました。
SmoothChart というライブラリを用いているようです。
確かに実装できれば素晴らしいのですが、よく見るとリアルタイムのストリーミングデータを扱っています。
今作りたいものは、一括して読み込んだデータセットのグラフ化なので、別を当たった方がよいかもしれません。
色々見ているうちにこちらに当たりました。
一度こちらを試してみたいと思います。
という感じで、実際の作業に入っていきます。
管理関係の動作が不安定
について、取り組みます。
基本的なことですが、コンパイラに頼ってみることにしました。
[ファイル]-[環境設定]のコンパイラの警告レベルを引き上げてみます。
確かに表示されるメッセージは多くなりましたが、Warning は出ないし、新たな問題点は出せませんでした。
BLE通信の部分をもう少ししっかり見直す必要がありそうです。
サンプルコード、参考情報を元にテストコードを書いて、実験を繰り返す。これをやらないと安心できなくなってきました。
SMTesterの作製
SALZmini2022.inoを元にWarterringUnitに関連する部分をStubにして、適当な値を返すテストプログラムを作成しました。
int
GetCurrentWaterLevel(void) {
// テスト用 10~90の値を返す。
static float th = 0.0;
th += 2.0 * PI / 36.0;
if (th > 2.0 * PI)
th = 0.0;
return cos(th) * 40.0 + 50.0;
}
Serial.Print()でコメント出力を行っているので、PCにつないだ状態で動作させ、BLE接続ができなくなる原因を調べることにしてみました。
半日動作させてみた所、同様の現象が発生しました。シリアルモニタの様子はこんな感じでした。
ということは、SMTesterのループは回り続けているのですが、BLE関係の関数がうまく動作しなくなっていることが考えられます。
本当はその関数の戻り値を調べながら確かめたいのですが、それも今の知識ではできそうにありません。
通信が安定しないだけではなくモーターも動作していないようです。水分量%が減ってきているので、本来であればモーターが作動し、給水が行われ、土壌が潤い、その結果、水分量%が上がりモーターが停止します。
装置を手で触ってみるとモーター部が熱くなっていました。モーターが故障してしまったかもしれません。
どうしたものかと悩んでいましたが、とにかく一度ばらして調べるしかないと思い、ホースを外してみると。。。
勢いよくモーターが動き始めました!
どうやら、水やりホースが目詰まりを起こしていたようです。まち針で丁寧に穴を開けていたのですが、そのすべてが詰まってしまったのでしょうか。息を吹き込んでも空気が漏れない程になっていました。
原因がわかれば、対策は簡単。千枚通しでホースに穴をあけ直しました。
代品を買いに走ろうかとも思っていたところだったので、この問題が解決してホッとしました。
色んな問題を抱えながら、目の前の一つずつを拾って解決しています。
もがいているうちに、ネットで良い情報に巡り合えました。
BLEの基本から解説が始まり、ArduinoのBLEライブラリの解説まで。今とてもほしかった情報です。
ただ、頭になかなか入ってきません。
ここは正念場。同じドキュメントを何度も何度も繰り返し読み込んでみました。
読み込んでいくうちに、BLEでの作法がうっすらとわかってきたようで、
SMTesterのソース内で気になるところがいくつか出てきました。
ひとつは
pAdvertising->start();
delay(SECONDS(1));
pAdvertising->stop();
としているところ。
このサンプルは、電力節約のためにディープスリープするため、アドバタイジングの時間を決めていたものです。
他のサンプルを見ると、setup()関数内で、BLEDevice::startAdvertising();を呼ぶだけのものがあり、試して見る価値がありそうです。
定期的に呼び出しているSendData()関数内で、アドバタイジングの制御をやめました。
void
SendData(void) {
Serial.printf("SendData():\n");
Serial.printf("wateringLevel:%d st:%d c:%d wC:%d\n",
salzData.currentWaterLevel,
salzData.status,
salzData.count,
salzData.wCount);
setAdvData(salzData.currentWaterLevel, salzData.status, salzData.count, salzData.wCount);
/*
pAdvertising->start(); // アドバタイズ起動
Serial.println("Advertizing started...");
delay(SECONDS(1));
pAdvertising->stop();
Serial.println("Advertizing stop");
*/
salzData.count = (++salzData.count < UINT16_MAX) ? salzData.count : 0;
}
そして、テストをしたところ、
24時間以上連続でBLEの信号を出し続けるようになりました。
仕事でプログラムを組むときはここからが本番で徹底的に問題点を洗い出していくのですが、ここは趣味のプログラミング。
今、目の前の課題が乗り越えられそうであればひとつ乗り越え、また問題が起こるようであれば、その時にまた取り組むことにしました。
SALZmini2022のSendData()関数も同様に書き換え、稼働させてみます。
明らかな改善があり、信号が安定しました。
それで、少し様子を見てみます。
ただ、せっかく勉強したBLE。気になっている部分をもう少しすっきりさせておきたいと思いました。
例えば、BLEアプリで電波が飛んでいるか検索を掛けるとき、名前が表示されてほしいと思うのですが、MACアドレスが表示されるのみです。
setup()関数内で
BLEDevice::init("SALZmini2022");
を行っており、この「SALZmini2022」が表示されるようにしたいと考えています。
こちらの解決には時間が掛かりました。
こちらについて触れられているものが私の力では探し出すことができませんでした。
後は推測で下記のことをやってみたら、表示されるようになりました。
これで正解なのかわかりません。ですが、求める結果が出ているので、あとは使ってみてから考えることにいたします。
迷走のBLE受信
とにかくBLE関係のデバッグには時間が掛かります。
動作直後は正常に動作しているように見えても、長い時間かけてみれば問題が発生したり、また直ったりの連続で、落ち着くまで気が休まりません。BLE通信について、だいぶん安定性は増してきていると思われるのですが、データが飛んでこない時間帯があったりしています。
グラフの直線が長い箇所はデータが送られてきていない所です。
SMGatewayのソースを確認していて、気になる箇所を発見しました。
SALZmini2022からのアドバタイズ信号を受信すると、
ambient.set(pos * 4 + 1, sd.wateringLevel);
ambient.set(pos * 4 + 2, sd.st);
ambient.set(pos * 4 + 3, sd.count);
ambient.set(pos * 4 + 4, sd.wCount);
を行い、20分に一度、
ambient.send();
でデータを吐き出しています。
「pos」はMACアドレスを蓄えておき、知っているMACアドレスだったらその登録番号を返すように作っています。
この「pos」が正しく返ってこないと、値のセットも正しく行われないということに気が付いたのです。
当然、毎回MACアドレスは正常に返ってきていると思っていましたが、文字化けしてたり、またはその他理由で違っていれば、この現象は説明できます。
まずはどんな値で処理しているのかが分かるようにしていきたいと思います。
SMGatewayにデバッグコマンドを多く盛り込み、不具合が発生したときの状況を確認したいと考えています。
また、ソースをいじりながら試していると、一回だけ信号を送った後、データが途絶えてしまいました。
スマホのアプリにも表示されていません。
困ったなと思い、庭の実機を見てみると、LEDが付いていません。
元の電源を抜き差ししただけでは直りませんでした。装置側のコネクタの接触不良のようです。
最近、頻繁に抜き差ししていたので、少し甘くなっているかもしれません。風で揺すられて、一時的に電源が落ちてしまうことがあったかもしれません。
これが端末側の問題であれば、今までの不具合が全て説明できるので、ありがたいのですがどうでしょうか。
しばらく様子を見たあと、接触に関する対策を考えて見たいと思います。
ログを見返していて、不具合の痕跡を見つけました。
「scan_evt timeout」が連発し始めました。その後約8分後、リセットがかかっていました。
こちらは、SMGateway側の問題の可能性が高いです。
15:15:01.930 -> ************
15:15:08.845 -> 34:b4:72:11:73:3a:1:T (6,1):T (7,10751):T (8,3490):T
15:15:08.987 -> *
15:15:08.987 -> 34:b4:72:11:e9:32:0:T (2,2):T (3,6370):T (4,3):T
15:15:08.987 -> **********
15:15:15.776 -> 34:b4:72:11:73:3a:1:T (6,1):T (7,10752):T (8,3491):T
15:15:15.871 -> **
15:15:15.964 -> 34:b4:72:11:e9:32:0:T (2,2):T (3,6370):T (4,3):T
15:15:16.058 -> ****scan_evt timeout
15:15:19.822 -> scan_evt timeout
15:15:19.916 -> scan_evt timeout
15:15:20.010 -> scan_evt timeout
15:15:20.152 -> scan_evt timeout
:
(略)
:
15:23:03.098 -> scan_evt timeout
15:23:03.192 -> scan_evt timeout
15:23:03.288 -> scan_evt timeout
15:23:04.636 -> Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0).
15:23:04.636 ->
15:23:04.636 -> Core 0 register dump:
15:23:04.636 -> PC : 0x4008c1d6 PS : 0x00060035 A0 : 0x8008c4a4 A1 : 0x3ffc1dbc
15:23:04.636 -> A2 : 0x400853b8 A3 : 0x00000000 A4 : 0x3ffc5a8c A5 : 0x3ffb9274
15:23:04.636 -> A6 : 0x3ff71010 A7 : 0x3ffc1eac A8 : 0x8008c1d6 A9 : 0x3ffc1d9c
15:23:04.636 -> A10 : 0x00000000 A11 : 0x3ffc1dbc A12 : 0x3ffc1dc4 A13 : 0x00000000
15:23:04.636 -> A14 : 0x00060223 A15 : 0x00060223 SAR : 0x0000001c EXCCAUSE: 0x00000005
15:23:04.636 -> EXCVADDR: 0x00000000 LBEG : 0x4008486d LEND : 0x40084875 LCOUNT : 0x00000027
15:23:04.636 ->
15:23:04.636 ->
15:23:04.636 -> Backtrace:0x4008c1d3:0x3ffc1dbc |<-CORRUPTED
15:23:04.636 ->
15:23:04.636 ->
15:23:04.636 -> Core 1 register dump:
15:23:04.636 -> PC : 0x401c343e PS : 0x00060f35 A0 : 0x800e4d74 A1 : 0x3ffcbe80
15:23:04.636 -> A2 : 0x00000000 A3 : 0x00060023 A4 : 0x00060023 A5 : 0x80000000
15:23:04.636 -> A6 : 0x007bf1e8 A7 : 0x003fffff A8 : 0x00000014 A9 : 0x00000004
15:23:04.636 -> A10 : 0x3ffbd114 A11 : 0x80000001 A12 : 0x80096e30 A13 : 0x3ffcbd80
15:23:04.683 -> A14 : 0x00000003 A15 : 0x00060023 SAR : 0x00000000 EXCCAUSE: 0x00000005
15:23:04.683 -> EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
15:23:04.683 ->
15:23:04.683 ->
15:23:04.683 -> Backtrace:0x401c343b:0x3ffcbe800x400e4d71:0x3ffcbea0 0x40095210:0x3ffcbec0
15:23:04.683 ->
15:23:04.683 ->
15:23:04.683 ->
15:23:04.683 ->
15:23:04.683 -> ELF file SHA256: 0000000000000000
15:23:04.683 ->
15:23:04.683 -> Rebooting...
15:23:04.730 -> ets Jun 8 2016 00:22:57
15:23:04.730 ->
15:23:04.730 -> rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
15:23:04.730 -> configsip: 188777542, SPIWP:0xee
15:23:04.730 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
15:23:04.730 -> mode:DIO, clock div:1
15:23:04.730 -> load:0x3fff0030,len:1184
15:23:04.730 -> load:0x40078000,len:12812
15:23:04.730 -> load:0x40080400,len:3032
15:23:04.730 -> entry 0x400805e4
15:23:05.185 -> initializing.....OK
15:23:09.042 -> Switch Mode to INK_PARTIAL_MODE
15:23:09.465 -> Scanning...
15:23:10.169 -> .................
15:23:12.884 -> **
15:23:12.931 -> 34:b4:72:11:73:3a:0:T (2,2):T (3,10852):T (4,3516):T
15:23:12.931 -> **********
15:23:20.018 -> 34:b4:72:11:73:3a:0:T (2,2):T (3,10852):T (4,3516):T
15:23:20.158 -> *******
15:23:26.948 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,10853):T (4,3517):T
15:23:27.089 -> **********
ただ、再起動後、SMTesterだけ受信でき、SALZmini2022からの電波は拾えていません。
通信途絶した機器が復活した様子。
15:26:22.236 -> ************
15:26:29.227 -> 34:b4:72:11:73:3a:0:T (2,2):T (3,10889):T (4,3528):T
15:26:29.273 -> ********
15:26:36.282 -> 34:b4:72:11:73:3a:0:T (2,2):T (3,10889):T (4,3528):T
15:26:36.329 -> *****
15:26:36.881 -> 34:b4:72:11:e9:32:1:T (6,2):T (7,6438):T (8,3):T
15:26:37.303 -> ******
15:26:43.324 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,10890):T (4,3529):T
15:26:43.324 -> ****
15:26:43.465 -> 34:b4:72:11:e9:32:1:T (6,2):T (7,6438):T (8,3):T
15:26:43.558 -> *******
15:26:50.238 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,10891):T (4,3530):T
15:26:50.285 -> *****
15:26:50.472 -> 34:b4:72:11:e9:32:1:T (6,2):T (7,6439):T (8,3):T
15:26:50.709 -> *****
15:26:57.263 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,10892):T (4,3531):T
15:26:57.263 -> ****
(略)
15:52:33.350 -> ***********
15:52:40.360 -> 34:b4:72:11:e9:32:1:T (6,2):T (7,6592):T (8,3):T
15:52:40.360 -> *
15:52:40.360 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,11186):T (4,3625):T
15:52:40.453 -> *********
15:52:47.290 -> 34:b4:72:11:e9:32:1:T (6,2):T (7,6593):T (8,3):T
15:52:47.290 -> **
15:52:47.290 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,11186):T (4,3625):T
15:52:47.290 -> *********
15:52:54.236 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,11187):T (4,3626):T
15:52:54.283 -> ************
15:53:01.291 -> 34:b4:72:11:73:3a:0:T (2,1):T (3,11188):T (4,3627):T
15:53:01.338 -> *********
屋外で稼働させているSALZmini2022からの通信が途絶えた瞬間です。
今の所は、機器の接触不良ではないかと仮定しているため、接触不良対策をしていないうちは時々起こる現象として認識することにします。
しばらくは機嫌よく動いていたのですが、今日は午前中から受信できていないようです。
2台とも同時に不調になるとは今の所考えにくいので、SMGatewayの問題なのでしょうか?
一週間ほど様子を見ての結論
SMTesterは安定動作しています。
SMGatewayが不調でリセットしても、カウントはそのままに継続する様子からまず問題ないと思います。
SALZmini2022は半日程度でBLEが飛ばなくなっています。この原因がまだはっきりしません。最初は装置の接触不良を疑っていました。現在もまだ疑っていて、なにか良い対策はないか検討しています。接触不良の場合はリセットがかかるため、電波が飛びやすくなってると思うのですが、それがどうもよくわかりません。
今回はこの辺で記事を締めくくろうと思います。少し頭を冷やして、アイデアが湧いてくるのを待ちたいと思います。最後までお付き合いくださいまして誠にありがとうございました。