M
M
MWX Library
検索…
SM_SIMPLE ステートマシン
SM_SIMPLEは、サンプルコード中の状態遷移、タイムアウト待ち、送信完了などの処理待ちを行うために用意しています。
SM_SIMPLEの基本的なコード抜粋を示します。
1
#include <SM_SIMPLE>
2
3
enum class STATE : uint8_t {
4
INIT = 0,
5
SENSOR,
6
TX,
7
TX_WAIT_COMP,
8
GO_SLEEP
9
};
10
11
SM_SIMPLE<STATE> step;
12
13
begin() {
14
...
15
step.init(); //初期化
16
}
17
18
loop() {
19
do {
20
switch(step.state()) {
21
case STATE::INIT:
22
...
23
step.next(STATE::SENSOR);
24
break;
25
26
case STATE::SENSOR:
27
...
28
step.next(STATE::TX);
29
break;
30
31
case STATE::TX:
32
if (/*送信要求成功*/) {
33
step.set_timeout(100); // タイムアウトの設定
34
step.clear_flag(); //処理待ち
35
36
step.next(STATE::TX_WAIT_COMP);
37
}
38
break;
39
40
case STATE::TX_WAIT_COMP:
41
if (step.is_timeout()) the_twelite.reset_system(); // タイムアウト
42
if (step.is_flag_ready()) sleepNow(); // flagがセットされた
43
break;
44
45
...
46
}
47
} while(step.b_more_loop());
48
}
49
50
void on_tx_comp(mwx::packet_ev_tx& ev, bool_t &b_handled) {
51
step.set_flag(ev.bStatus);
52
}
53
54
void sleepNow() {
55
step.on_sleep(false); // reset state machine.
56
the_twelite.sleep(10000); // 10sec
57
}
Copied!

解説

SM_SIMPLEを利用するには状態一覧としてのenum class定義が必要です。上記ではSTATEとして定義しています。このステージをパラメータとしてSM_SIMPLE<STATE> step;のようにクラスオブエクトを生成します。生成したクラスオブジェクトは.setup()により初期化しておきます。
1
enum class STATE : uint8_t {
2
INIT = 0,
3
SENSOR,
4
TX,
5
TX_WAIT_COMP,
6
GO_SLEEP
7
};
8
9
SM_SIMPLE<STATE> step;
10
11
void setup() {
12
step.init();
13
}
Copied!
SM_SIMPLEの初期状態は値が0で、上記の例ではSTATE::INITが対応します。現在の状態を取得するには.state()を用、上記例のようにdo while文中のswitch節の判定式に用います。
1
loop() {
2
do {
3
switch(step.state()) {
4
case STATE::INIT: // 値0の状態
5
...
Copied!
状態の遷移には.next()を呼び出します。状態が変更された場合、b_more_loop()trueになりdo while節のループがもう一度実行されます。例ではSTATE::SENSOR状態から.next(STATE::TX)を呼び出すことで、ループがもう一度実行されcase STATE::TX:節も実行されることになります。状態を変更しない場合はdo whileループを脱出しloop()を一旦終了します。次のloop()の呼び出しまで一旦待ちます。
1
do {
2
switch(step.state()) {
3
...
4
case STATE::SENSOR:
5
...
6
step.next(STATE::TX); // (1)状態遷移
7
break;
8
9
case STATE::TX: // (3) 2回めのループで呼び出される
10
if (/*送信要求成功*/) {
11
...
12
}
13
} while (b_more_loop()); // (2) ループ継続判定 true
Copied!
送信完了などの処理待ちをしたい場合は.clear_flag()を呼び出し、別のコールバック関数などで.set_flag(uint32_t)により処理完了を知らせます。ここで指定したuint32_t型のパラメータをは.get_flag_value()から読み出せます。
またタイムアウトの処理を行いたい場合は.set_timeout(uint32_t)を呼び出した時刻を記録し、.is_timeout()によりタイムアウト時間が経過したかを調べることができます。
1
case STATE::TX:
2
if (/*送信要求成功*/) {
3
step.set_timeout(100); // タイムアウトの設定
4
step.clear_flag(); //処理待ち
5
6
step.next(STATE::TX_WAIT_COMP);
7
}
8
break;
9
10
case STATE::TX_WAIT_COMP:
11
if (step.is_timeout()) ...; // タイムアウト
12
if (step.is_flag_ready()) ...; // flagがセットされた
13
break;
14
...
15
16
// 送信完了イベント
17
void on_tx_comp(mwx::packet_ev_tx& ev, bool_t &b_handled) {
18
step.set_flag(ev.bStatus); // flag を設定する
19
}
Copied!
スリープからの復帰で再びSM_SIMPLEを利用することになりますが、スリープ前に必ず.on_sleep(bool)を呼び出すようにします。パラメータにfalseを入れると復帰後に0状態から開始し、trueを入れるとスリープ直前の状態から再開します。
1
void sleepNow() {
2
step.on_sleep(false); // reset state machine.
3
the_twelite.sleep(10000); // 10sec
4
}
Copied!

ソースコード

以下にSM_SIMPLEのソースコードを示します。
1
// very simple class to control state used in loop().
2
template <typename STATE>
3
class SM_SIMPLE {
4
uint32_t _u32_flag_value; // optional data when flag is set.
5
uint32_t _ms_start; // system time when start waiting.
6
uint32_t _ms_timeout; // timeout duration
7
8
STATE _step; // current state
9
STATE _step_prev; // previous state
10
bool_t _b_flag; // flag control.
11
public:
12
// init
13
void setup() { memset(this, 0, sizeof(SM_SIMPLE)); }
14
// call befoer sleeping (save state machine status)
15
void on_sleep(bool b_save_state = false) {
16
STATE save = _step;
17
setup();
18
if(b_save_state) _step = _step_prev = save;
19
}
20
21
// state control
22
void next(STATE next) { _step = next; } // set next state
23
STATE state() { return _step; } // state number
24
bool b_more_loop() { // if state is changed during the loop, set true
25
if (_step != _step_prev) { _step_prev = _step; return true; }
26
else return false;
27
}
28
29
// timeout control
30
void set_timeout(uint32_t timeout) {
31
_ms_start = millis();
32
_ms_timeout = timeout;
33
}
34
bool is_timeout() { return (millis() - _ms_start) >= _ms_timeout; }
35
36
// flag control
37
void clear_flag() { _b_flag = false; _u32_flag_value = 0; }
38
void set_flag(uint32_t u32_flag_value = 0) {
39
_b_flag = true;
40
_u32_flag_value = u32_flag_value; }
41
uint32_t get_flag_value() { return _u32_flag_value; }
42
bool is_flag_ready() { return _b_flag; }
43
};
Copied!
    バージョンによって内容が変化する場合があり。
    本体はmwxライブラリソースディレクトリのSM_SIMPLE.hppに格納されます。
最終更新 1mo ago
PDFに出力
リンクのコピー