反省

いきなり反省である。/INT端子の出力を取り出してないWSN256で開発したため/INT端子の挙動がいまいち理解できていなく、ライブラリィに反映されてなかったためタイマおよびアラームの挙動がおかしかった。
そこで改めて開発環境を組んで/INT端子周りのテストを行いバクを潰したのだ。

変更した開発環境

変更した開発環境

/INT端子とは

RTC8564の/INT端子はタイマやアラームが起動した時に変化する端子である。WSN256のように/INT端子をArduinoに接続してないとすると常にRTCを監視する必要がある。これではMPUの資源を浪費だ。割り込みによる通知の方が本来RTCの使い方であろう。

使い方

極々簡単な使い方は、以下の通り。

時刻合わせ

時刻合わせ方法は、下記のAdustDateのスケッチの通りだ。

#include <Wire.h>
#include <RTC8564.h>

RTC8564 RTC;
RTC_TIME rtc_time;
const char* dayofweek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void setup()
{
  Serial.begin(9600);
  RTC.begin();

  /* 2013年4月27日 0時0分0秒に時刻合わせ */
  rtc_time.year = 2013;
  rtc_time.month = 4;
  rtc_time.day = 27;
  rtc_time.hour = 0;
  rtc_time.min = 0;
  rtc_time.sec = 0;
  RTC.adjust( rtc_time );

//  これでもOK
//  RTC.adjust( 2013, 4, 27, 0, 0, 0 );
}

void loop()
{
  char buf[32];

  if(RTC.now(&rtc_time))
  {
    snprintf(buf,32,"%04u-%02u-%02u(%s) %02u:%02u:%02u\n",
    rtc_time.year,
    rtc_time.month,
    rtc_time.day,
    dayofweek[rtc_time.wday],
    rtc_time.hour,
    rtc_time.min,
    rtc_time.sec   );

    Serial.print(buf);
  }
  delay(1000);
}

RTC8564はバックアップ電源の端子を持たないので、今回作った実験回路などでは起動する度に時刻設定が必要になる。これではRTCの呈をなさないので、実際に使うときにはWSN256のようにスーパーキャパシタなどで組んだ回路で電源が落ちたときでもRTCのVCCに電圧が掛かっているようにする必要がある。

CLKOUT端子の信号

CLKOE端子を’H’レベルにした上でスケッチSetClkOutのようにするとCLKOUT端子の信号の周波数が変えられる。CLKOUT信号で割り込みを入れるとRTC8564のタイミングで時刻などを表示することができる。

#include <Wire.h>
#include <RTC8564.h>

RTC8564 RTC;

void setup()
{
  RTC.begin();

  /* ====================
   * CLKOUT端子出力周波数
   * --------------------
   * FREQ_32768 : 32768Hz
   * FREQ_1024  : 1024Hz
   * FREQ_32    : 32hz
   * FREQ_1     : 1Hz
   * FREQ_0     : 停止
   * --------------------
   */
  RTC.setClkOut( RTC.FREQ_32768 );
}

void loop()
{
}

タイマ

タイマには二種類あるようである。ひとつは一度だけ割り込みが入るもの、もう一つは繰り返しタイマ割り込みが入るもの。いずれにしても/INT端子の信号を”D2″などarduinoの外部割り込みピンに接続するのが前提である。

一度だけ割り込みが入るものは、以下のようなスケッチになる。

#include <Wire.h>
#include <RTC8564.h>

RTC8564 RTC;
RTC_TIME rtc_time;
bool fWakeUp;
const char* dayofweek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void walkeup()
{
  fWakeUp = true;
}

void setup()
{
  fWakeUp = false;

  Serial.begin(9600);
  RTC.begin();

  // タイマー設定:10分後 繰り返しなし、/INTロー割り込みあり
  RTC.setTimer( RTC.TIMING_1_MIN, 10, false, true );

  // /INT端子をD2に接続する
  attachInterrupt(0, walkeup, FALLING);
}

