ラベル 電子工作 の投稿を表示しています。 すべての投稿を表示
ラベル 電子工作 の投稿を表示しています。 すべての投稿を表示

2009年8月16日日曜日

錠剤カウンタの制御部

そろそろ大詰めになってきた錠剤カウンタ。


・電源はACアダプタを差し込むことでONとなる
・スタートスイッチを押すと、カウンタがリセットされ、モータが回転する。
・錠剤の落下から10回転しても次の落下が見られない場合には、錠剤がなくなったとみなし回転を停止する

さらに、

・回転は、定常速度まで徐々に加速する

ようにしたいところ。

2009年8月15日土曜日

カウンタ部を基板に乗せてみた


少々手間取ったものの、移動完了・・・

空きスペース部分に、メインのコントロール部を載せる予定。

2009年8月9日日曜日

カセットを置く台


錠剤カセットを固定するための台を製作。
桐材・120*100*15mm

接着剤が落ち着くのを待つ。
さらに、モータの振動で外れないようにする工夫が必要。

2009年7月31日金曜日

とりあえず脈モニタにしてみた

非反転増幅アンプを作ってみたところ、Spiceでの予想どおりの動作。
気分がいいので、

フォトインタラプタ + 50倍非反転増幅アンプ + シュミットトリガ + 情けないブザ → なんとなく脈モニタ

にしてみました。





黄色線:フォトトランジスタの出力を50倍に増幅
赤色線:シュミットトリガの出力



フォト・インタラプタ部:


赤外LEDとフォトトランジスタの間に指を入れます。
指の中で脈を打っている血流で、赤外線量が変化するのです。
この信号が、次のアンプで増幅される。


50倍非反転増幅部:

Spiceでsimした回路。無難に動きました。
AC電源の部分は、 +5Vを加えたTPS616のエミッタに接続(100KΩ両端に電圧発生)、R11を100KΩとしておよそ50倍の非反転アンプとした。



シュミットトリガ部:

以前、錠剤をカウントするときに考えたものです。


情けない音のブザ:


440Hzの音がでます。わざわざこのために、PICを焼きました。PIC便利ですね。
↑ここまで

2009年7月30日木曜日

情けない音のブザができた


圧電ブザと12F675で、440Hzのブザを作りました。

GP2がHIになると、440Hzの方形波をGP0から出力します。



今にも死にそうな、予想以上に情けない音がします。

でもこれでいいんです。後で使います。


2009年7月21日火曜日

カウンタ零号機、初の稼働テスト


どうも筐体を加工するような工作は苦手です。
モータとセンサを取り付ける適当な容器が見あたらなかったので、ダイソーで買ってきました。

ポリエチレンの容器を。。。

なんか、熱でダレそうな素材ですが、、、まあ乗るのは綾波レイ実験機なので、これでいいでしょう。

ポリエチレンの箱を裏返し、ドリルでモータ固定用の穴2ヶ所と、ロータ軸を出す穴をあけます。ロータの穴はさらにリーマで拡大します。
錠剤が落ちてゆく穴は、ドリルの穴を並べ、ニッパでつないで切り落としました。
そして、モータとセンサを固定します。


センサは位置が決定していないので、今回はテープ固定です。


モータとモータドライバを接続。
センサ基板から555のパルス補正回路へ接続。
回転パルス発生装置とモータドライバを接続。
実験用錠剤・エスタゾラム「アメル」10錠準備完了。

さて、電源をいれます・・・・




あっという間に10錠のカウントが完了してしまいました!もっとゆっくりだと思っていたのに・・・。

やたら振動が多いのは、ステッピングモータのステップ数があまり細かくないからです。
ちょっとうるさいですよね、、、、

2009年7月20日月曜日

NE555の単安定動作

Signeticsの555と云えば、かつては、それこそ今のPICの如くにプロからアマチュアにまで弄られたICです。ジェネリック品も多数存在し、この応用の広さたるや、豆腐百珍の世界なのです。

