MAXQ2000によるセキュリティシステム制御

要約

アラーム制御パネルは、家庭でも職場でも日常生活の一部となっています。このアーティクルは、MAX-IDE開発環境で作成された、低電力LCDマイクロコントローラMAXQ2000を利用したアラーム制御のサンプルアプリケーションについて説明します。MAXQ2000は、LCDディスプレイ、PIN (暗証番号)入力キーパッド、圧電ブザー、および磁気リードスイッチなどのセキュリティアプリケーションで標準的に使われるペリフェラルと容易にインタフェースすることができます。

アラームコントロールパネルには、普通、さまざまな入力デバイスとユーザディスプレイが使われています。よく使われるコンポーネントは以下のようなものです。

  • ユーザからの入力を受け付けるデバイス:4 x 4のスイッチキーパッド
  • ユーザに対する出力を表示するデバイス:LCDディスプレイ
  • 入力デバイス:磁気リードスイッチ
  • 出力デバイス:圧電ブザー

このようにさまざまなコンポーネントを、シンプルなアプリケーションとパワフルで柔軟なMAXQ2000マイクロコントローラで管理・制御することができます。MAX-IDE開発環境とMAXQアセンブリ言語で作られたこのアプリケーションダウンロード可能です。コードの前提となっているのは、以下のハードウェアを持つMAXQ2000評価キットボードです。

  • キーパッド:Grayhill 16ボタン(4行4列)キーパッド96BB2-006-F
  • 圧電ブザー:CEP-1172
  • 磁気リードスイッチ:標準的なシングルループタイプ

設計目標

サンプルアプリケーションは以下のタスクを実行します。

  • 磁気リードスイッチをモニタリングし、ドアや窓が開いているか閉じているかを検出します。
  • キーパッドからPINを入力することによって、システムセキュリティの設定・解除ができるようにします。
  • ステータス情報をLCDに表示します。
  • キー入力やセンサ開閉を検知すると、圧電ブザーを鳴らして音による警告を行います。
  • システムセキュリティが設定され、かつ、センサが開を検知すると、ブザーを鳴らし続けます。

図1に示すように、アラーム制御アプリケーションの動作には、CLOSED、OPEN、SET、ALERTという4つのステータスがあります。

図1. アラーム制御アプリケーションには、CLOSED、OPEN、SET、ALERTという4つのステータスがあります。

図1. アラーム制御アプリケーションには、CLOSED、OPEN、SET、ALERTという4つのステータスがあります。

磁気リードスイッチとのインタフェース

警報システムでは、磁気リードスイッチの磁気部分とリードスイッチ部分を別の場所に取り付けます。磁気部分はドアや窓の動くところに取り付け、スイッチ部分は枠組みに固定します。ドアや窓が閉まっていると、磁気によってリードスイッチが閉じ、アラームは発報していません。システムセキュリティが設定され、ドアや窓が開くと、リードスイッチのステートが変化し、MAXQ2000が侵入警報を発報します。

リードスイッチは、ポートピンP5.2とP5.3間に接続するだけでMAXQ2000とインタフェースします。P5.2がアクティブロープルダウン(PD = 1、PO = 0)、P5.3が弱プルアップ入力(PD = 0、PO = 1)に設定されているとき、リードスイッチが閉じるとP5.3がゼロを読み込み、開くと1を読み込みます。


   move    PD5.2, #1         ; Drive one side of reed switch LOW
   move    PO5.2, #0

   move    PD5.3, #0         ; Set weak pullup high on other side
   move    PO5.3, #1

...

ML_Closed_Check:
   move    C, PI5.3
   jump    NC, ML_Closed_L   ; Switch is closed, continue in this state

   call    ShortBeep
   call    ShortPause
   call    ShortBeep
   call    ShortPause
   call    ShortBeep
   call    ShortPause
   call    ShortBeep
   call    ShortPause
   jump    ML_Open           ; Switch is open, transition to OPEN state

4 x 4キーパッドとのインタフェース

ラーム制御システムでは、PINを確実に入力したり、システムセキュリティの設定・解除を行ったり、システムの構成を変更するためにキーパッドを用います。今回のサンプルアプリケーションで使用するキーパッドは4 x 4グリッドの16スイッチです。スイッチは行と列のマトリクスになっており(図2)、キーパッドスイッチを押すと、ある行とある列が接続されます。たとえば、「3」キーを押すと、行3と列1が接続されます。

