タイマー(3桁数字表示)

ここでは、タイマー割り込み機能を利用して、3桁の数字を動的表示する手法を紹介します。この方法は、4〜6桁の表示に応用できます。

  1. 3桁の7素子表示器

     7素子数字表示器は電卓などでおなじみの表示器で、7本の表示素子(多くは棒状のLED)を数字の形にならべ、0-9 の形になるように発光させます。ここでは、3桁の表示が可能な C-533 を利用します。
      
    中身は、7(小数点を含めると8)個のLEDで1ケタを表示し、それを、4本の線(DUG1,2,3,)で高速に切り替えて表示します。このモジュールは カソード(-側)が共通になっていますから(カソードコモンと呼びます)、DIG1に LOW を出力し、A 端子に HIGH を出力すると、1桁目のAセグメントが点灯します。
     表示素子を小数点が右下になるように置いたとき、左下が1ピン、右下が6ピン、になります。右上が7ピンで左上が12 ピンです。この反時計まわりの数え方はピンの数が変わっても同じです。

  2. 表示回路

     表示素子の7個の端子 a-g を Arduino の D6-D12 に(電流制限用の抵抗を通して)接続します。表示素子の dig1-dig3 をArduinoの D2-D4 に接続します。D6-D12 に数字のパターン(たとえば 0x6)を出力し、dig1 をHighにすると第一桁が点灯します。
     第2桁の数字パターンを設定し、dig2 を HIGH にすると2桁目が表示され、どうように第3、4桁を点灯し、これを繰り返して表示します。各桁を切り替えながら表示するので、動的点灯と呼ばれます。
     
  3. 3桁数字表示回路

     同じセグメントとなる 数字表示器の端子(a-g)と UNO の端子(D6-D12)を接続します。ただし、a-g の端子には 1kオームの抵抗を直列に挿入します。下図右の回路図で左の端子が UNO の端子、右が表示素子で、端子(g)の上側の数字(5)がピン番号です。
     電流は D12〜D7 から1kの抵抗を通して 7セグ素子のLEDに流れ、表示桁に従いD4〜D2に流れ込みます。電流を流すためには、D4〜D2 は L出力とする必要があります。L出力の端子はコンピュータ内部で GND と接続し、端子からの電流を「吸い取る」ことになります。 また、表示器の d1,d2,d3 を UNO の D4,D3,D2 に接続します。
        
         3桁表示回路                            回路図

  4. 時間の取得のタイマー割り込

     ここでは、開始以後の時間を秒単位で表示します。時間を知る機能として、millis() 命令があります。これは、プログラム実行開始以後の経過時間を ミリ秒単位で返してくれます。millis() は long で値を返します。前の値との時間差が 1000 以上になったら、秒の計数を増加させます。
     各セグメントの表示は一定時間以内で継続する必要があります。通常の loop()処理の中で、動的表示を行うのは困難なので、タイマー割り込み:MsTimer.h を利用します。
      #include <MsTimer2.h>
     次の命令で割り込みの間隔(m秒単位)と割り込む関数を指定します。
      MsTimer2::set(10, intr );//10mS間隔で intr メソッドを呼び出す
     実際の割り込みの開始と、終了には以下のメソッドを利用します。
      MsTimew2(start);
     MsTimer3(stop);

  5. タイマー表示プログラム

     mills()を利用し経過時間を ct に記録します。前の時刻 pt より 1000 経過したら、秒数 secc を増加し、secc を10進数に分解して、val[] の保存します。このとき、左側の 0 を表示しないよう 、segment[10] を 0 とし、左側の 0 を10に変更します。
     7セグへの実際の表示は intr() メソッドを利用します。表示する桁 を dg 、前の表示桁を pdg とします。segment[val[dg]] で、dg 桁の表示パターンを data 取り出します。digitalWrite(6+isg,bitRead(data,isg)); で表示を行いますが、6+isg が表示する ディジタル端子の番号で、bitRead(data,isg) が表示する値(1/0)になります。
     bitRead(d,n) は d の第nビットを取り出す命令です。digitalWrite(2+dg,LOW); で dg 桁のLED の表示を設定し、digitalWrite(2+dg,LOW); で前の桁の表示を停止します。
    //タイマー表示
    #include <MsTimer2.h>
    
    //下位7bitがセグメントのパターン
    byte segment[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x67,0x0};
    int val[3];
    byte dg,pdg,isg;
    byte data;
    int secc;
    int cnt;
    long pt,ct;
    
    void setup(){
      Serial.begin(9600);
      byte i;
      for(i = 2; i <= 15; i++){
        pinMode(i,OUTPUT);
      }
     //タイマー割り込みの設定 
      MsTimer2::set(4, intr );
      MsTimer2::start(); 
      secc = 0;
      pt=millis();
      val[0]=0;
      val[1]=10;
      val[2]=10;
     dg=0;
     pdg=2;
    }//setup
    
    void loop(){
      ct=millis();
      if((ct-pt)>1000) {
        secc++;
        val[2] = secc/100;
        val[1] = (secc-val[2]*100)/10;
        val[0] = secc % 10;
        if(val[2]==0)  val[2]=10;
        if((val[2]==10) && (val[1]==0)) val[1]=10;
        pt=ct;
        if(secc>1000) secc=0;
      }
    }//loop
    
    void intr(){
      //割り込みでLEDを表示
        dg++;
        if(dg==2) dg=0;
        data = segment[val[dg]];
        //各セグメントを点灯する
        for(isg=0;isg<7;isg++){ //a-gのセグメント設定
         //>>は右シフト、& はand演算 、isg番のbitを表示
            digitalWrite(6+isg,bitRead(data,isg));
        }
        digitalWrite(2+pdg,HIGH);
        digitalWrite(2+dg,LOW);
        pdg=dg;
    }

  6. 発展

    1. タイマー割り込みの周期はどれくらいが適当ですか?

       短いと UNO に負担がかかります。長くすると表示がちらつきます。4-10 暗いが適当です。

    2. 割り込み処理は必須ですか

       loop() の中で、桁を切り替えながら表示ができますが、loop() の中で長い処理があると動的表示が停止します。

    3. MsTimer2 を利用するときの :: はなんですか?

       MsTimer2 は class でなく 「名前空間:namespace」として定義されています。namespace を参照するとき :: で指定します。

    4. 時刻表示用の4桁の表示器はありませんか?

      OSL40562 などが利用できます。


    5. シリアル接続の数字モジュールはありませんか?

       スイッチサイエンスなどから 「シリアル接続4桁LED」が販売されています。RSシリアル、I2C、などで接続できます。