PICの工作(3)



 PICを使った短時間タイマーの製作

PICを使った短時間タイマー(露光時間設定用)の詳細を紹介します。



 ポジ感光基板の製造年月日によって露光時間が違うので、短時間タイマーを作り時間をセッティング できるようにしました。
「プリント基板用露光機」のタイマーを外して、このAC100V用短時間タイマーを接続して露光機を 使用することにしました。
 タイムは、1秒から9分59秒までセットできるようにしました。
  製作に当たっては、mcalcさんの長時間タイマーhttp://mcalc.zapto.org/mcalcHome/otherDoc/timer/index.html を参考にさせていただきました。



  完成作品


 短時間タイマには、PIC16F84Aを使用しています。
 電源スイッチ PowerSWをONに入れると、7SEG_LEDが002、020、200と表示されます。 動作確認です。
 その右中ほどにあるにあるSWをStop&Set側にして、右下にあるSelectSWをタイマーを セットしたい「分」と「秒」により「Min」、「Sec」側にし、「UP」「Down」のプッシュSWを 押すとカウントアップとカウントダウンがされタイマーの時間をセットします。

 時間をセットしたら、中ほどのSWを「Start」側にするとカウントダウンが始まり、 それと同時にコンセントに接続したAC100V用の器具がONになります。
 7SEG_LEDの表示が0.00になるとAC100Vの電源がOFFになりブザーが鳴ります。 「Start」SWをStop&Set側にして終了です。




  回路図


 下記に回路図を表示しておきます。




  回路図の概略


1.PIC16F84Aを次のように使用しています。
(1)RA0~RA3:3つの7SEG-LEDを表示するためのデコーダ/ドライバ「74HC4511」へ
(2)RA4:StartとStop&切替用スイッチへ
(3)RB0~RB2:7SEG-LEDの各桁点灯用トランジスタへ
(4)RB3:SSRへの出力端子
(5)RB4:ブザーの+端子へ
(6)RB5:時間をセットするための分と秒の切り替えSWへ
(7)RB6:時間をカウントアップするプッシュボタンSWへ
(8)RB7:時間をカウントダウンするプッシュボタンSWへ

2.SSRは、秋月電子のソリッドステート・リレーキットを使用しています。

3.セラミック発振子は10MHzです。

4.本来は、
(1)RB3:時間をセットするための分と秒の切り替えSWへ
(2)RB4:SSRへの出力端子
(3)RB5:ブザーの+端子へ
とする予定でしたが、プリント基板作成時に間違えましたので、プログラム上で修正しました。




  プログラムコード


 短時間タイマーのPICプログラムを掲載しておきます。

// ShortTimer

#include <16F84A.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(CLOCK=10000000)

#byte port_a=5
#byte port_b=6

byte SEC;
byte MIN;
byte COUNT;
byte SEG_PIN;
byte STATUS;
byte bdata;

//割込み処理、タイマー0
#INT_RTCC
int_clock()
{
  if(STATUS==1){
    if(COUNT==0){
      if(SEC==0){
        if(MIN==0){
          STATUS = 0;
        }
        else {
          MIN--;
          sec = 59;
          COUNT = 38;
        }
      }
      else {
        SEC--;
        COUNT = 38;
        if((SEC-(SEC/3)*3)==0) COUNT++;      //3秒に1度COUNTを+1して調整
      }
    }
    COUNT--;
  }
}

// LEDのダイナミック点灯
light_seg(){
  int bcd;
  int xxx;
  int yyy;
  xxx = SEC;
  yyy = MIN;

  if(SEG_PIN==1) bcd = (xxx - (xxx/10)*10);
  else if(SEG_PIN==2) bcd = (xxx/10);
  else bcd = yyy;
  port_a = bcd;
  port_b = bdata | SEG_PIN;
  SEG_PIN = SEG_PIN<<1;
  if(SEG_PIN>4) SEG_PIN = 1;
}

initial_Val(){
  output_low(PIN_B3);    //AC電源OFF
  bdata = 0;
  output_low(PIN_B4);    //ブザーOFF
SEC = 0; MIN = 2; COUNT = 38; SEG_PIN = 1; STATUS = 0; } // 電源オン時に 002 020 200 を表示 initial_disp(){ int i; MIN = 0; SEC = 02; for(i=0;i<100;i++) {light_seg(); delay_ms(5);} MIN = 0; SEC = 20; for(i=0;i<100;i++) {light_seg(); delay_ms(5);} MIN = 2; SEC = 00; for(i=0;i<100;i++) {light_seg(); delay_ms(5);} initial_Val(); } main(){ set_tris_a(0x10); set_tris_b(0XE0); initial_Val(); initial_disp(); setup_timer_0( RTCC_INTERNAL | RTCC_DIV_256); set_timer0(0); enable_interrupts(INT_TIMER0); enable_interrupts(GLOBAL); while(1){ if(input(PIN_A4)==0){ //Startのとき if(STATUS==0) COUNT = 38; if((SEC==00) && (MIN==00)){ //タイムアウトのとき STATUS = 0; output_low(PIN_B3); //AC電源OFF bdata = 0; output_high(PIN_B4); //ブザーON } else { STATUS = 1; //タイムインのとき output_high(PIN_B3); //AC電源ON bdata = 8; output_low(PIN_B4); //ブザーOFF } } else { //Stop&Setのとき STATUS = 0; output_low(PIN_B3); //AC電源OFF bdata = 0; output_low(PIN_B4); //ブザーOFF if(input(PIN_B5)==0){ //SelectSWがMIN if(input(PIN_B6)==0){ //UPをONで分をカウントアップ delay_ms(5); if(input(PIN_B6)==0){ MIN++; if(MIN >9) MIN = 0; while(input(PIN_B6)==0) {light_seg(); delay_ms(5);} SEC = 0; COUNT = 38; } } else if(input(PIN_B7)==0){ //DOWNをONで分をカウントダウン delay_ms(5); if(input(PIN_B7)==0){ MIN--; if(MIN >9) MIN = 0; while(input(PIN_B7)==0) {light_seg(); delay_ms(5);} SEC = 0; COUNT = 38; } } } else{ //SelectSWがSEC if(input(PIN_B6)==0){ //UPをONで秒をカウントアップ delay_ms(5); if(input(PIN_B6)==0){ SEC++; if(SEC>59) SEC = 0; while(input(PIN_B6)==0) {light_seg(); delay_ms(5);} COUNT = 38; } } else if(input(PIN_B7)==0){ //DOWNをONで秒をカウントダウン delay_ms(5); if(input(PIN_B7)==0){ SEC--; if(SEC>59) SEC = 59; while(input(PIN_B7)==0) {light_seg(); delay_ms(5);} COUNT = 38; } } } } light_seg(); delay_ms(5); } }



  プログラムの概要


1.タイマ0の割込み処理の所は、基本的には前作の「プリント基板用露光機」の割り込みと 変わりませんが、mcalcさんの例に倣い、3秒に1回COUNTを+1することにしました。

2.タイマ0の誤差分、セラミック振動子の誤差分を調整するためにいろいろと調整しましたが、 これが一番楽で簡単な方法だと思います。

3.何度か測定してみましたが8分で0.2secくらいの誤差でした。露光機用なので問題ありません。

4.7SEG点灯用のlight_seg()の変数bdataは、上記RB端子の間違いを無理やり修正するために設けました。
RB3がlowの時bdata=0、RB3がhighの時bdata=8としています。

5.initial_disp()は、mcalcさんに倣い電源投入時の7SEGの初期表示で、002、020、200と 順次表示してるだけです。