PICNIC

課題2 ドア開放時間計測・警報アラーム機能の実現

■ 課題2 

1. 課題2の目標

2. ソケットタイムアウト検査用のカウンタ timer について

3. timerの各ビットをタイマポストスケーラとして利用する

4. 実験1:カウンタ timer の利用

5. 実験2:新規カウンタ counter1 の利用

6. 実験3:「ドア開放状態」のタイムアウト後、警報アラーム作動

7. 実行例

8. 課題2の提出

9. 考察のポイント

■レポート提出システム

 

→質問やお気づきの点はこちら

←目次へ戻る

2007年8月6日 17:51 更新

 

●課題2の目標

課題2として、「ドア開放時間計測・警報アラーム機能の実現」の課題提出を行う。→課題提出はここから

基本的な実装方針は以下の通りである。

・カウンタ timer をTMR1割り込みのポストスケーラとして利用する
・TMR1タイマ割り込み(約13.1msec)の間隔でドア開閉状態を検査する
・タイムアウト時間の設定
・「ドア開放状態」のタイムアウト後、警報アラーム作動

●ソケットタイムアウト検査用のカウンタ timer について

(1)概要

割り込みルーティン内 int_tmr2 が、TMR1割り込み(13.1msec)間隔で呼び出され、直後、ソケットタイムアウト検査用のカウンタ timer(レジスタBANK#1)を +1 している。

<割り込みルーティン int_tmr2ラベル付近の実装>

int_tmr2	; ソケットタイムアウトチェック
bsf STATUS,RP0 ; BANK#1
MOVLW 1
ADDWF timer,1 ; timer++1
btfsc STATUS,C ; ロールオーバーチェック
GOTO dec_tm ; ソケット用タイマ管理
; --> dec_tm9へ戻ってくる。
dec_tm9 ; dec_tm呼出し後の戻りラベル
CLRF STATUS ;

カウンタtimerは8bitなので、256回カウントアップした後、ロールオーバーし、dec_tmを呼び出している。これにかかる時間は、13.107msec x 256カウント = 3355.392msec ( = 約3.36秒 ) となる。


(2)インクリメント部分の改良

timerは+1するだけで、その後Wregは利用していないので、「MOVLW + ADDWF + Carryフラグチェック」 より、
「INCF + Zeroフラグチェック」の方が1ワード節約できて良いかもしれない。

ADD(SUB)系演算命令とINC(DEC)系演算命令は、演算後のSTATUSフラグの変化が異なる(ADD系はC,DC,Z、INC系はZのみ変化)ので適宜使い分ける。

詳細については、以下のデータシート命令詳細を参照せよ。

ADDWF命令:
PIC16F87x MIDRANGE Reference Manual page531
microchip/33023a.pdf#page=531

INCF命令:
PIC16F87x MIDRANGE Reference Manual page546
microchip/33023a.pdf#page=546

ということで、INCF+Zeroフラグチェックを行う版は以下のように実装すればよい。

<改良案>

int_tmr2	; ソケットタイムアウトチェック
bsf STATUS,RP0 ; BANK#1
INCF timer,1 ; timer++1
btfsc STATUS,Z ; ロールオーバーチェック
GOTO dec_tm ; ソケット用タイマ管理
; --> dec_tm9へ戻ってくる。
dec_tm9 ; dec_tm呼出し後の戻りラベル
CLRF STATUS ;

 

●timerの各ビットをタイマポストスケーラとして利用する

カウンタ timer の各ビット(bit0〜7)は、TMR1割り込み間隔(約13.1msec)の1:2〜1:256分周を行うポストスケーラとしてみることができる。

表1:timer各ビットの周期

----------------------------------------
bit | 分周比 | 周期(msec)
----------------------------------------
bit0 | 1:2 | 26.2
bit1 | 1:4 | 52.4
bit2 | 1:8 | 104.8
bit3 | 1:16 | 209.7
bit4 | 1:32 | 419.4
bit5 | 1:64 | 838.8
bit6 | 1:128 | 1677.6
bit7 | 1:256 | 3355.3
----------------------------------------

最上位ビット(bit7)周期は 約3.36秒。少し長すぎる。bit5の周期は 約0.84秒で、ドア開放時間の計測には、これが丁度良い。

●実験1:カウンタ timer の利用

先の課題1で作成したtest4モジュールの代わりに、呼び出された後、カウンタtimerのbit5の分周比(1:64)を利用して、約0.84秒毎に、RB4(LED#4)を点灯⇔消灯するような出力を行い、ポストスケーラとしての動作確認をしてみる。

PICマイコンの条件分岐命令としては、AND命令でビットマスクをかけて、その領域が全部ゼロの場合にZフラグが立つことをチェックする方法が一番簡単である。

従って、timer:bit5の分周比(1:64)で分岐処理をさせたい場合、bit5〜0が全て0かどうかのチェックを行って、RB4の出力値変更(H⇔L)をする実装がよい。

<特定のビット値の交換 H⇔L 方法>

XOR演算命令を行う。ビットマスクのように、
・値を変更したいビット 1
・値を保全したいビット 0
を対応させると、XOR命令1回でH⇔L値の変更ができて便利である。

例:Wレジスタのbit4を値交換H⇔Lする

   XORLW B'00010000'

<test5モジュール実装例>


test5
; 割り込みルーティンからのエントリポイント

; Wreg <- timer
; bitマスク [0011.1111]
; bit5--0が全部ゼロか?
 → test5_09

; RB4の出力状態を変更
; PORTBを読む→regW
; bit4を値交換H⇔L
; regW→PORTBへ出力

test5_09
; 割り込みルーティンへの復帰

#割り込みルーティン側からは goto test5 することは言うまでもない。

実行してみると、LED#4の点滅が1.6秒くらいで行われることが確認できる。
(どうやって? →ヒント:"点滅"を36回数えるのに約1分かかる)

LEDの点滅は、まるで、心臓の鼓動(ハートビート)のようである。

 

●実験2:新規カウンタ counter1 の利用

カウンタtimerを流用するかわりに、新規カウンタ counter1(BANK#3)を利用し、test5モジュールと同等の動作を行ってみる。もちろん、counter1のインクリメントは、自前で行わなければならない。

(変更点)

bsf STATUS,RP1
bsf STATUS,RP0 ; レジスタBANK#3

incf counter1,0 ; Wreg <- counter1 + 1
movwf counter1 ; counter1 <- Wreg

bcf STATUS,RP1
bcf STATUS,RP0 ; レジスタBANK#0

●実験3:「ドア開放状態」のタイムアウト後、警報アラーム作動

新規カウンタcounter2を利用して、「ドア開放状態」時間の計測と、タイムアウト時間の設定、ならびに通知処理を行う、test6モジュールを作成する。

counter2は実験1・2で作成した”ハートビート”の周期 timer(あるいはcounter1)でカウントアップされるものとする。(約0.84秒で+1)

ドア状態による条件分岐処理については、課題0・実験4で作成した test2モジュールが参考になるであろう。

<仕様>

・「ドア開放状態」が一定時間以上続いた場合、警報アラーム作動
・タイムアウト時間は、約10秒とする。
・ドアを閉めるとアラームは停止する。

<処理概要>

・ドア閉鎖中 : RB7(警報アラーム)オフ
         counter2をゼロにセット

・ドア開放中 : timer分周処理
         counter2が一定カウント数を超えているか?
         →超えていた場合 :RB7(警報アラーム)オン
         →超えていない場合:counter2を+1する

<タイムアウト時間の計算例>

ドア開放時、カウンタ counter2 は、TMR1割り込み間隔の1:64分周の約0.84秒でカウントアップさせる。

例えば、「ドア開放後、約10秒で警報アラームが作動するようにしたい」という要求があった場合を考える。

この場合、タイムアウトまでのカウント数は、10 / 0.84 = 11.90… となり、counter2は0からカウントを開始するから、結局、タイムアウトのための「しきい値」=12 となる。

ポイントその1:
counter2は8bitカウンタで0-255までカウント可能であるから、タイムアウト時間の最大値は、0.84秒 x 255カウント = 214.2秒(約3分半)となる。これ以上のタイムアウト時間を設けたい場合、timer(あるいはcounter1)からの分周比をもっと大きいビットから(例:bit7から)取得する。

ポイントその2:
タイムアウト時間の精度を上げたい場合は、分周比をもっと小さいビットから取得し、タイムアウト値として大きな数値をとれるようにすれば良い。

ポイントその3:
プログラムディバッグ時、counter2の値のモニターが行えると大変都合が良い。このためには、先の課題1で実装を行った、「ドア開閉回数カウンタ counter web制御画面への表示(put_countモジュール)」を参考にせよ。

●実行例

ドアを閉めている状態 → ドア開放 → (10秒経過) → タイムアウトして警報アラーム作動中
→ドアを閉めればアラーム停止 → (最初へ戻る)


●課題2の提出

【課題2】(実験3)
「ドア開放状態」時間の計測と、タイムアウト時間の設定、ならびに通知処理を行う、test6モジュールを作成しなさい。タイムアウトの時間設定は、約10秒としなさい。仕様通りの動作が行われることを、ドアセンサ状態、web制御画面、カウンタ値の変化を用いて確認せよ。

(1)「ドア開放状態」のタイムアウト後、警報アラーム作動を実現するためのtest6モジュールの作成 を行いなさい。

(2)仕様通りの動作が行われることを、ドアセンサ状態、web制御画面、カウンタ値の変化を用いて確認せよ。

(3)アセンブルソースファイルのバージョン番号を、
 ver1.2.0.7
へ変更せよ。また、web制御画面のフッタ部分を、各自の学籍番号等に適宜変更せよ。

(4)完成したアセンブルソースファイルを v1207e2.asm という名前で保存せよ(全て半角英数字・アルファベットは小文字、半角カタカナ・全角文字はファイル名には決して使用しない)。

(5)以下のレポート提出システムから、v1207e2.asm をアップロードせよ。レポート受領後、採点が行われる。

<提出方法>
作成したプログラムは以下のレポートシステム(ファイルアップロード機能付き)を用いて、アセンブル・ソースファイル(拡張子が *.asm のもの。*.hexの方ではない)を提出します。 

提出されたファイルは、こちらで動作を確認した後、動作に不備があった場合には再提出、動作がOKの場合には修了の判定を行います。

レポート課題2(課題番号:picnic-exp02)の提出はここからどうぞ

(6)「判定待ち」となります。少々お待ちください。なかなか判定結果が出ない場合は、こちらへメールして下さい。

(7)再提出判定がなされた場合には指摘された不具合を修正し、v1207e2a.asmなどとファイル名を替えて、再提出する。

(8)(7)でない場合(修了判定)、レポート課題2は受理され、完了となった。

 

●考察のポイント

以下に、今回の仕様と実装に対する考察ポイントを挙げます。レポートとして回答必須ではありませんが、プログラム完成・レポート提出前に必ず各自で考えをまとめておくようにせよ。

 

[1] タイムアウト設定時間として数秒〜数時間などという範囲を想定する場合、今回の実装のような8bitカウンタによるポストスケーラでは不都合が生じる。このような要求を満たすためにはどのように改良すればよいか?

[2] 内部タイマ自体、水晶振動子による外部クロックを分周して利用しているため、大変精度が良い(クオーツ時計と同じ)。ドア開放アラームではなく、24時間タイマとして実装・稼動させ、一定の時間間隔でリレーをオン・オフ作動させることは容易だと思われる。しかしながら、クロック(20MHz)を1:2^n分周していった場合、そのままでは1秒単位・1分単位・1時間単位のカウンタにはならない。各々を変数counter1,2,3として計算し利用するには、分周をどのように行えばよいのだろうか?

[3] カウンタ counter2 は、リセット後、何処かで初期値:=0にセットされるべきである。これは具体的に何処へ実装したらよいか?

信州大学インターネット大学院

Creative Commons License

IT技術演習(院)−PICNIC− by Katsumi WASAKI is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.1 Japan License.