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つのステータスがあります。
磁気リードスイッチとのインタフェース
警報システムでは、磁気リードスイッチの磁気部分とリードスイッチ部分を別の場所に取り付けます。磁気部分はドアや窓の動くところに取り付け、スイッチ部分は枠組みに固定します。ドアや窓が閉まっていると、磁気によってリードスイッチが閉じ、アラームは発報していません。システムセキュリティが設定され、ドアや窓が開くと、リードスイッチのステートが変化し、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列のグリッドになっています。
キーパッドには、キーパッドマトリクスの各行と各列ごとに端子が出ており、全部で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つのキーパッドスイッチのステートを読み取ります。
割込駆動のステートマシン
キーが押されている間に確実に読み取るためには、キーパッドの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個の読み取り準備を行います。
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セグメント文字を表示することができます。
まず、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に掲載されています。