時計モジュール(RTC)

取得したデータに、日付や時刻情報を付加しておくと便利です。この日付や時刻情報を低電力かつ高精度提供してくれるモジュール:RTC を紹介します。

  1. 時計モジュール:RTC8564

     RTC8564は内部に水晶発振子を組み込んだ時計(Real Time Clock)です。表面実装タイプですから、ここでは小型基盤に組み込んだモジュールを利用します。
    電圧は 1.8-5.5V で動作します。I2C 接続で可能で、消費電力は アクセスした瞬間は 800μA、それ以外は 275nAです。


     年月日、時分秒を初期設定すると、水晶時計の精度で日時を更新してくれます。また、指定時間で間隔で INT 端子を利用して割り込み信号を出してくれます。

  2. RTCの接続(I2C)

     接続端子は上図の左下を1ピンとしたとき、下のようになります。: の次が端子番号です。

     電源 VDD:8、 VSS(GND):4
     I2C  SCL:5 、SDA;5
     クロック CLKOE:1、 CLKOUT:2、 INT:3

    CLKOE をHIGH にすると CLKOUT からクロックが出力されます。INT は割り込み出力端子で、RTCのレジスタに周期を設定する、指定間隔で INT に割り込み信号を出します(ここでは利用しません)。VDD,GND に 3.3V(5Vも可)電源を接続します。全体の写真は、「温度センサー」の節を参照してください。

  3. RTCの利用

     アラーム機能などを利用しない場合、レジスタ 0,1 に 0 を書き込みます。2番地から、秒、分、時、日、曜日、月、年、を16進で設定します。曜日は 日月火水木金土 に対し、0123456 を指定します。この値が、時間の経過で更新されます。
     逆に、日付・時刻を読みだすときは、このレジスタから読みだします。
  4. RTCライブラリ

     最初に rtc_init() で初期設定します。rtc_date_set() で、配列 dt[] 秒、分、時、日、曜日、月、年 をレジスタ2番以後に設定します。読みだすときは、rtc_date_read() を利用します。あとは、loop() で一秒間隔で、日時を読み出しシリアルモニターに表示します。
     
    #include <Wire.h>
    //RTC realTimeClock
    
    void rtc_init()
    {    
        //delay_ms(700);
        Wire.begin(); // begin master
        int ans;
        Wire.beginTransmission(RTC_ADRS);
        Wire.write(0x00);  // control0のアドレス
        Wire.write(0x0); // test=0
        Wire.write(0x0); //AIE=TIE=0 タイマー、アラーム割り込み停止
        ans=Wire.endTransmission();
    }
    
    //日付・時刻設定
    void rtc_date_set(byte dt[])
    {
        int i;   
       Wire.beginTransmission(RTC_ADRS) ;
       Wire.write((byte)0x0);
       Wire.write((byte)0x0);
       Wire.write((byte)0x11);//reg1
       for(i=0;i<7;i++){
          Wire.write(dt[i]);//秒、分、時、日、曜、月、年(00-99)
       }
       Wire.endTransmission();
    }
    
    //日付・時刻読み出し
    void rtc_date_read(byte cdt[])
    {
        int i;
        //Serial.print(&quot;get date:&quot;);
        Wire.beginTransmission(RTC_ADRS); //
        Wire.write(0x02); // 秒のアドレス
        Wire.endTransmission(); 
        //Serial.print(&quot;request date:&quot;);
        Wire.requestFrom(RTC_ADRS, 7);
        i=0;
        while(Wire.available())   {
         cdt[i] = Wire.read() & mask[i]; // receive a byte as character
         //Serial.print(cdt[i],HEX);   // print date
         //Serial.print(&quot;,&quot;);
         i++;
        }
        Wire.endTransmission();
    }
    
    void rtc_getstatus(byte st[]){
          //get status:
        Wire.beginTransmission(RTC_ADRS);
        Wire.write(0x01); //ctrl reg
        Wire.endTransmission(); 
        Wire.requestFrom(RTC_ADRS,2) ;
        st[0] = Wire.read()  ; // Reg 01H を受信する
        st[1] = Wire.read()  ; // Reg 02H を受信する
        Wire.endTransmission();
    }

  5. 時刻表示プログラム

     RTC のライブラリーを利用して、シリアルモニターと LCD の年月日と時分秒を表示します。現在の日時に設定するには、配列 dt[] を編集します。一度、設定したら、電源を切らない限り時刻を更新します。

    //秒、分、時、日、曜、月、年(00-99)
    byte dt[7]={0x0,0x45,0x16,0x13,0x1,0x2,0x14};
    byte cdt[7];
    byte mask[7]={0x7F,0x7f,0x3F,0X3F,0x7,0x1F,0xff};
    
    int i;
    int RTC_ADRS=0x51;
    
    void setup()
    {
      delay(100);//wait rtc
      Serial.begin(9600);
      rtc_init();
      rtc_date_set(dt);
      lcd_begin();
    }
    
    void loop()
    {
      char buff[10];
      rtc_date_read(cdt);
      //年月日
      sprintf(buff,"%2x %2x %2x",cdt[2],cdt[1],cdt[0]);
      lcd_setCursor(0,0);
      lcd_print(buff);
      //時分秒
      sprintf(buff,"%2x %2x %2x",cdt[6],cdt[5],cdt[3]);
      lcd_setCursor(0,1);
      lcd_print(buff);
      //シリアルモニタ出力
      for(i=0;i<7;i++){
        Serial.print(cdt[i],HEX);
        if(i==2) Serial.print(":");
        else Serial.print(" ");
      }
      Serial.println();
      delay(1000);
    }
    

     プログラムを入力後Arduinoボードに送りこみます。結果は シリアルモニターで確認します。
    0 45 16:13 1 2 14 
    1 45 16:13 1 2 14 
    2 45 16:13 1 2 14 
    3 45 16:13 1 2 14 
    4 45 16:13 1 2 14 
    5 45 16:13 1 2 14 

    LCDの表示、上段が 時・分・秒、下段が 年・月・日


  6. 発展

     
    1. RTCの電源を切ると日付も消えますか?

      消えてしまいますから、スパーキャパシタなどでバックアップ用の電源を用意する必要があります。

    2. アラーム機能はありますか?

      設定できます。アラーム時刻になると割り込み信号が出ますから、割り込みを受けたMPU側で割り込み原因をチェックします。

    3. 時間の精度は?

      水晶発振子を内蔵しています。通常のクオーツ時計の精度です。長時間の精度が必要な場合、時報に合わせて秒をリセットするなどの機能が必要です。

    4. RTCの割り込みはどんな時に利用しますか?

       MPUが一定時間間隔で処理をする場合(他の時間は仕事がない)、MPU を 「スリープ」状態にします。これで、MPU の消費電力が1割以下になります。スリープから解除するのに RTC の割り込みを利用します。RTC は常時 250nA しか電流を必要としませんから全体で消費電力を削減できます(ボタン電池で動作可能になります)。