図2. キーパッドスイッチは、4行4列のグリッドになっています。

図2. キーパッドスイッチは、4行4列のグリッドになっています。

キーパッドには、キーパッドマトリクスの各行と各列ごとに端子が出ており、全部で8本のインタフェース端子があります。キーパッドとMAXQ2000のEVキットの接続は以下のようになります。

Pin Connect Port Pin JU2 Pin
1 Row 1 P6.0 54
2 Row 2 P6.1 52
3 Row 3 P6.2 50
4 Row 4 P6.3 48
5 Col 1 P6.4 46
6 Col 2 P6.5 44
7 Col 3 P7.0 42
8 Col 4 P7.1 40

今回のアプリケーションでは、EVキットボードを以下のように構成します。

  • DIPスイッチ

    • 以下のスイッチはオフにします:SW1スイッチすべて、SW3.1、SW3.7、SW3.8、SW6.1、SW6.4、SW6.5、SW6.6、SW6.7、およびSW6.8
    • その他のDIPスイッチはどのようなステートでも大丈夫です。
  • ジャンパ

    • 以下のジャンパはOPENにします:JU5、JU6、JU8、およびJU9
    • 以下のジャンパはCLOSEDにします:JU1、JU2、JU3およびJU11
    • その他のジャンパはどのようなステートであっても構いません。

列スキャン

キーパッドは行と列という構成になっているため、ある行、あるいはある列の4個のスイッチのステートを同時に読むことができます。1列目の4個のスイッチのステートを読み取るためには、まず、そのラインをローにプルダウンし、他の列はトライステートとします(図3)。次に、各行のラインを弱プルアップとします。最後に、4本の行ラインをポートピン入力に接続します。こうすると、スイッチが押されている行の入力だけがロー、残りはハイになります。

同様に、1行に並んだ4個のスイッチのステートは、その行のラインをローにプルダウンし、4列ともに入力と弱プルアップを設定すれば読み取ることができます。行と列は交換可能です。

サンプルアプリケーションの構成では、4本の行ライン(キーパッド端子の1から4まで)が同じ入力ポート(P6[3:0])に接続されるため、同時に読み取ることが簡単です。このため、サンプルアプリケーションでは、1列分のスイッチを同時にスキャンするようにしています。キーパッドに接続した8本のポートピンラインについては、4種類のセットアップがありえます。セットアップごとに、4個のスイッチのステートを読み取ることができます。読み込まれているスイッチが閉じていれば全入力ラインはローを読み込み、スイッチが開いていればハイを読み込みます。

STATE P6.0 P6.1 P6.2 P6.3 P6.4 P6.5 P7.0 P7.1
1 Input - 1 Input - 4 Input - 7 Input - * low tri-state tri-state tri-state
2 Input - 2 Input - 5 Input - 8 Input - 0 tri-state low tri-state tri-state
3 Input - 3 Input - 6 Input - 9 Input - # tri-state tri-state low tri-state
4 Input - A Input - B Input - C Input - D tri-state tri-state tri-state low

図3. MAXQ2000は、列1をローにプルダウンして、最初の4つのキーパッドスイッチのステートを読み取ります。

図3. MAXQ2000は、列1をローにプルダウンして、最初の4つのキーパッドスイッチのステートを読み取ります。

割込駆動のステートマシン

キーが押されている間に確実に読み取るためには、キーパッドの4列をすばやくスキャンする必要があります。また、複数回のキー操作をスイッチのチャタリングと誤判断することを避けるために、一定時間以上、スイッチが押されてスイッチ押下と判断される必要があります。以上は、いずれも、アプリケーションの中心であるタイマーを使った割込ルーチンによってすぐに実現可能です。このようにすることによって、4列のいずれかを定期的にスキャンし、キーが押されている時間を計るアプリケーションが可能になります。


RELOAD           equ 0FF00h

