コード修正について
標準アプリケーションのコードについてのポイントを記述します。
基本構造
本アプリケーションで重要な関数を以下に述べる。
AppColdStart() ⇒ 電源投入時のシステムの初期化 vProcessEvCorePwr() または vProcessEvCoreSlp() をシステムに登録。 vProcessEvCorePwr() ⇒ 常時通電時の基本処理 TIMER_0 割り込み毎に呼び出され送信条件判定⇒送信 vProcessEvCoreSlp() ⇒ スリープモードの基本処理 起動⇒IOの測定結果待ち⇒送信⇒送信終了待ち⇒再スリープ TIMER_0 ⇒ 秒64回割り込みを発生し、アプリケーションの動作を決定 cbToCoNet_vHwEvent() で呼び出される。 TickTimer ⇒ 4ms または 1ms 毎のタイマー処理 cbToCoNet_u8HwInt() で呼び出される。
処理例
受信時
cbToCoNet_vRxEvent()が呼び出され、無線パケットのコマンドバイト(.u8Cmd) の値によって処理を分けます。
- TOCONET_PACKET_CMD_APP_DATA ⇒ シリアルメッセージ vReceiveSerMsg()
- TOCONET_PACKET_CMD_APP_USER_IO_DATA ⇒ IO状態 vReceiveIoData()
- TOCONET_PACKET_CMD_APP_USER_IO_DATA_EXT ⇒ シリアルコマンドによるIO変更要求 vReceiveIoSettingRequest()
vReceiveXXX() 関数では、受信したパケットに応じた処理が行われます。
受信時 - vReceiveIoData()
通常のボタンの押し下げなどを検知し、無線パケットが送信された時の処理です。
- パケット構造を読み取ります。
- 自身が中継機で、中継フラグが設定されていない未中継パケットを受信した場合に限り i16TransmitRepeat() を呼び出し、中継パケットを送信します。
- パケットが親機⇒子機または子機⇒親機の場合にのみ処理を行います。親機⇒親機といったパケットは処理しません。
- パケットの中身のIO情報を基に DO, PWM を設定します。
パケット構造
以下にパケット構造を記載する。
- 断りが無い限り 2 OCTET, 4OCTET のデータはビッグエンディアンの並びとする。0x1234 - 0x12 0x34 の順で並ぶ。
TOCONET_PACKET_CMD_APP_USER_IO_DATA
名前 | データサイズ(OCTET=BYTE) | 備考 |
---|---|---|
アプリケーション識別子 | 1 | パケット混信を抑制するための識別子(アプリケーションIDを基に作成した1バイトが使用される) |
プロトコルバージョン | 1 | プロトコルのバージョン間で混信を起こさないための識別子 |
送信元簡易アドレス | 1 | 送信元のアドレス |
送信元アドレス | 4 | 送信元の32bitアドレス |
宛先簡易アドレス | 1 | 宛先のアドレス |
タイムスタンプ | 2 | 送信元のタイムスタンプ (重複パケット処理のため使用する)。MSB(0x8000) が設定された場合は低レイテンシモード向け優先パケットとして設定を強行する。 |
中継フラグ | 1 | 初回送信時は 0 を設定し、中継パケットとなった場合は 1 を設定する。中継パケットを再中継しないためのフラグ |
電圧 | 2 | 送信元の電圧値を格納する |
予備 | 1 | |
ボタン状態 | 1 | LSB から順に DI1, DI2, DI3, DI4 の値を格納する。0x3 なら DI1, DI2 が LO の状態 |
ボタン、変更マスク | 1 | LSB から順に DI1, DI2, DI3, DI4 の値を格納する。0x3 なら DI1, DI2 が変更対象で、DI3 DI4 は変更しないように設定する |
ADC値 | 4 | AI1 から順に各ADCの値を8bitで格納する。16倍すると測定値の mV 値となる。 |
ADC値、誤差情報 | 1 | LSB から順に2ビットずつ誤差補正情報となる。4倍した値を ADC 値に付加する。 |
入力の取り扱いについて
ディジタル入力
ディジタル入力は、5回連続で同じ値になって初めて状態が確定する連照方式を採用しています。そのため、IOが変化してからこれを検知するまで遅延が発生します(20ms程度)。
低レイテンシモードでは、割り込み発生を起点として、HL遷移を示す無線パケットの送信を連続して行います。約100ms後に改めて LH 遷移の取りこぼしを防ぐために IO 状態の再送信を行います。つまり、低レイテンシモードは、HL 遷移を優先して検出し、検出後暫くは他の検出を行わない仕組みになっています。また LH については割り込みが使用できないため HL に比べ長めの検出時間となります。
アナログ入力
本アプリケーションのアナログ入力は、つまみを操作するような比較的ゆっくりした変化を伝達する目的です。一般の○○Hzのアナログ信号といった入力は想定していません。
本アプリケーションでのアナログ入力の使用法は少々特殊で、一定以上の電圧を与えたとき未使用という状態を設定しています。この閾値はマクロADC_MAX_THRESで指定され 2050mV となっています。
- 電源電圧:測定時の変動が多いため一定回数の平均値を求めています
- 各測定値:過去4サンプルの平均値を求めています。
- ADC値の変化:直前送信時の電圧からADC_DELTA_COARSE(64mV)変化した場合としています。また300ms経過後にADC_DELTA_COARSE/2(32mV)変化した場合です。変化した時には無線パケットを送信します。
改造例
送信(再送回数など)について調整したい
送信パラメータは、受信の成功率や遅延を決定する重要なパラメータです。コード中では再送は1回のみ、遅延は最大16msとしています。
送信パラメータは i16TransmitXXX() 関数中で設定を行っています。以下では i16TransmitIoData() のコード例です。
sTx.u8Retry = 0x81; // 1回再送 sTx.u16RetryDur = bQuick ? 0 : 4; // 再送間隔 sTx.u16DelayMax = bQuick ? 0 : 16; // 衝突を抑制するため送信タイミングにブレを作る(最大16ms)
- .u8Retry の値を 0x83 とすると、3回再送が行われます。
- .u16RetryDur の値を 8 とすると、約 8ms 毎に再送が行われます。
- .u16RetryDelayMax の値を bQuick ? 0 : 4 とすると、通常時は最大 4ms 遅れてから送信が行われます。
※ 中継パケット(i16TransmitRepeat() )の送信パラメータには注意してください。中継元のパケットと中継のパケットが衝突する可能性が有りますので、出来る限り時間を離すようにしてください。デフォルトでは再送間隔を 8ms と長めに設定し、かつ、送信時の遅延を 16~32ms と長めに設定しています。
sTx.u16RetryDur = 8; // 再送間隔 sTx.u16DelayMin = 16; // 衝突を抑制するため送信タイミングにブレを作る(16ms 遅延) sTx.u16DelayMax = 16; // 衝突を抑制するため送信タイミングにブレを作る(u16DelayMin+最大16ms)
子機間の通信を行いたい
通常のIO送受信を例にとると、
- パケット構造に示される宛先簡易アドレスを i16TransmitIoData() で設定します。
(標準アプリケーションでは個のフィールドは使用していませんので暫定的な値が入っています)。
例えば子機宛ブロードキャストとする場合は、LOGICAL_ID_CHILDREN (0x78) を指定します。親機宛なら LOGICAL_ID_PARENT(0x00) を指定します。 - vReceiveIoData() での送信パケットのアドレス判定を作成する。