組み込みプログラム remoIntr での kVerifier 適用例

組み込みプログラム向け kVerifierRt(Real Time ) を PPM(Pulse Position Modulation)リモコン信号のデコード・プログラムにてきようします。kVerifier の仕様記述スレッドを使ったエンコード回路のシミュレーションも行わせます。

             0             1                0                1
      ┌┐      ┌┐                ┌┐        ┌┐                  ┌┐
  ─┘└───┘└────────┘└────┘└─────────┘└
      │1.00mSec│     2.00mSec     ││264uSec
      │   T    │        2T        │

                PPM信号の例

PPM 信号は上の図のように、bit 信号 0/1 に対して、1mSec/2mSec 幅のパルス信号を与えるエンコード方法です。

PPM は赤外線リモコンで使われています。リモコンは 10cm の至近距離から、使われることも、10m 以上離れて使われることもあります。受信側では AGC(Automatic Gain Control) をかけて、信号を一定にするようにしますが、AGC が働くまでの過度応答や外乱などもあり、信号パルス幅は保証できません。パルス幅が意味を持たない PPM が赤外線リモコンでは多く使われています。

外乱光の影響を受け難くするために、細工が必要です。リモコン信号の波長近くには、蛍光灯などから外乱赤外線が出ています。このデコードを PPM 信号の検出を単純にエッジの間の時間の測定だけで行うと、外乱光で誤動作してしまう、信頼性の低いものになってしまいます。


          外来ノイズ
          ↓
             0            1                0                1
      ┌┐      ┌┐┃              ┌┐        ┌┐                  ┌┐
  ─┘└───┘└┸───────┘└────┘└─────────┘└
      │1.00mSec│     2.00mSec     ││264uSec
      │   T    │        2T        │

                PPM信号に外来ノイズが重畳した例

組み込みマイコンのソフト処理を行うのですから、外乱光があっても誤動作しにくいアルゴリズムを使うことが望まれます。ここでは下のように 最初の信号から T/2:500uSEc だけ経過した時点から T:1mSec ごとの時間ウィンドウをもうけ、このウィンドウ内にリモコン信号があるかないかにより 0/1 信号への復調を行うアルゴリズムを使っています。下の図より外乱があって誤復調しなくできます。

組み込みマイコンのソフト処理を行うのですから、外乱光があっても誤動作しにくいアルゴリズムを使うことが望まれます。ここでは下のように 最初の信号から T/2:500uSEc だけ経過した時点から T:1mSec ごとの時間ウィンドウをもうけ、このウィンドウ内にリモコン信号があるかないかにより 0/1 信号への復調を行うアルゴリズムを使っています。下の図より外乱があって誤復調しなくできます。

          外来ノイズ
          ↓
      ┌┐      ┌┐┃             ┌┐      ┌┐                ┌┐
  ─┘└───┘└┸───────┘└───┘└────────┘└
      │1/2T│   T    │   T    │   T    │   T    │   T    │   T    │

    復調信号          0                  1         0                   1
             
                時間幅Tごとの検出窓を設けた例

PPM 信号のエッジから外乱光ノイズが下のようにズレタときは、誤復調してしまいます。

            外来ノイズ
            ↓
             0                1                0                 1
      ┌┐      ┌┐  ┃          ┌┐      ┌┐                ┌┐
  ─┘└───┘└──┸─────┘└───┘└────────┘└
      │1/2T│   T    │   T    │   T    │   T    │   T    │   T    │
             
誤った復調信号        0         0        0         0                   1
本来の復調信号        0                  1         0                   1
                図4 誤って復調するノイズの

でも、外乱は AC50/60 Hz に同期して発生します。一方でリモコン信号は何度も繰り返し発生します。正常な信号を二回連続して受信したときに、リモコン信号を受信したことにすることにより、誤復調がありながらも、ノイズにつよいリモコン受信プログラムにできます。

リモコン受信プログラム

この kVerifierRt 適用例は、三つのプログラムと mntr ディレクトリにある RTOS(Real Time )より構成されます。


    remoIntr.c          リモコン信号受信・デコード割り込みプログラム
    testTsk4.c          リモコン信号エンコード、マイコン回路のシミュレーション・プログラム
    testTsk3.c          リモコン信号受信タスク
    mntr\CntxtCu.e      k-uOS : ワンチップ・マイコン用、スタック共用 RTOS
        \DffrdCll.c
            ・
            ・

remoIntr.c は割り込みプログラムです。タイマー・割り込みと組み合わせて、PPM リモコン信号のデコード動作を行い 15 bit 受信データを生成します。

testTsk4.c はリモコン信号の生成回路や、ワンチップ・マイコン内のタイマー回路をシミュレーションを kVerifier が備えている ClVrfyThrd クラスを使って実現しています。