void loop()
{
  char buf[32];

  if(RTC.now(&rtc_time))
  {
    snprintf(buf,32,"%04u-%02u-%02u(%s) %02u:%02u:%02u\n",
                    rtc_time.year,
                    rtc_time.month,
                    rtc_time.day,
                    dayofweek[rtc_time.wday],
                    rtc_time.hour,
                    rtc_time.min,
                    rtc_time.sec   );

    Serial.print(buf);
  }

  if (fWakeUp)
  {
    fWakeUp = false;
    Serial.println("WakeUp Timer!!");

    // 繰り返しなしなら /INTはローになりっぱなし
    // 場合によってはタイマーを停止させる
    RTC.stopTimer();
  }

  delay(1000);
}

一度だけ割り込みがものは、/INT端子の割り込みは入ると常にロー状態になる。次に使うにはタイマ停止させるかタイマクリアする必要がある。

繰り返しタイマ割り込みは、以下のようなスケッチになる。

#include <Wire.h>
#include <RTC8564.h>

RTC8564 RTC;
RTC_TIME rtc_time;
bool fWakeUp;
const char* dayofweek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void walkeup()
{
  fWakeUp = true;
}

void setup()
{
  fWakeUp = false;

  Serial.begin(9600);
  RTC.begin();

  // タイマー設定:10分後 繰り返しあり、/INTロー割り込みあり
  RTC.setTimer( RTC.TIMING_1_MIN, 10, true, true );

  // /INT端子をD2に接続する
  attachInterrupt(0, walkeup, FALLING);
}

void loop()
{
  char buf[32];

  if(RTC.now(&rtc_time))
  {
    snprintf(buf,32,"%04u-%02u-%02u(%s) %02u:%02u:%02u\n",
                    rtc_time.year,
                    rtc_time.month,
                    rtc_time.day,
                    dayofweek[rtc_time.wday],
                    rtc_time.hour,
                    rtc_time.min,
                    rtc_time.sec   );

    Serial.print(buf);
  }

  if (fWakeUp)
  {
    fWakeUp = false;
    Serial.println("WakeUp Timer!!");
  }

  delay(1000);
}

与えたタイミングで/INT端子がハイからローに繰り返し変化する。これはタイマ停止させない限りは続く。

アラーム

特定の日時に起動する。設定は以下の様にする。注意点は不要なら該当データを0xFFに設定すること。

#include <Wire.h>
#include <RTC8564.h>

RTC8564 RTC;
ALARM_TIME alarm;
RTC_TIME rtc_time;
bool fWakeUp;
const char* dayofweek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void walkeup()
{
  fWakeUp = true;
}

void setup()
{
  fWakeUp = false;

  Serial.begin(9600);
  RTC.begin();

  // アラーム設定:23時15分、/INTロー割り込みあり
  alarm.min = 15;
  alarm.hour = 23;
  alarm.day = 0xFF;                 // 使用しないのなら0xFFに設定
  alarm.wday = 0xFF;                //           〃
  RTC.setAlarm( alarm, true );

  // /INT端子をD2に接続する
  attachInterrupt(0, walkeup, FALLING);
}

void loop()
{
  char buf[32];

  if(RTC.now(&rtc_time))
  {
    snprintf(buf,32,"%04u-%02u-%02u(%s) %02u:%02u:%02u\n",
    rtc_time.year,
    rtc_time.month,
    rtc_time.day,
    dayofweek[rtc_time.wday],
    rtc_time.hour,
    rtc_time.min,
    rtc_time.sec   );

    Serial.print(buf);
  }

  if (fWakeUp)
  {
    fWakeUp = false;
    Serial.println("WakeUp Alarm!!");

    // /INTはローになりっぱなし
    // 次回のアラームのためにアラームをクリア
    RTC.clearAlarm();
  }
  delay(1000);
}

新しいライブラリィ

今回は真面目にデバッグしたのでこれでOKだろう。新しいライブラリィはこれだ。一昨日公開したとこだけど、20件近くのダウンロードがあった。前のバーションをダウンロードされた方は、これをダウンロードしてくれ。

Arduino用RTC8564ライブラリィ"Arduino用RTC8564ライブラリィ"をダウンロード