この555の単安定動作を使えば、10-20ms幅のパルスを作るのは簡単そうですね。


参考回路を探してみましたが、Signeticsのページでは見つかりませんでした。代わりにLMC555の参考回路を発見。しかも日本語で書いてあります。

もっとも簡単でデジタル的な振る舞いをする555の代表回路で、 ̄TRIGに負方向のパルスが加わえられると、OUTに指定された幅のパルスが得られるというものです。パルスの幅は、

TH=1.1 × RA × C

という式で得られます。

今回は、10~20msぐらいのパルスを得たいので、RA=100KΩ、C=0.1uFとして、ブレッドボードで実験しました。


昨日の回路(右図)の出力は負論理ですから、そのまま ̄TRIGに入れることができます。



オペアンプの出力端子と、555のOUTにプローブを接続し、波形を写してみました。オペアンプが赤、555が黄色です。フォトインタラプタ部分を遮ってみます。




12-13ms程度の幅を持つパルスが出力されています。


つぎに、チャタリングの模倣として、トランジスタの3本足を通してみます。


パルスの幅は拡大されているものの、3つのパルスが出ています。これではチャタリング対策にはなりません。

そこで、RA=330KΩとして試してみました。パルス幅は、計算上36msほどになります。


今度は見事に、1つのパルスとして整形されました。


最後に、フォトトランジスタのコレクタ電流と、555で整形した波形をのせておきます。

RA=100KΩの時


RA=330KΩの時
これで、多少のチャタリングにも負けない、丈夫なセンサ部分が出来たのではないかと思います。

2009年7月19日日曜日

センサ部の基板化と錠剤カウントを試す


OPアンプを使用した回路はブレボ上で上手く動いているように見えても、基板に組んだときには思うように動かなかったり、厄介極まりない発振を起こすことが多々ある。本体を組み上げてから大幅な設計変更を強いられる前に、ユニバーサル基板に回路を組み、実験しておく必要がある。
ユニバーサル基板の一部に15mm幅の切り欠きを作り、その両側に発光部と受光部を設置。
ブレッドボード上のカウンタ部に接続し、実際に錠剤を使って落下テストを行ってみた。
センサ基板は水平、錠剤は垂直という条件となっている。



結果は誤カウントもなく計測できた。後半は、念のためにオシロでOPアンプの出力波形を観測した結果。
2本足のLEDを落とすとパルスは2つ、3本足のパワトラを落とすと3つ波形が出ているあたりは、律儀です。
スイープ速度と画面更新の関係で、画面外に表示されて見えないパルスがあるのは3万円のオシロだからかもしれません。

次に、センサ配置による隙間の影響を考えてみました。棒を、フォトトランジスタを1,2,3と順に遮るように動かした結果です。

まず、直径3mmほどの耳掻きです。


赤いラインはフォトトランジスタの負荷抵抗にかかる電圧(前回の回路図の点Aの電圧)、黄色いラインはOPアンプの出力電圧の変化です。

センサ間隙に耳掻きが入ったときには、光量が増加しているのがわかります。センサは3つなので、下向きの山は3つになっています。しかしどちらかのセンサをわずかに遮るサイズなので、シュミットトリガの働きもあり、出力は1つのパルスになっています。


次は、直径1mmもないLEDの足です。


センサの間隙に収まった際には、光が遮断されていないことがわかりました。出力波形も山3つです。対策としてはセンサの密度を上げるのが簡単で正攻法なのですが、サイズ的には面実装の超小型品をつかわなければならないなど現実的ではありません。

カウントする錠剤は、もっとも小さい(薄い)ところでも1mmはあるでしょうから重複カウントされる心配は少ないのですが、さらに10ms~20msのタイマを加えパルスの最短幅を10~20msに揃えるか、PIC側でその処理を行うか、という対策を、ダメ押しでしておく必要があると思います。


それにしても、OPアンプの出力に、リンギングのような波形が見られるのが大変気になります。

2009年7月18日土曜日