ワンチップ・マイコンに組み込まれている回路の動作を action scripts だけで記述することも可能ですが、無理があります。RTOS が時間に従ってタスクを準じ駆動していくためには、1mSec ... 10mSec 周期程度のタイマー割り込みが必要になります。これを action scripts で記述すると 非常に多くのタイマー割り込み関数呼び出しを action script に書かねばなりません。それを簡便にするため、

    class Cl10mSecIntervalTask: public ClVrfyThrd

の仕様記述シミュレーション・タスクを設けています。

リモコン信号のエンコード信号を action scripts で記述するのは、タイマー以上に複雑になります。

    class ClRemoIntr: public ClVrfyThrd

スレッドを設けて、action script からは、下のように書くだけで、0xaa に対応する 15bit リモコン信号エンコード信号を生成し、リモコン信号割り込み関数を呼び出すようにしています。

    +100mS StartRemoconInterrupt __function 0xaa

testTsk3.c は、ワンチップ・マイコン向けの RTOS k-uOS 上で動いているタスクです。15 ビットリモコン信号を受信する毎に働きます。PPM リモコン信号自体は 1mSec のオーダーで処理を完了する必要があり、割り込みルーチンで処理しなければなりません。でもリモコン 15bit エンコード・データは 100mSec 前後の頻度でしか発生しません。これを割り込みルーチン内で処理することは、不必要に 割り込みでの CPU 時間を消費します。他に急ぐ処理がなければ、それでもかまいません。通常は、他にも割り込みで処理すべき制御対象が多くあります。そのため、100mSec のオーダーで処理が完了すればよいタスク側で 15 bit データを処理しています。

このアプリケーション例では 15bit リモコン信号は 60mSec 周期で発生するものとしています。230mSec 以内に二つの 15bit リモコン信号を受信し、それらが同じであったとき、リモコン信号受信 LED を点灯させています。実際のアプリケーションでは、同時に、リモコン信号のコードの解析ルーチンを呼び出し、コードに対応したタスクを起動することになります。ここでは LED の点灯だけで終わらせています。

test.ins

この例のような組み込みプログラムでは一度に複数のタスクが平行して走ります。action scripts も複数のものを平行して走らせる必要があります。そのために ins (instruction) ファイルから複数の action script を指定できるようにしています。

この例では test.ins に、action scripts を指定させています。

    >type test.ins
    
    @ClVrfyIntfSglt kk::ClVfIntfThrd
        @ClTestVctInstance xxx     # blank test vector instance name
            @TestVectorFile test.vrf
    
    @ClVrfyIntfSglt kk::ClVfIntfRtosPrdc
        @ClTestVctInstance testTsk3         # test vector instance name
            @TestVectorFile v\test3.vrf     # test vector file

下の test.vrf は 19003mSec まで仕様記述すレットが働いていることを保証します。

    >type test.vrf
    +0 __TmSendVariableName blSgnlStt
    +0 __TmSendBitName blSgnlStt remoIntSgnl  bit0
    +0 __TmSendVariableName btFlReceivingStt
    +0 __TmSendBitName btFlReceivingStt receiveLED  bit0
    
    +3mS start __function 
    
    +8S port __set 0x02
    +1S port __set 0x3
    
    +10000mS __end

port __set 0x02 などは、LoopingWait(.) のコンテキスト・スイッチ関数をループさせながら待つ動作をさせているのですが、今の段階では説明を端折ります。

test3.vrf では StartRemoconInterrupt __function 0xaa により、リモコン・エンコーダー回路を開始させています。その結果、リモコン LED btFlReceivingStt が On/Off していることをかくにんしています。

    >type v\test3.vrf
    +100mS StartRemoconInterrupt __function 0xaa
    
    +100mS StartRemoconInterrupt __function 0xaa
    +35mS   btFlReceivingStt __compare 1
    +100mS StartRemoconInterrupt __function 0xaa
    +1mS   btFlReceivingStt __compare 1
    +300mS   btFlReceivingStt __compare 1   // error test
    
    +1000mS __end

>k-uOS について

k-uOS はラムか 4K,8K バイトなどと限られたワンチップ・マイコンでも wait(.) delay(.) などのコンテキスト・スイッチを含むタスク記述を行えるように開発しました。タスクごとにスタックを割り振っていたのではラムが直ぐに不足するので、並列して動くタスクの間でスタックを共用するようにつくりました。コンテキスト・スイッチではスタック・ポインタではなく、スタック・フレームを保存するようにしました。これにより、同時に並行して走るタスクの間でのスタックの共用をかのうにしました。

k-uOS は C で 2000 行を超えるプログラムです。章をあらためて、別に説明します。

注意: remoIntr は Vc7 向けのライブラリです。

    TkFb.sln

ファイルををダブル・クリックすれば、Vc7 の IDE が立ち上がるはずです。でも、それだけでは、コマンド・ラインからの test.ins 指定ができていません。Property Pages->debugging->Command Argments がブランクになっており、ユーザーがマニュアルで test.ins を一回は入力してやらないと、abnormal program termination になります。