RaspberryPi & ESP32 [38] I2C接続のDS3231 RTCモジュール
I2C接続のRTCモジュールです。アマゾンで4つで1485円で買いました。

I2Cなので、液晶ディスプレイと同じピンから接続できます。アドレスを確認してみると、0x68でした。これが表示されないなら、I2Cが有効になっているか確認してください。
pi@w2-x4-44:~/work/PPW $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
+5V 3.3Vの両方に対応しています。
DS3231を認識させるために、/boot/config.txt に dtoverlay=i2c-rtc,ds3231 と追記してリブートします。なんか、いろいろやるのかなと思いましたが、それだけです。一度、インターネットに接続してRTCに現時刻を記録させればインターネット接続が途切れても時刻を刻みます。
5番 + ーー>Vcc
4番 D -->SDA
3番 C -->SDC
2番 NC
1番 ー -->GND
DS3231のチップにはSQW(Square Wave)がありますが、このモジュールはそれが配線されておらず、NCになっています。
同じアマゾンで、VKLSVAN 2個 DS3231 AT24C32 RTCモジュールというのがありますが、これはSQWと32Kの出力があります。

これをI2Cチェッカにかけると、二つのアドレスが見えす。これは、EEPROMが搭載されているモジュールでそのアドレスが見えるようです。
デバイス | チップ | I2C アドレス |
---|---|---|
RTC(リアルタイムクロック) | DS3231 | 0x68 |
EEPROM(不揮発性メモリ) | AT24C32 | 0x57 |
1️⃣ DS3231(RTC:リアルタイムクロック)
- I2C アドレス:
0x68
- 現在時刻や温度データを管理する IC。
0x68
は 固定アドレス で、変更不可。
2️⃣ AT24C32(EEPROM:不揮発性メモリ)
- I2C アドレス:
0x57
- 32Kbit(4KB) のメモリを搭載し、データの保存が可能。
- 例えば、RTC の設定データやユーザー独自のデータを記録できる。
- EEPROM のアドレスは
0x50
~0x57
の範囲で設定
ESP32でのアドレスチェックのスケッチとSQWが生きているかを調べるスケッチを上げておきます。
#include <Wire.h>
#define SDA_PIN 23 // 使用する SDA ピン(変更可能)
#define SCL_PIN 19 // 使用する SCL ピン(変更可能)
void setup() {
Serial.begin(115200);
Serial.println("\nI2C Scanner");
// I2C 通信を開始(カスタム SDA/SCL の場合は Wire.begin(SDA, SCL);)
Wire.begin(SDA_PIN, SCL_PIN);
Serial.println("Scanning for I2C devices...");
}
void loop() {
byte error, address;
int nDevices = 0;
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
Serial.print(address, HEX); // 16進数で表示
Serial.println(" !");
nDevices++;
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
Serial.println(address, HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
} else {
Serial.println("Scan complete\n");
}
delay(5000); // 5秒ごとにスキャンを繰り返す
}
#include <Wire.h>
#include "RTClib.h"
#include <Wire.h>
#define DS3231_ADDRESS 0x68 // DS3231のI2Cアドレス
#define SDA_PIN 23 // I2C SDA
#define SCL_PIN 19 // I2C SCL
#define SQW_PIN 18 // SQW ピンを接続する GPIO(変更可能
volatile unsigned long lastTime = 0;
volatile unsigned long pulseInterval = 0;
// 割り込み関数:SQWの立ち下がりを検出
void IRAM_ATTR sqwInterrupt() {
unsigned long currentTime = micros();
pulseInterval = currentTime - lastTime;
lastTime = currentTime;
}
// DS3231のSQW出力を1Hzに設定
void setSQWFrequency(uint8_t mode) {
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write(0x0E); // 制御レジスタのアドレス
Wire.write(mode); // 設定値
Wire.endTransmission();
}
void setup() {
Serial.begin(115200);
Wire.begin(SDA_PIN, SCL_PIN); // I2C通信開始
pinMode(SQW_PIN, INPUT_PULLUP); // SQWピンを入力モードに設定
attachInterrupt(digitalPinToInterrupt(SQW_PIN), sqwInterrupt, FALLING); // 割り込み設定
// 1Hzの出力に設定
setSQWFrequency(0x00);
}
void loop() {
if (pulseInterval > 0) {
Serial.print("Pulse Interval: ");
Serial.print(pulseInterval);
Serial.println(" us");
float frequency = 1000000.0 / pulseInterval; // 周波数 (Hz)
Serial.print("Frequency: ");
Serial.print(frequency);
Serial.println(" Hz");
pulseInterval = 0; // 測定値をリセット
}
delay(500);
}