OPアンプによるヒステリシス回路


前回作成したフォトインタラプタには欠点があります。それは発光側と受光側の距離に反比例して、フォトトランジスタのコレクタ電流が減少することです(TPS616データシート参照)。負荷抵抗に発生する電圧がPIC入力端子の閾値を超えないと、ソフトウェアで変化を検出することができません。

LEDの輝度を上げるのは限界があります。
そこで、今回はOPアンプを使用してみました。この方式では、反応する閾値を設定できることと、ヒステリシスを持たせられるという利点があります。

その回路図です。
受光部に幅を持たせるため、TPS616を3つ直列にしています。どの受光部が遮られてもコレクタ電流が低下します。このほかに小信号用ダイオードを介して並列にする方法や、シュミットトリガ入力を持つORを使う方法も考えられますが、部品点数が増えて面倒なのでやめました。


シュミットトリガになる動作を解説しておきます。
今回の実験回路での発光ダイオードとフォトトランジスタの距離は15mmで、障害物が全くないときの点Aの電圧は約1.65Vでした。


まず、OPアンプの出力が0Vである場合です。バイアス抵抗は次の等価回路と考えられます。
この時の点Bの電圧は1.17Vとなるので、点Aの電圧がこの電圧を下回らないと、出力は反転しません。



次に出力が反転すると等価回路は次のようになり、
今度は点Aの電圧が1.43Vを越えなければ、出力が反転しないことになります。

つまり、R4とR5でバイアスを決定し、R6でヒステリシスの幅を決めることができます。
ただし実際には、OPアンプの出力の幅は0→5Vではありませんし、負荷側の影響も受けますから計算通りにはなりません。E12やE24に収まるよう、実験で適当に決定する必要があります。

以下、光の遮断と、点Bの電圧変化の様子です。


最後に。東芝の光センサという資料ですが、p.63のOPアンプを使用したシュミットトリガの回路図が変な気がするのですが、どうなんでしょう。

2009年7月17日金曜日

フォトインタラプタの実験


錠剤が落ちたかどうかを判定する簡単な方法は、発光ダイオードから放射される光をフォトトランジスタで受光しておき、モノが通ると光が遮られることを利用した、通過型センサを用いることでしょう。
さっそくブレッドボード上に作ってみました。左が発光部、右が受光部です。


TPS616のデータシートにあるスイッチング時間測定回路を、R=180Ω(LED電流を28mA)、RL=1kΩとして構成。このときのTLN119とTPS616の距離は、約15mm。





出力の部分には、動作確認のために2SC1815を介したモニタ用LEDを接続するとともに、完成品で使用する予定の十進カウンタにも接続。
あっさりと動作。



ピンセット、抵抗の足、耳掻きを順に通してみた。カウンタは16F84Aで構成し、シュミットトリガを内蔵したINT線を入力に用いているためか、意外にもチャタらずに大人しくカウントしている。抵抗の足のような細いモノでも反応してくれるのは少し感動するところである(すばやく動かした場合にはさすがに反応しないが)。

実験中、通過させる際にLEDやフォトトランジスタに触ってしまい、少し光軸がずれただけで動かなくなり、何回か動画を撮り直した。

なお、光入力時に出力端子に出ている電圧は、0.80Vであった。このときフォトトランジスタに流れている電流は約0.8mAということになる。

この実験から分かったことは、
  • 蛍光灯下でもフリッカに影響されず期待したように動く
  • TLN119とTPS616のペアは実用的な指向性が見られる
  • ちいさな錠剤の検出にも期待が持てる
  • とりあえずチャタリングは起こさなさそうである
といったところか。

自動錠剤分包装置


自動錠剤分包装置、と言われてすぐにわかる人は少ないだろうから、なにをするための装置なのかを紹介しておこう。


中には、錠剤が入ったカセットがたくさん並んでいる。


カセット裏側:0.8モジュールのポリアセタール歯車を介して内部のロータを駆動される。
回転により、歯車上部のスリットから錠剤が1つ単位で落下する。