StartTimer:
   move    IIR.3, #1         ; Enable interrupts for module 3
   move    IMR.3, #1

   move    T2V0, #RELOAD
   move    T2R0, #0h
   move    T2C0, #0h

   move    Acc, T2CFG0       ; Set timer 0 to run from HFClk/128
   and     #08Fh
   or      #070h
   move    T2CFG0, Acc

   move    T2CNA0.3, #1      ; Start timer 0
   move    T2CNA0.7, #1      ; Enable timer 0 interrupts
   ret

タイマーのリロード値によって割込頻度を制御します。キー押下を確実にとらえるためには、このリロード値を十分に小さくする必要があります。さらに、キー応答が遅くならないようにするためには、リロード値を長くして、処理時間を消費しすぎないようにする必要もあります。いろいろと実験した結果、上記にあるように0FF00hという値にたどり着きました(およそ2.4msごとに1回)。

4つのスイッチをひとまとめにした列ラインをローに駆動すると、押下されたスイッチを経由して接続動作を行い、入力ラインをローにするために、若干の時間、待つ必要となるかもしれません。どの程度の時間がかかるかは、スイッチのオン抵抗や同時に押された列スイッチの数によって異なります。列ラインをローにプルダウンしてから4個のスイッチのステートを読むまで割込サービスルーチンに遅延をかけなくても済むように、あるステートの列ラインをあらかじめローにプルダウンするようにしました。(図4)

図4. 4つのキースキャンステートのそれぞれにおいて、アプリケーションは、4個のスイッチのステートを読み取るとともに、次の4個の読み取り準備を行います。

図4. 4つのキースキャンステートのそれぞれにおいて、アプリケーションは、4個のスイッチのステートを読み取るとともに、次の4個の読み取り準備を行います。

MAXQ2000の割込ベクター(IV)は実行時にセットすることができるので、アプリケーションは次のステート値を割込ベクターレジスタに保持します。タイマーから割込がかかると、現在のキースキャンステートのハンドラルーチンが、次のステートのハンドラルーチンに割込ベクターアドレスを設定します。


org  0000h

Main:
   call    InitializeLCD

   move    PD6, #010h         ; For state 1
   move    PO6, #00Fh         ; For all states
   move    PD7, #000h         ; For state 1
   move    PO7, #000h         ; For all states

   move    IV, #State1
   call    StartTimer
   move    IC, #1            ; Enable global interrupts

   jump    $


State1:
   push    PSF
   push    Acc

   move    Acc, PI6
   and     #000Fh            ; Grab lowest four bits only
   sla4
   move    A[13], Acc

   move    PD6, #020h        ; For state 2
   move    PD7, #000h

   move    T2V0, #RELOAD     ; Set reload value
   move    T2CNB0.1, #0      ; Clear interrupt flags
   move    T2CNB0.3, #0
   move    IV, #State2

   pop     Acc
   pop     PSF

   reti

他の4ステートのハンドラルーチンも同様ですが、すでに情報を集め、A[13]ホールディングレジスタに保存されているスイッチビットのORに若干の調整を行います。このステートルーチンでは、3つのワーキングアキュムレータを使用します。

A[13]は、キーパッドを通し現在のパスで読み込んだ全スイッチステートのビット行列を保持します。ステート4の読み込みが完了すると、このレジスタに保持されるビットは以下のようになります。ここで1のビットは開いた(押されていない)キースイッチを示し、0ビットは閉じた(押された)キースイッチを示します。

BIT
15
BIT
14
BIT
13
BIT
12
BIT
11
BIT
10
BIT
9
BIT
8
BIT
7
BIT
6
BIT
5
BIT
4
BIT
3
BIT
2
BIT
1
BIT
0
* 7 4 1 2 5 8 0 3 6 9 # D C B A

スイッチのデバウンシング

ステート4に到達してすべてのキーのスキャンが終了すると、押されたキーを認めるかどうかの判断をしなければなりません。シンプルなデバウンシング手法としては、16個のスイッチそれぞれについてカウンタ値を保持するという方法があります。ステート4に到達したとき、キーが押されていたらカウンタをインクリメントします。キーが押されていない場合は、カウンタをデクリメントします。このカウンタが一定値に達すると、キーが押されたものとして登録します。キーを押下しつづけたときキーリピートにならないように(コンピュータキーボードではキーリピートが普通ですが、キーパッドではキーリピートさせません)、一度登録されたキーがもう一度登録されるためには、まず、(キーの押下が終わり)カウンタがゼロまでデクリメントされなければならないようにする必要があります。

