![]() |
秋月電子のサイトから |
ずっと以前に買ってあったものの使う機会がなくて部品沼に沈んでましたが、在庫リストを見ていたら出てきたので使ってみました。
配線は、SDA - SDA, SCL - SCL, Vcc - Vcc, Gnd - Gndで何のひねりもありません。動作電圧範囲が広いのでmbedでもArduino / ESP8266/ ESP-WROOM-02どれでもそのまま使えます。
欠点としては、バッテリバックアップのラインが別になっていないので、電池やスーパーキャパシタをつなぐときにはSBRダイオードなどで一手間かかってしまいます。
この点、VddとVbatが分かれているDS1307+とかPCF2129は便利なんですよね。
余談ですが、こないだPCF2129で基板を作ったんですが動作しなくて泣いています。その辺の顛末はまたいつかブログに書きます。
■ソース■
こちらの記事を参考にさせていただきました。ありがとうございます。RTCに多いんですが、年月日時分秒すべて60進数のBCDです。通常の10進をそのままセットするとまともな値が返ってこないので、セット前 / 読み出し後に変換してやる必要があります。fromClockFormatはBCD(60進)から10進、toClockFormatは10進からBCDへの変換を行ってます。
time_t(unix時間:1970年1月1日 00:00:00.000からの経過ミリ秒)とグレゴリアン歴との変換は標準関数で済ませてしまいました。テヘペロ。
起動するとWiFiに接続してsntpから時間を取得してRTCにセットし、あとはRTCから読み込んでは時間を表示しているだけです。
このRTCにはアラームをセットして割り込みを掛けたりする機能もあるのですが、使っていません。ESP-WROOM-02でRSTにつないでやると、deep sleepの後に指定した時刻に立ち上がる、なんてこともできると思います。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Both_RX-8025NB by kkurahashi 2016-06-21 | |
// | |
// thanks: | |
// 秋月のリアルタイムクロック(RTC)モジュール | |
// http://s2jp.com/2015/03/rtc-module/ | |
// | |
// | |
#include <Wire.h> | |
#include <Time.h> | |
#include <ESP8266WiFi.h> | |
#include <WiFiClient.h> | |
extern "C" { | |
#include "user_interface.h" | |
#include "sntp.h" | |
} | |
#define LCD_ADRS 0x3E | |
#define RTC_ADRS 0x32 | |
void setupRTC() { | |
Wire.beginTransmission(RTC_ADRS); | |
Wire.write(0xE0); | |
Wire.write(0x20); // 24 hour mode | |
Wire.write(0x00); // PON Clear | |
Wire.endTransmission(); | |
delay(1); | |
} | |
void writeRTC(time_t *inTime) { | |
int yy, mm, dd, HH, MM, SS; | |
setTime(*inTime); | |
Serial.print("year = "); | |
Serial.println(year()); | |
yy = year() % 100; | |
mm = month(); | |
dd = day(); | |
HH = hour(); | |
MM = minute(); | |
SS = second(); | |
Wire.beginTransmission(RTC_ADRS); | |
Wire.write(0x00); | |
Wire.write(toClockFormat(SS)); | |
Wire.write(toClockFormat(MM)); | |
Wire.write(toClockFormat(HH)); | |
Wire.write(0x00); | |
Wire.write(toClockFormat(dd)); | |
Wire.write(toClockFormat(mm)); | |
Wire.write(toClockFormat(yy)); | |
Wire.endTransmission(); | |
} | |
void readRTC(time_t *outTime) { | |
int yyyy, mm, dd, HH, MM, SS; | |
Wire.requestFrom(RTC_ADRS, 8); | |
Wire.read(); | |
SS = fromClockFormat(Wire.read()); | |
MM = fromClockFormat(Wire.read()); | |
HH = fromClockFormat(Wire.read()); | |
Wire.read(); // dummy read | |
dd = fromClockFormat(Wire.read()); | |
mm = fromClockFormat(Wire.read()); | |
yyyy = 2000 + fromClockFormat(Wire.read()); | |
setTime(HH, MM, SS, dd, mm, yyyy); | |
*outTime = now(); | |
} | |
byte fromClockFormat(int inClock) { | |
return ((inClock & 0xf0) >> 4) * 10 + (inClock & 0x0f); | |
} | |
byte toClockFormat(int inValue) { | |
return abs(inValue / 10) * 16 + (inValue % 10); | |
} | |
// | |
// Wifi | |
// | |
#include "../../private_ssid.h" | |
//const char *ssid = "*************"; | |
//const char *password = "*************"; | |
WiFiClient client; | |
void setup() | |
{ | |
Serial.begin(115200); | |
startWifi(); | |
pinMode(13, OUTPUT); | |
Wire.begin(); | |
setupRTC(); | |
time_t tt = getTimestamp(); | |
Serial.print("get sntp = "); | |
Serial.println(tt); | |
writeRTC(&tt); | |
} | |
void loop() | |
{ | |
digitalWrite(13, HIGH); | |
time_t tt; | |
readRTC(&tt); | |
Serial.print(tt); | |
Serial.print(" "); | |
Serial.print(year()); | |
Serial.print("-"); | |
Serial.print(month()); | |
Serial.print("-"); | |
Serial.print(day()); | |
Serial.print(" "); | |
Serial.print(hour()); | |
Serial.print(":"); | |
Serial.print(minute()); | |
Serial.print(":"); | |
Serial.println(second()); | |
digitalWrite(13, LOW); | |
delay(1000); | |
} | |
// | |
// WiFi | |
// | |
bool startWifi() { | |
WiFi.begin ( ssid, password ); | |
Serial.println("Started"); | |
// Wait for connection | |
while ( WiFi.status() != WL_CONNECTED ) { | |
delay ( 500 ); | |
Serial.print ( "." ); | |
} | |
Serial.println("Wifi Connected"); | |
return true; | |
} | |
// | |
// sntp | |
// | |
uint32_t getTimestamp() { | |
configTime(9 * 3600, 0, "ntp.nict.jp", NULL, NULL); | |
uint32_t result = 0; | |
int cnt = 0; | |
while (result == 0) { | |
result = sntp_get_current_timestamp(); | |
delay(100); | |
if (++cnt > 10) { | |
break; | |
} | |
} | |
return result; | |
} |
いい感じで動いているからあと何個か買っておこう。
…秋月にアフィリエイトがないのが残念です(笑)。
エプソンのRTCは使い易いと思います。
返信削除DS1307だと発振子が邪魔だし、そもそもちゃんと発振してくれるのかという疑問が付きまといますから。
あとエプソンは極端に消費電流が少ないのでRTCだけ保持してシステムはスリープするとき有利です。
最近のRX8900SA辺りだとVbat端子がありますし、チップ単価も安いです。
コメントありがとうございます!
返信削除ほんとに使いやすいし消費電力も小さいし、データロガーなどを作るには打って付けですよね。
RX8900SAは存じませんでした(私の部品調達は秋月が中心なので)。今度digikeyに注文してみます。