本体側:駆動用の歯車と、錠剤が落下するため孔部。面実装型のフォトトランジスタが8個並んでおり、反対側に設置されたLEDからの光を落下する錠剤が遮断することにより、錠剤の落下を検知する仕組み。


指示を出すPCの画面。ここで落下させる錠剤の種類、数、用法、パターンの指示を行う。


これが実際に分包された見本。朝に服用する分、昼に服用する分、夕方に服用する分それぞれに必要な薬が必要な数だけ含まれる。
これをワンドーズパッケージまたは一包化製剤と呼ぶ。

この一包化を行うための装置が、自動錠剤分包装置なのだ。

2009年7月15日水曜日

ワイヤリングペンの作成


カウンタ部分をブレッドボード上に作成したのだけれど、4つの7SEG LEDを配置するときの配線が面倒だった。ユニバーサル基板においても、バスの配線は基本的に面倒な作業になる。

そこで、ワイヤリングペンを作ってみた。


材料
・0.5mm シャープペン(ミツビシ・M5-108 Uni Aqua Touch)
・プラスチックボビン(サンヒット・メリーホビー)
・アルミ針金(エコー金属・1.5mm×7.5m)
・0.2mm UEW線(SUNCO Corp.20m)

ポリウレタン線以外は、百円ショップSeriaで購入。

シャープペンを選ぶときのポイントは、1)半透明で中が見やすいこと、2)頭の部分を回転させて外せること、3)中の機構部を取り除けること、4)おしりを取り外せること である。

まずシャープペンを加工します。
外せるところは、全部外してみます。







芯を押し出した状態で、芯をホールドする機構部を突出させます。
そして、電工ニッパーで切り落とします。





バラバラになりました。
内部の機構は捨てますが、頭に残る白い軸のようなものはワイヤーのガイドとして残すことにします。






次に、ボビンにUEW線を巻きます。
菜箸を2本つかうと早く、綺麗に、楽に巻くことが出来ます。
1本はボビンに通して回転軸とし、もう一本はUEW線が絡まらないよう吊るために用います。










ポリウレタン線のコイルが詰まってきたり、絡み始めたら、ボビンを中心にして1-2回、巻線をほどく方へ回転させると、自然にポリウレタン線はほどけてきます。無理に引っ張ったりすると終了です。











 上手く巻くと、20mでこのぐらいになります。








先端からUEW線を引き出します。
まだボビンから箸を外さない方が賢明です。







最後に、アルミ針金で固定します。ボビンが軽く回るように調整します。UEW線を交換する毎に折り曲げることになるため、消耗品と考えたほうが楽です。



ポリウレタン線は、

・細くて丈夫
・ポリウレタン塗装されており絶縁線として使える
・半田ごての熱で被覆が取れるためそのまま半田付けしやすい


というメリットがありますが、

・細いので大電流は流せない
・バス配線とする場合クロストークが出る(周波数が上がるほど強くなりやすい)
・熱に弱く、被覆が薄いためショートを起こす場合がある


というデメリットも存在します。

自分用や試作には大変便利なのですが、商品に使用するのは不適と思います。

フォトトランジスタと赤外線LEDの購入



大須のタケイムセンで、フォトトランジスタと赤外線LEDを購入。
フォトトランジスタがTPS616(可視光カットタイプ)、赤外LEDがTLN119(非カットタイプ)。



最近の型番を知らなかったものだからお店で「可視光カット」「3φ」という条件で購入したのだが、帰ってから型番を忘れてしまい、お店へ電話して教えて貰った次第。

可視光カットのPTrを選ぶ理由は、電灯からの電灯線周波数の変調光の影響を減らすため。他の光源からの影響を避けるとき、簡単に思い浮かぶのは、

1) 一定帯域のLED-PTrの組み合わせを使う
2) 発光に変調を掛け、変調光のみを検出する

