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(リアルタイムクロック)DS32310x68
EEPROM(不揮発性メモリ)AT24C320x57

1️⃣ DS3231(RTC:リアルタイムクロック)

  • I2C アドレス: 0x68
  • 現在時刻や温度データを管理する IC。
  • 0x68固定アドレス で、変更不可。

2️⃣ AT24C32(EEPROM:不揮発性メモリ)

  • I2C アドレス: 0x57
  • 32Kbit(4KB) のメモリを搭載し、データの保存が可能。
  • 例えば、RTC の設定データやユーザー独自のデータを記録できる。
  • EEPROM のアドレスは 0x500x57 の範囲で設定

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);
}