リアルタイムクロックの無いArduinoやRaspberryPiへクロック機能を追加するためにリアルタイムクロックモジュールをよく用います。
この辺が有名どころですが
https://www.switch-science.com/catalog/3038/
このモジュールはマキシムのDS1307を使ったものでチップだけも秋月電子からも入手可能です。DS1307は安価で良いのですが、水晶と負荷キャパシタをつける必要がありまして、クロック精度が水晶とキャパシタに依存するのであんまり精確ではありません。電源も5V。普通水晶の誤差が20ppm で加えてキャパシタの誤差等ありますので、実際に使った所では日に2秒くらいずれるのは普通でもう少し精確なクロックは欲しいところです。
高精度のRTCモジュールでは他に同じくマキシムのDS3231チップを使ったものがあります。
https://www.switch-science.com/catalog/3036/
DS3231 は精度が2ppm - 3.5 ppmと高精度です。でも少し高価。
水晶、温度補償内蔵で使いやすいので以前はRTCモジュールというとこればかりだった様ですが最近はメジャーでなくなってしまって、チップ単体も国内でも手に入らなくなってしまった様です。チップはMouserから入手可能ですが、一個1000円くらいしてやたら高いです。何ででしょ。。。
ところがAmazonにこのモジュールと同等のモジュールがやたら安価に出ています。調べてみるとAliEspressからはチップ単体がこれまた安価に入手可能でした。まあまさかニセモノではないだろうと思うのでとりあえずオーダーしました 20個で14ドルくらいでした。2週間くらいかかりましたが届きました。
厄介なのはチップが幅広のSOPで、変換基板にちょうど良いものが見つからない。。。
しばらくほったらかしにしておいたのですが、
後で気がついた、
秋月のArduinoユニバーサル基板に1.27mm表面実装パターンがあるので、それがそのまま使える。
http://akizukidenshi.com/catalog/g/gP-07555/
というわけでRTCシールドを作ってみました。回路図はデータシートのサンプルの通り、プルアップ抵抗とキャパシタ、バックアップ用バッテリー だけです。
抵抗はウラに
テストスケッチは以下になります
あらかじめRTCLibをインストールしてください。RTCクラスは RTC_DS1317を指定していますがRTCLibのバージョンによってはRTC_DS3231 でも結構です。
起動すると一秒おきにRTCの時刻をシリアルコンソールへ出力します。
シリアルコンソールへ入力された文字列を 2018/02/01 12:00:00 のフォーマットで読み込みRTCへセットします。文字列はエラー確認していませんのでデタラメを入れるとデタラメの時刻になりますのでご注意下さい。
==================================
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
char instr[256];
unsigned char chpt=0;
boolean linein = false;
void setup () {
Serial.begin(9600);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
//RTC.adjust(DateTime(__DATE__, __TIME__));
}
// RTC.adjust(DateTime(year, month, day, hour, minute, seconds))
// RTC.adjust(DateTime(2018, 2, 14, 12, 34, 0));
}
void loop () {
DateTime now = RTC.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
if(linein){
setrtc();
Serial.print(instr);
chpt=0;
linein=false;
}
delay(1000);
}
void setrtc(void)
{
int yr,mo,dy,hr,mi,sc;
sscanf(instr,"%4d/%02d/%02d %02d:%02d:%02d",&yr,&mo,&dy,&hr,&mi,&sc);
Serial.print(yr,DEC);
Serial.print(mo,DEC);
Serial.print(dy,DEC);
Serial.print(hr,DEC);
Serial.print(mi,DEC);
Serial.println(sc,DEC);
RTC.adjust(DateTime(yr,mo,dy,hr,mi,sc));
}
void serialEvent() {
char c;
while (Serial.available()) {
c = Serial.read();
instr[chpt++]=c;
if (c == '\n') {
linein = true;
}
}
}
==================================
時刻を設定した後3日ほど放置してズレがどれくらいになるか調べてみました。
普通2,3秒のずれが発生すると思いますが誤差は一秒未満の様で、精度は十分良くなったと思います。