という方式。2)の方式にすればエアコンやテレビのリモコン類との干渉も防ぐことができるのだが、今回は落下する錠剤を数えるためのセンサなので、簡単な1)を選んだ。完成品は遮光することになるのだけれど、微調整を行うときには電灯下で行うことになるため、できるだけノイズを減らしたいという意図がある。


2009年7月12日日曜日

10進カウンタの試作


錠剤カウンタで使用する10進カウンタを、16F84Aで作ってみました。


友人から教えていただいた、7セグメントLEDをダイナミック点灯する方式の回路をそのまま流用することにし、入力にシュミットトリガを持つINT線の割込を使いたかったので、プログラムの部分は作りました。

RA0~3でPNPトランジスタをスイッチすることでセグメントを選択し、RB1-7で各セグメントa-gを点灯させます。RB0はINTの入力とし、信号の立ち上がりでカウンタをインクリメントします。74138あたりのデコーダを用いれば桁数はもっと増やせそうな気がします。

以下、プログラムの内容です。

;
; for 16F84A Decimal Counter
;
; Ver 0.01 6, Jul 2009
; Ver 0.02 10, Jul 2009 カウンタ各桁の表示はループを使わず展開して行う
;
;
;
;


LIST P=16F84A

INCLUDE P16F84A.INC
ERRORLEVEL -302,-306

;
; configration bit
;
__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

__IDLOCS H'FFFF'


;*********************************************************
; Label definition
;*********************************************************

;RAM領域のマッピング(0x20-0x4f)

VARIABLES equ 0x20 ;プログラム中で使用するレジスタ群
COUNT_DATA equ 0x30 ;BCDカウンタ 表示用RAM領域
SEG_DATA equ 0x40 ;7セグメント駆動用パターン領域


;-----------------------------------
; プログラムで使用する変数領域の確保
;-----------------------------------

cblock VARIABLES

;Disp_Seg ;
t1mc ; 1ms確保するサブルーチン内でのカウンタ

w_save ; INT 開始に伴うメインルーチンのWレジスタ値保管領域
s_save ; INT 開始に伴うメインルーチンのStatusレジスタ値保管領域

endc

;-----------------------------------
; 表示用10進数の保管領域(BCD値)の確保
;-----------------------------------

cblock COUNT_DATA

DEG_100 ;1の位
DEG_101 ;10の位
DEG_102 ;100の位
DEG_103 ;1000の位

endc

;-----------------------------------
; 7セグメント表示データの保管領域
;-----------------------------------

; 7セグの表示はテーブルを作成し、
; 先頭アドレス(SEG_DATA)+indexで読む
;
; SEG_DATA
; ↓
; 0123456789

; Anode Common にて駆動する
; 0:点灯 1:消灯

; b'gfedcba-'
SEG_0 equ b'10000001'
SEG_1 equ b'11110011'
SEG_2 equ b'01001001'
SEG_3 equ b'01100001'
SEG_4 equ b'00110011'
SEG_5 equ b'00100101'
SEG_6 equ b'00000101'
SEG_7 equ b'10110001'
SEG_8 equ b'00000001'
SEG_9 equ b'00100001'


; 16F84にはEEPROMが無いため、RAM領域へ作成
; Initial Process にて、LW→seg_xへ格納される

cblock SEG_DATA

seg_0
seg_1
seg_2
seg_3
seg_4
seg_5
seg_6
seg_7
seg_8
seg_9

endc

;*********************************************************
; EEPROM Data definition
;*********************************************************


; 16F84にはEEPROMは存在しない



;*********************************************************
; Program Start
;*********************************************************

ORG 0 ;Reset Vector
GOTO INIT
ORG 4 ;Interrupt Vector
GOTO INT

;*********************************************************
; Initial Process
;*********************************************************

INIT
;WPUを無効
bsf STATUS,RP0 ;change to bank 1
movlw b'11010111' ;PU OFF, PosEDG, INTCLK, NegEDG, TMR0, 1/256
movwf OPTION_REG ;set option registor