16のキーすべてのステートを1つのレジスタに保持しているため、もっとシンプルで、かつ、メモリ消費量が少ないデバウンシングソリューションが考えられます。このアプリケーションの保持するカウンタ値は1つとし、ビットパターンが前回のスキャンで読んだパターンと等しいときにカウンタ値をインクリメントします。


State4:
   push    PSF
   push    Acc

   move    Acc, PI6
   and     #000Fh            ; Grab low four bits only
   or      A[13]
   cmp     A[15]
   jump    E, State4_End    ; Ignore the last debounced pattern

   cmp     A[14]
   jump    E, State4_Match

   move    LC[0], #DEBOUNCE
   move    A[14], Acc       ; Reset current bit array


キーリピート防止の為、ビットパターンをもう一度認める条件は、ビットパターンがキー押下と認めるだけの時間一定であり、且つ、他のビットパターン(キー押下がないアイドルステートも含む)が認められた後のみとします。

複数キー同時押下の処理

キーパッド入力デバイスの使用では、複数キーの同時押下が可能です。サンプルアプリケーションのデバウンシングコードでは、2番目のキーが押されるとデバウンスインターバルのカウントが最初に戻りますが、デバウンスインターバル自体が短いため、これが問題になることはありません。

ビットパターンが認められると、アキュムレータを使い、押下されたキーのビットについて、16ビットすべてをローテーションしてそれぞれキャリービットに入れ、その際にビットごとにチェックすることができます。サンプルアプリケーションのコードは、最初に押下されたキーのみに反応しますが、必要であれば、この変更も容易です。


State4_Match:
   djnz    LC[0], State4_End
   move    A[15], Acc       ; Reset last debounced pattern

   rrc
   jump    NC, State4_KeyA
   rrc
   jump    NC, State4_KeyB
   rrc
   jump    NC, State4_KeyC
   rrc
   jump    NC, State4_KeyD

   rrc
   jump    NC, State4_Key3
   rrc
   jump    NC, State4_Key6
   rrc
   jump    NC, State4_Key9
   rrc
   jump    NC, State4_KeyPound

   rrc
   jump    NC, State4_Key2
   rrc
   jump    NC, State4_Key5
   rrc
   jump    NC, State4_Key8
   rrc
   jump    NC, State4_Key0

   rrc
   jump    NC, State4_Key1
   rrc
   jump    NC, State4_Key4
   rrc
   jump    NC, State4_Key7
   rrc
   jump    NC, State4_KeyStar

   jump    State4_End

LCDディスプレイのインタフェース

MAXQ2000のEVキットに搭載されているLCDディスプレイは、図5のようなセグメントを持ちます。

図5. このLCDディスプレイには、4.5桁の7セグメント文字を表示することができます。

図5. このLCDディスプレイには、4.5桁の7セグメント文字を表示することができます。

まず、LCDディスプレイをスタティック駆動モードに初期化し、イネーブルとします。この処理が終わると、セグメントを適切に設定することによって、ディスプレイ上に文字を描くことができます。


InitializeLCD:
   move    LCRA, #03E0h      ; xxx0001111100000
                             ;    00            - DUTY : Static
                             ;      0111        - FRM  : Frame freq
                             ;          1       - LCCS : HFClk / 128
                             ;           1      - LRIG : Ground VADJ
                             ;            00000 - LRA  : RADJ = max

   move    LCFG, #0F3h       ; 1111xx11
                             ; 1111     - PCF  : All segments enabled
                             ;       1  - OPM  : Normal operation
                             ;        1 - DPE  : Display enabled

   move    LCD0, #00h        ; Clear all segments
   move    LCD1, #00h
   move    LCD2, #00h
   move    LCD3, #00h
   move    LCD4, #00h
   ret

PINの入力

CLOSED状態とSET状態、ALERT状態では、PINを入力してアラームコントローラの状態を変更することができます。文字が入力されるごとに、A[10]に保持されるワーキング値を左にシフトし、新しい文字とのORをとります。同時に、LCDディスプレイ上の小数点が左に動き、入力した文字数を表示します。セキュリティ上の理由から、入力されたPINをディスプレイに表示することはしません。


