Slp_Wk_and_Tx
Slp_Wk_and_Tx は、定期起床後、何か実行(センサーデータの取得など)を行って、その結果を無線パケットとして送信するようなアプリケーションを想定した、テンプレートソースコードです。
setup(), loop() の形式では、どうしても loop() 中が判読しづらい条件分岐が発生しがちです。本Actでは、loop()中を switch構文による単純な状態遷移を用いることで、コードの見通しを良くしています。
このアクトの解説の前にBRD_APPTWELITEの解説をご覧いただくことを推奨します。
アクトの機能
起動後、速やかにスリープする
setup(): 初期化するbegin(): スリープに遷移する
スリープ起床後、状態変数を初期化し、以下の順に動作を行う
wakeup(): スリープからの起床、各初期化を行うloop()状態INIT->WORK_JOBに遷移: 何らかの処理を行う(このActでは 1ms ごとの TickCount ごとにカウンタを更新し 100 カウント後にTX状態に進む)loop()状態TX: 送信要求を行うloop()状態WAIT_TX: 送信完了待ちを行うloop()状態EXIT_NORMAL: スリープする (1. に戻る)
loop()状態EXIT_FATAL: エラーが発生した場合は、モジュールリセットする
アクトの解説
インクルード
パケット送信を行うため <NWK_SIMPLE> をインクルードしています。また、アプリケーションIDなど基本的な定義は "Common.h" に記述しています。
Common.h には基本的な定義に加え、以下の列挙体が定義されています。こちらを状態変数として利用します。
setup()
the_tweliteクラスオブジェクトの初期化とネットワーク <NWK_SIMPLE> の登録を行います。
begin()
setup()の直後に一度だけ呼び出されます。SleepNow()関数夜を呼び出して初回のスリープ手続きを行います。
wakeup()
起床直後に呼び出されます。ここでは状態変数eStateを初期状態E_STATE::INITにセットします。この後loop()が呼び出されます。
loop()
上記のコードは、実際のコードを簡略化したものです。
このコードではloop_moreを条件としてdo..while() 構文のループになっています。これはloop()を脱出せずに次の状態のコード(case節)を実行する目的です。
wakeup()でINIT状態にセットされていますので初回のloop()ではINITが評価されます。ここは変数の初期化しているだけです。続く状態の処理を行うのにloop()を脱出する必要がないためloop_moreをtrueにしています。
WORK_JOB状態ではTichTimer.available()になるたびにカウンタを減算し0になったら次の状態TXに遷移します。
TX状態ではvTransmit()関数を呼び出しパケット送信要求を行います。この時点ではまだパケットが送信されていないため、この時点でスリープをしてはいけません。パケット送信要求が成功したらWAIT_TX状態に遷移します。タイムアウトの管理のため、この時点でのシステム時間u32millis_txを保存します。失敗したらEXIT_FATALに遷移します(モジュールのリセット実行)。
WAIT_TX状態では送信IDに対応する送信が完了したかを判定し、完了したらEXIT_NORMAL、100ms以上経過したらEXIT_FATAL状態に遷移します。
EXIT_NORMAL状態はSleepNow()を呼び出し、スリープします。
EXIT_FATAL状態ではシステムリセットを行います。
void SleepNow()
周期スリープを行います。スリープ時間はrandom()関数を用いて、一定の時間ブレを作っています。これは複数のデバイスの送信周期が同期した場合、著しく失敗率が上がる場合があるためです。
MWX_APIRET vTransmit()
ID=0x00の親機宛に無線パケットの送信要求を行います。格納されるデータはActサンプルで共通に使われている4文字識別子(FOURCC)に加え、システム時間[ms]が含まれます。
MWX_APIRETはuint32_t型をラップしたクラスで、MSBを失敗成功のフラグとし、以下31ビットをデータとして用いています。pkt.transmit()の戻り型になっており、送信要求の成功と失敗ならびに送信IDをデータ部に格納します。
最終更新