;Port の 設定
;
;Port A
;RA0 OUT: LED 1の位 選択
;RA1 OUT: LED 10の位 選択
;RA2 OUT: LED 100の位 選択
;RA3 OUT: LED 1000の位 選択
;RA4 IN: Counter Reset

bsf STATUS,RP0
movlw b'00010000'
movwf TRISA

;Port B
;RB0 IN: Counter Input(INT 立ち下がり)
;RB1 OUT: Seg A 選択
;RB2 OUT: Seg B 選択
;RB3 OUT: Seg C 選択
;RB4 OUT: Seg D 選択
;RB5 OUT: Seg E 選択
;RB6 OUT: Seg F 選択
;RB7 OUT: Seg G 選択

bsf STATUS,RP0
movlw b'00000001'
movwf TRISB

;Bank 0 に戻す
bcf STATUS,RP0

;GPIO 初期化
clrf PORTA
clrf PORTB


; test

movlw DEG_100
movlw seg_0


;7セグメントの表示パターンをRAM領域へ展開

movlw SEG_0
movwf seg_0
movlw SEG_1
movwf seg_1
movlw SEG_2
movwf seg_2
movlw SEG_3
movwf seg_3
movlw SEG_4
movwf seg_4
movlw SEG_5
movwf seg_5
movlw SEG_6
movwf seg_6
movlw SEG_7
movwf seg_7
movlw SEG_8
movwf seg_8
movlw SEG_9
movwf seg_9

;各桁を0にリセット
clrf DEG_100
clrf DEG_101
clrf DEG_102
clrf DEG_103


;割り込みの設定

bcf STATUS,RP0
movlw b'10010000' ;GIE ON, EEPROM OFF, TMR0 OFF, INTE ON, RBIE OFF, IF CLR
movwf INTCON

;Bank 0 に戻す
bcf STATUS,RP0



;*********************************************************
; Main Routine
;*********************************************************

MAIN
;-----------------------------------
; 数値表示部
;-----------------------------------

;千の位のセグメントを表示
movlw b'00001110' ; 千の位のA1015をONにする
movwf PORTA ; A1015 ON

movfw COUNT_DATA+3; W に 千の位の値をロード
addlw SEG_DATA ; W に 点灯パターンの先頭値にIndex値を加える
movwf FSR ; テーブルのアドレスをセット
movfw INDF ; テーブルの数値を得る
movwf PORTB ; 点灯パターンをPORT B に出力

call T1ms ;1msの表示ウェイト

;百の位のセグメントを表示
movlw b'00001101' ; 百の位のA1015をONにする
movwf PORTA ; A1015 ON

movfw COUNT_DATA+2; W に 百の位の値をロード
addlw SEG_DATA ; W に 点灯パターンの先頭値にIndex値を加える
movwf FSR ; テーブルのアドレスをセット
movfw INDF ; テーブルの数値を得る
movwf PORTB ; 点灯パターンをPORT B に出力

call T1ms ;1msの表示ウェイト

;十の位のセグメントを表示
movlw b'00001011' ; 十の位のA1015をONにする
movwf PORTA ; A1015 ON

movfw COUNT_DATA+1; W に 十の位の値をロード
addlw SEG_DATA ; W に 点灯パターンの先頭値にIndex値を加える
movwf FSR ; テーブルのアドレスをセット
movfw INDF ; テーブルの数値を得る
movwf PORTB ; 点灯パターンをPORT B に出力

call T1ms ;1msの表示ウェイト

;一の位のセグメントを表示
movlw b'00000111' ; 一の位のA1015をONにする
movwf PORTA ; A1015 ON

movfw COUNT_DATA+0; W に 一の位の値をロード
addlw SEG_DATA ; W に 点灯パターンの先頭値にIndex値を加える
movwf FSR ; テーブルのアドレスをセット
movfw INDF ; テーブルの数値を得る
movwf PORTB ; 点灯パターンをPORT B に出力

call T1ms ;1msの表示ウェイト

;-----------------------------------
; リセットスイッチ判定
;-----------------------------------