State4_Key0:
   move    Acc, #0000h
   jump    State4_Shift

State4_Key1:
   move    Acc, #0001h
   jump    State4_Shift

State4_Key2:
   move    Acc, #0002h
   jump    State4_Shift

....

State4_Shift:
   move    A[12], Acc

   move    Acc, A[10]
   cmp     #0FFFFh         ; flag indicating no PIN entry allowed
                           ;    in current state
   jump    E, State4_NoKey

   move    Acc, A[11]      ; key count
   cmp     #04             ; if already at 4 (should have been cleared)
   jump    E, State4_NoKey

   add     #1
   move    A[11], Acc

   move    Acc, A[10]
   sla4
   or      A[12]
   move    A[10], Acc

4文字すべてが入力されると、入力されたPINをハードコーディングされた値と比較します。この入力された値がPINと一致すると、適切な状態に移行します。


PIN_VALUE        equ 03870h       ; Just a random number

;; "Closed" state code

ML_Closed:
   move    A[10], #00000h         ; Reset PIN value
   move    A[11], #0              ; Reset number of PIN chars entered

   move    LCD3, #LCD_CHAR_C
   move    LCD2, #LCD_CHAR_L
   move    LCD1, #LCD_CHAR_5
   move    LCD0, #LCD_CHAR_D

ML_Closed_L:
   move    Acc, A[11]
   cmp     #4                     ; 4 characters entered?
   jump    NE, ML_Closed_Check

   move    Acc, A[10]
   cmp     #PIN_VALUE             ; PIN matches?
   jump    E, ML_Set

   call    LongBeep               ; Beep on incorrect PIN and reset
   move    A[10], #0000h
   move    A[11], #0
   move    LCD3.7, #0

ML_Closed_Check:
   move    C, PI5.3               ; Check reed switch
   jump    NC, ML_Closed_L        ; Closed, stay in current state

   call    ShortBeep              ; 4 short beeps signal transition
   call    ShortPause
   call    ShortBeep
   call    ShortPause
   call    ShortBeep
   call    ShortPause
   call    ShortBeep
   call    ShortPause
   jump    ML_Open                ; Switch opened, go to OPEN state

圧電ブザーの使い方

アプリケーションでは、小型圧電ブザーにより以下の2つの機能を実現しています。(1)キー押下や不正なPINの入力に対し、音によるフィードバックを提供する。(2)システムセキュリティが設定されているときリードスイッチが開くとアラームを発報する。

デモ目的の場合、MAXQ2000の2つのポートピンに接続するだけで小型圧電ブザーをインタフェースすることができます。圧電ブザーの電流駆動を増加するために、ポートピンは差動で駆動されます。また、ブザーのトーン周波数は、ドライバコードのループカウント数によって決まります。


ShortBeep:
   move    LC[1], #100       ; Number of cycles
SB_L1:
   move    PO5.6, #0
   move    PO5.7, #1

   move    Acc, #2000        ; Count for forward polarity period
SB_L2:
   sub     #1
   jump    NZ, SB_L2

   move    PO5.6, #1
   move    PO5.7, #0

   move    Acc, #2000        ; Count for reverse polarity period
SB_L3:
   sub     #1
   jump    NZ, SB_L3

   djnz    LC[1], SB_L1
   ret

実際の警報システムでは、強力な駆動回路を用いて圧電ブザーを駆動するか、ブザーの共振周波数で駆動して音量を上げるなどが考えられます。

まとめ

MAXQ2000は専用LCDコントローラペリフェラルで、LCDディスプレイに容易かつ直接つなぐことができます。MAXQ2000の柔軟なポートピン配置により、マルチプレクス型キーパッドも簡単に読むことができます。マトリクス接続されたキーのすべては、タイマー割込駆動型のステートマシンによって、最小のプロセッサオーバーヘッドでスキャンとデバウンシングを行うことができます。最後に、圧電ブザーと磁気リードスイッチも、MAXQ2000にある汎用ポートピンを使って、容易に制御可能です。

この記事はMER Vol 5に掲載されています。