Arduinoで時刻を取得するためには、RTCモジュールが必要。今回は以下のモジュールを動作させる。
このチップにはアラーム機能が備わっているので、そのチェックも行う。
Arduinoへの配線とライブラリ
今回の配線はI2Sのみなので書くまでも無いが、一応表だけでも。
Arduino | DS3231 |
---|---|
A4 | SDA |
A5 | SCL |
ライブラリは以下の物を利用させて頂く。
サンプルスケッチ
上記ライブラリに付属のサンプルスケッチを以下に再掲する。
このチップにはアラーム機能が付いていて、そのテストを行うプログラムになっている。
rtc_ds3231_alarm_every_5m.ino
// during an alarm the INT pin of the RTC is pulled low
//
// this is handy for minimizing power consumption for sensor-like devices,
// since they can be started up by this pin on given time intervals.
#include <Wire.h>
#include "ds3231.h"
#define BUFF_MAX 256
uint8_t sleep_period = 1; // the sleep interval in minutes between 2 consecutive alarms
// how often to refresh the info on stdout (ms)
unsigned long prev = 5000, interval = 5000;
void set_next_alarm(void)
{
struct ts t;
unsigned char wakeup_min;
DS3231_get(&t);
// calculate the minute when the next alarm will be triggered
wakeup_min = (t.min / sleep_period + 1) * sleep_period;
if (wakeup_min > 59) {
wakeup_min -= 60;
}
// flags define what calendar component to be checked against the current time in order
// to trigger the alarm
// A2M2 (minutes) (0 to enable, 1 to disable)
// A2M3 (hour) (0 to enable, 1 to disable)
// A2M4 (day) (0 to enable, 1 to disable)
// DY/DT (dayofweek == 1/dayofmonth == 0)
uint8_t flags[4] = { 0, 1, 1, 1 };
// set Alarm2. only the minute is set since we ignore the hour and day component
DS3231_set_a2(wakeup_min, 0, 0, flags);
// activate Alarm2
DS3231_set_creg(DS3231_CONTROL_INTCN | DS3231_CONTROL_A2IE);
}
void setup()
{
Serial.begin(115200);
Wire.begin();
DS3231_init(DS3231_CONTROL_INTCN);
DS3231_clear_a2f();
set_next_alarm();
}
void loop()
{
char buff[BUFF_MAX];
unsigned long now = millis();
struct ts t;
// once a while show what is going on
if ((now - prev > interval) && (Serial.available() <= 0)) {
DS3231_get(&t);
// display current time
snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
t.mon, t.mday, t.hour, t.min, t.sec);
Serial.println(buff);
// display a2 debug info
DS3231_get_a2(&buff[0], 59);
Serial.println(buff);
if (DS3231_triggered_a2()) {
Serial.println(" -> alarm2 has been triggered");
set_next_alarm();
// clear a2 alarm flag and let INT go into hi-z
DS3231_clear_a2f();
}
prev = now;
}
}
上記を実行した時のシリアルポート出力は以下。5秒おきにRTCチップのステータスレジスタを読みに行って、アラームがトリガーしたかをチェックしている。
1900.01.01 01:21:51
m00 h00 d22 fm1 h0 d0 wm0 128 0 28
1900.01.01 01:21:56
m00 h00 d22 fm1 h0 d0 wm0 128 0 28
1900.01.01 01:22:01
m02 h00 d22 fm1 h0 d0 wm0 130 0 28
-> alarm2 has been triggered
1900.01.01 01:22:06
m00 h00 d22 fm1 h0 d0 wm0 128 0 28
ロジアナでアラームのピン出力をチェック
今回使用したボードにはI2Cの他にアラームのトリガー出力とクロック出力が出ているので、それらをロジアナに接続して確認してみた。(ボードのシルク印刷はSQWとなっているが、チップの信号名としてはINTが正しい)
ロジアナに接続してSQW(INT)にトリガを設定してサンプルプログラムを動かしながら測定した結果が以下。I2CとタイミングがズレているせいかI2Cには何も出てないが、シリアルポートに”triggered”のメッセージが出力されると確かにロジアナもトリガーが掛かって停止する。32kHzのピンからは何も出ていない。
サンプリング周波数を落として長時間測定を行った結果は以下。I2Cはサンプリング周波数が低すぎて正しく記録出来ていないが、INTピンの立ち下がりパルスが綺麗に記録出来るようになった。
32kHzを出力させる
ライブラリにDS3231_set_32kHz_output()という関数が用意されている。
DS3231_set_32kHz_output(1);
上記の一行をsetup()に追加したらあっさり32kHzが出力されるようになった。
コメント