btfss PORTA, 4 ; RA4が1なら次の命令をスキップ
goto MAIN ; そうでないならMAINの継続
goto INIT ; 初期化へ


;*********************************************************
; 1ms wait routine
;*********************************************************

T1ms ;1000命令こなす Routine
movlw .249 ; 1
movwf t1mc ; 1
t1mlp nop ; 1*249
decfsz t1mc,f ; 1*249 + 1(skip)
goto t1mlp ; 2*248
nop ; 1
return ; 2 sum 1000

;*********************************************************
; Interrupt Routine
;*********************************************************

;-----------------------------------
; レジスタ情報保存 と 割り込み分岐
;-----------------------------------
INT
movwf w_save ;Wレジスタを保存
movfw STATUS
movwf s_save ;STATUSレジスタを保存
bcf STATUS,RP0
btfss INTCON,INTF ;GPIFの変化なら次の命令をスキップ
goto INIT ;不正終了は初期化へ

;-----------------------------------
; カウンタのインクリメント
;-----------------------------------

; カウンタは1ずつ増加

intmain
; 1の位の処理
incf DEG_100 ;1の位を+1
movfw DEG_100 ;比較のためワークレジスタへコピー
xorlw .10 ;10になったらゼロフラグ=1
btfss STATUS,Z ;ゼロフラグが0なら次の命令をスキップ
goto intend ;メインルーチンへ復帰するプロセスへ

; 10の位の処理
clrf DEG_100 ;1の位を0にする
incf DEG_101 ;10の位を+1
movfw DEG_101 ;比較のためワークレジスタへコピー
xorlw .10 ;10になったらゼロフラグ=1
btfss STATUS,Z ;ゼロフラグが0なら次の命令をスキップ
goto intend ;メインルーチンへ復帰するプロセスへ

; 100の位の処理
clrf DEG_100 ;1の位を0にする
clrf DEG_101 ;10の位を0にする
incf DEG_102 ;100の位を+1
movfw DEG_102 ;比較のためワークレジスタへコピー
xorlw .10 ;10になったらゼロフラグ=1
btfss STATUS,Z ;ゼロフラグが0なら次の命令をスキップ
goto intend ;メインルーチンへ復帰するプロセスへ

; 1000の位の処理
clrf DEG_100 ;1の位を0にする
clrf DEG_101 ;10の位を0にする
clrf DEG_102 ;100の位を0にする
incf DEG_103 ;1000の位を+1
movfw DEG_103 ;比較のためワークレジスタへコピー
xorlw .10 ;10になったらゼロフラグ=1
btfss STATUS,Z ;ゼロフラグが0なら次の命令をスキップ
goto intend ;メインルーチンへ復帰するプロセスへ

; 9999を超えた場合の処理
clrf DEG_100 ;1の位を0にする
clrf DEG_101 ;10の位を0にする
clrf DEG_102 ;100の位を0にする
clrf DEG_103 ;100の位を0にする

intend
bcf STATUS,RP0
bcf INTCON,INTF ;GPIFクリア
movfw s_save
movwf STATUS ;STATUSレジスタ復帰
swapf w_save,f ;Wレジスタの復帰
swapf w_save,w ;フラグを変化させないで戻す
retfie ;INT routineの終了

END


メモリにも余裕がありますし、わざと冗長に作ってあります。あとで改造したりするときに読みやすい方が好ましいからです。
MAIN部は永遠に10進数を保管しているレジスタを表示し続けるだけで、割込が入ったときに、そのレジスタをインクリする処理にしています。プログラムで立ち上がり/立ち下がりを検出するのは面倒だと思ったからです。

PICを焼き、可変周波数発生回路から信号となるパルスをいれてみました。同じ信号を以前に作成したステッピングモータドライバにも入れてみたので、回ります。



このカウンタ、FFFFまでカウントできる16進カウンタにもすぐに改造出来ると思うので、4桁表示のままでも60000回越えのカウントができますね。