汎用タイマ

  1. タイマ基板を利用したタイマ


    1. wanak社の基板紹介

       マイコン1,2,3線インタフェース入門、PIC電子工作、などの著者の中尾氏が開発されている基板群です。本の執筆で作成された回路をプリント基板にして、手ごろな価格(ワンタッチタイマで500円)で頒布しています。基板は小型で多くの回路はI2Cで接続可能です。また、ICSPでプログラム可能です。
       類似の作品に「発表用タイマー」がありますが、これは基板が手作りです。

    2. wsnak社のワンタッチタイマ基板

       ここでは、wsnak社(さん)が提供するワンタッチタイマー基板を利用した、タイマ-を紹介します。タイマーの使用は以下のとおりです。

       表示:7SEGLED3桁、LED8個
       入力:スイッチ4個
       出力;リレー2個
       プロセッサ:PIC16F873A
       電源:単4電池2個

       図はhttp://www.wsnak.comより

      基板のシルクパタンです。上部のCN1 が電源、I2Cのコネクタ、中央縦がICSP(PICKEY)端子です。
      図はhttp://www.wsnak.comより

      上部左にリレー端子が2個、左下にRS232Cの接続端子もあります。

    3. 回路

       wsnakさんがPDFで公開している回路図参照させていただきます。部品の多くは、「秋月電子」で入手できます。表示7素子LEDは3桁3連の c553-SR です。この7素子LEDと8個のLEDをダイナミックドライブします。
       接続端子が多いので、74HC174を利用して出力端子を増設しています。これは6個のD型FFで、入力は7素子LEDと共用します。RB5でクロックして、出力を設定します。出力は、リレー二つと、入力のスイッチの切り替えに使用しています。
       入力の4スイッチは、2個組を切り替えて読んでいます。これだけでは、4端子利用するので端子の節約にはなりませんが、7素子LEDの端子と共用した増設出力ポート(74HC174)の余りの2本を利用しているので、出力端子を2本節約しています。このため、スイッチを読むには、増設出力ポートの6Qと5QをLレベルにしRB7,RB6 から読みます。これは、ICSPの PGDとPGC端子と兼用しています。PicKit2ではこの端子はプルダウンされるため、実行時にはPicKit2の接続を切る必要があります。
       出力はドライバTD62004を利用します。これは、出力電流最大500mA、耐圧50Vのトランジスタアレイです。TD62003も入力抵抗の違いだけです(シルクパターンは003、回路図は004になっています)。

  2. プログラム


    1. プログラム

      プログラムは公開せず、プログラムされたPICを販売しています(700円)。他の目的で利用するにはソースがひつようなので自作します。
       タイマー0を利用し、10mS毎に割込みをかけます。1秒ごとに、LEDを点滅します。表示は、0.1分(6秒)単位としました。したがって、5.5 の表示は5分と30秒です。製作者のデザインは最後の10分を、m.ss (分1桁、秒2桁)で表示するものですが、途中で1分間表示が変化しないのは不便なので、6秒単位の変則表示としました。
       今回、追加したのは時間の設定部分です。+ と - ボタンで設定しますが、6秒単位で10分を設定するのは面倒です。それで、ボタンを長押しすると、高速増加(減少)機能を追加しました。これは、ボタンが押されている間LEDのダイナミックループの回数を調べ、回数が一定値を越えたらループの速度でタイマーの値を増加(減少)させます。

    2. ソース


      //3dig Timer
      
      //sw2:start/stop
      //sw3: inc time
      //sw4: dec time
      
      
      #include <16f873a.h>
      
      #fuses HS,NOWDT,NOLVP,NOPROTECT,NOCPD,NOBROWNOUT,
      #use delay(CLOCK=20000000) //クロック20MHz
      #use fast_io(a)
      #use fast_io(b)
      #use fast_io(c)
      
      #ROM 0x2100 = {60,0}
      //#ROM 0x2110 = {"999 timer"}
              
      int dgt,count;
      long st2;
      int st1,st0,ptn;
      int swa,swb;
      int seg_data[]={0x7E,0x0C,0xB6,0x9E,0xCC,0xDA,
              0xFA,0xE,0xFE,0xCE};
      long uptime;
      long val;
      int prd;
      int ontime,secLed;
      int bsw2,bsw3,bsw4;
      long ms10;
      long loopinc,loopdec;
      
      #int_rtcc
      void rtcc_isr()
      {
              ms10++;
              if(ms10 % 100 == 0) secLed=!secLed;
              if(ms10==600){//6sec
                      uptime--;
                      ms10=0;
                      if(uptime==0) {
                              ontime=0;
                              //              
                       }
              }       
              set_timer0(prd);
              
      }
      
      void setLED(int pat);
      void clrLED();
      void buzzer();
      
      void main()
      {
        val=0;
        count=0;
        ms10=0;
        bsw2=bsw3=bsw4=0;
        
        set_tris_a(0b000000);
        set_tris_b(0b11000000);
        set_tris_c(0b11111000);
        
        output_bit(pin_b5,0);//HC174 clock
        
        //タイマ0のモード設定
        setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
      
        ontime=0;
        loopdec=loopinc=0;
        //uptime = read_eeprom(1)*256+read_eeprom(0);//last time
        uptime=60;
        //prd=60;//195*51.2=10,000 255-195=60
        
        enable_interrupts(GLOBAL);
          
        while(1){
              
              //read sw
              port_b_pullups(true);
              output_bit(pin_a1,0);//set HC174
              output_bit(pin_a0,1);
              output_bit(pin_b5,1);//clock Hc174
              output_bit(pin_b5,0);   
              swa = input_b();
              
              port_b_pullups(true);
              output_bit(pin_a1,1);//set HC174
              output_bit(pin_a0,0);
              output_bit(pin_b5,1);//clock Hc174
              output_bit(pin_b5,0);   
              swb = input_b();        
              
              if(uptime>999) uptime=100;
              val=uptime;                             
          //valを桁に分解
          if(count==0){
                st2 = val/100;
             st1 = val/10-st2*10;
             st0 = val%10;
             //val++;
          }
        
              for(dgt=0;dgt<4;dgt++){
                      
                        
                if(dgt==0) {
                        ptn=seg_data[st0];
                        setLed(ptn);
                        output_bit(pin_c0,1);
                }
                if(dgt==1) {
                        ptn=seg_data[st1];
                        bit_set(ptn,0);//dp
                        setLed(ptn);
                        output_bit(pin_c1,1);
                }
                if(dgt==2) {
                        ptn=seg_data[st2];
                        setLed(ptn);
                        output_bit(pin_c2,1);
                }
                if(dgt==3) {
                        ptn=0;//LED clear
                        
                        if(!bit_test(swa,7)){
                                bit_set(ptn,4);
                                if(bsw4) {
                                        uptime --;
                                     bsw4=0;
                                     loopdec=0;
                                };
                                loopdec++;
                                if(loopdec>100){
                                        if(loopdec % 2 == 0 && uptime >5 ) uptime--;
      
                               }
                       }
                        else {
                                bit_clear(ptn,4);//sw4 setLED4
                                bsw4=1;
                                loopdec=0;
                       };
                        
                        if(!bit_test(swa,6) ){//check sw3,4
                                bit_set(ptn,3);
                                if(bsw3) {
                                        uptime += 1;
                                     bsw3=0;
                                     loopinc=0;
                                 };
                                 loopinc++;
                                 if(loopinc>100){
                                         if(loopinc % 2 == 0) uptime++;
                                         if(uptime>999) uptime=999;
                                 };
                                 
                        }
                        else {
                                bit_clear(ptn,3);//sw3 setLED3
                                bsw3=1;
                                loopinc=0;
                       }
                        
                       if(!bit_test(swb,7) ){//check sw1
                                bit_set(ptn,2);
                                if(bsw2){
                                        ontime=!ontime;
                                    if(ontime){//タイマースタート
                                         set_timer0(prd);
                                         write_eeprom(0x2100,make8(uptime,0));
                                         write_eeprom(0x2101,make8(uptime,1));
                                         write_eeprom(0x2110,0x77);
                           enable_interrupts(INT_TIMER0);
                         }
                         else {
                              disable_interrupts(INT_TIMER0);
                            };
                          bsw2=0;
                        };
                     }
                        else {
                                bit_clear(ptn,2);//sw2 setLED2
                                bsw2=1;
                       };
                        
                        if(secLed) bit_set(ptn,5);
                        else bit_clear(ptn,5);          
                                                        
                        setLed(ptn);            
                        output_bit(pin_a4,1);
                        
                }
                
                delay_ms(4);
                
                clrLED();
                output_bit(pin_c0,0);
                output_bit(pin_c1,0);
                output_bit(pin_c2,0);
                output_bit(pin_a4,0);
                //output_bit(pin_a5,0);
                
               //delay_ms(1);
               
              }//for
              
          if(uptime==0) {
               disable_interrupts(INT_TIMER0);        
           buzzer();
               buzzer();
               buzzer();
               uptime = read_eeprom(0x2101)*256+read_eeprom(0x2100);  
               //uptime=70;  
          }
                  
          //count++;
          //if(count ==10) count=0;
          
        }//while
      }
      
      void setLED(int pat){
        
        output_bit(pin_b0,bit_test(pat,1));//a,led1
        output_bit(pin_b1,bit_test(pat,2));//b,led2
        output_bit(pin_b2,bit_test(pat,3));//c,led3
        output_bit(pin_b3,bit_test(pat,4));//d,led4
        
        output_bit(pin_a0,bit_test(pat,5));//e,led5
        output_bit(pin_a1,bit_test(pat,6));//f,led6
        output_bit(pin_a2,bit_test(pat,7));//g,led7
        output_bit(pin_a3,bit_test(pat,0));//dp,led8
        
        return;
      }
      
      void clrLED(){
        output_bit(pin_b0,0);
        output_bit(pin_b1,0);
        output_bit(pin_b2,0);
        output_bit(pin_b3,0);
        
        output_bit(pin_a0,0);
        output_bit(pin_a1,0);
        output_bit(pin_a2,0);
        output_bit(pin_a3,0);         
      
      }
       
      void buzzer(){
              
          output_bit(pin_b3,1);//Set Buzzer
          output_bit(pin_b5,1);//clock Hc174
          output_bit(pin_b5,0);      
          delay_ms(500);
                 
           output_bit(pin_b3,0);//Set Buzzer
           output_bit(pin_b5,1);//clock Hc174
           output_bit(pin_b5,0);
           delay_ms(300);          
      } 

  3. トラブル、問題


    1. PicKit2との接続

       PicKit2(ICSP)の利用も初めてなので、いくつかトラブルがありました。回路では PGDとPGCをスイッチ入力と共用していますが、PicKit2 がこの信号を L側に引くので、PicKit2を接続したままではスイッチが読めません。
       また、リレー1を出力端子にしたのですが、74HC174の12ピン(5Q)がHにならず、空きの3Q端子に切り替えました。原因は不明です(交換して見たので、ICのせいではありません、実装上の問題かと思います)。
    2. 電源

       他の問題は電源です。設計は5Vですが、単4電池*2の駆動にしています。トラブルは、予定していたリレーなしで電子ブザーを鳴らすには電圧が不足したことです。設計はオムロンのリレーになっていましたが、このリレーは3Vくらいから動作するので、このリレー経由で鳴らすことにしました。

    3. 回路設計

       7素子LEDと8個のLEDを動的点灯するのは面白い設計です。 全般的によく考えられていますが、外部ポートの増設には、74HS174(レジスタ型)でなくシフトレジスタを用いるほうが、2本で接続可能でシンプルな設計になると思います。74HS174の方が高速な処理ですが、動的表示に限定するならシフトレジスタでも十分だと思います。
       
    4. 基板設計

       ここで利用している7素子LEDは赤色の3桁です。できれば、青色も選択できる1桁KED*4の構成で設計してあれば、秒付のタイマーや時計表示ができるのですが..。
       また、コネクタが多いのですが、基板のシルクだけでは、コネクタの種類や1ピンの位置が不明です。逆差しできないコネクタを利用すればよいのですが、ピンヘッダなどを流用するとコネクタの位置や向きを間違えそうです。