戻る

Raspberry Pi Pico I2Cで仮想DS1307 RTCを読み取る

はじめに

プロジェクトにリアルタイムクロック(RTC)を追加したいけれど、手元にハードウェアがないと思ったことはありませんか?Velxioを使えば、Raspberry Pi Picoと仮想DS1307を使用して、完全なI2C RTC読み出しをブラウザ上でシミュレートできます。このチュートリアルでは、回路、コード、主要な概念を順を追って説明し、自身のプロジェクトでI2C通信を自信を持って使用できるようにします。

回路の解説

まずは回路を見てみましょう。Velxioでサンプルを開くと、以下のコンポーネントが表示されます。

Velxioシミュレータキャンバス上のpico-i2c-rtc-readの回路図

回路はシンプルです。Raspberry Pi Pico(nano-rp2040)が2つのLEDと仮想DS1307 RTC(個別のコンポーネントとしては表示されません—RTCはシミュレーションに組み込まれています)に接続されています。LEDはI2Cアクティビティの視覚的なインジケータとして使用されます。

両方のLEDは同じグラウンド(GND.1)を共有しています。I2CバスはSDA(データ)ラインとSCL(クロック)ラインで構成されています。DS1307 RTCは内部でアドレス0x68のこれらのラインに接続されています。LEDはI2C通信に厳密には必要ありませんが、ラインがトグルしていることを視覚的に示します。

この回路を自分で構築するには、Velxioのコンポーネントピッカーを使用できます。

カテゴリ別に部品を参照するVelxioコンポーネントピッカーモーダル

「Raspberry Pi Pico」と「LED」を検索し、説明の通りに配線します。キャンバスツールバーは、コンポーネントのズームや配置に役立ちます。

シミュレーションビューポート上のVelxioキャンバスツールバー

コードの解説

それではコードを見ていきましょう。スケッチはWireライブラリ(組み込み)を使用して、I2C経由でDS1307と通信します。以下が完全なコードです。

// Raspberry Pi Pico — I2C DS1307 RTC Read
// Reads time from virtual RTC at address 0x68

#include <Wire.h>

byte bcdToDec(byte val) {
  return ((val >> 4) * 10) + (val & 0x0F);
}

void setup() {
  Serial.begin(115200);
  delay(500);
  Wire.begin();
  Serial.println("=== Pico I2C RTC Read ===");
  Serial.println("Reading DS1307 at 0x68 (system time)");
  Serial.println();
}

void loop() {
  // Set register pointer to 0
  Wire.beginTransmission(0x68);
  Wire.write(0x00);
  Wire.endTransmission();

  // Read 7 bytes: sec, min, hr, dow, date, month, year
  Wire.requestFrom(0x68, 7);
  if (Wire.available() >= 7) {
    byte sec   = bcdToDec(Wire.read() & 0x7F);
    byte min   = bcdToDec(Wire.read());
    byte hr    = bcdToDec(Wire.read() & 0x3F);
    byte dow   = bcdToDec(Wire.read());
    byte date  = bcdToDec(Wire.read());
    byte month = bcdToDec(Wire.read());
    byte year  = bcdToDec(Wire.read());

    const char* days[] = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

    Serial.print("Time: ");
    if (hr < 10) Serial.print('0'); Serial.print(hr); Serial.print(':');
    if (min < 10) Serial.print('0'); Serial.print(min); Serial.print(':');
    if (sec < 10) Serial.print('0'); Serial.print(sec);
    Serial.print("  Date: ");
    Serial.print(days[dow]); Serial.print(' ');
    if (date < 10) Serial.print('0'); Serial.print(date); Serial.print('/');
    if (month < 10) Serial.print('0'); Serial.print(month); Serial.print('/');
    Serial.print("20"); if (year < 10) Serial.print('0'); Serial.println(year);
  } else {
    Serial.println("RTC not responding!");
  }

  delay(1000);
}

動作の仕組み

  1. セットアップ115200ボーでシリアル通信を開始し、Wire.begin()でI2Cバスを初期化します。DS1307はアドレス0x68にあります。

  2. ループ:1秒ごとに、以下の処理を行います。

    • アドレス0x68beginTransmissionを送信し、0x00(秒レジスタへのレジスタポインタ)を書き込み、endTransmissionを実行します。
    • Wire.requestFrom(0x68, 7)を使用してRTCから7バイトを要求します。
    • 各バイトを読み取り、ヘルパー関数bcdToDecを使用してBCD(2進化10進数)から10進数に変換します。
    • 時刻と日付をフォーマットしてシリアルモニタに出力します。
  3. BCD変換:DS1307は時刻値をBCD形式で保存します。例えば、バイト0x45はBCDで45を表します(4*10 + 5 = 45)。bcdToDec関数は10の位(上位ニブル)と1の位(下位ニブル)を抽出して結合します。

  4. マスキング:特定のレジスタにマスクを適用します。

    • 秒:& 0x7FでCH(クロック停止)ビットをクリアします。
    • 時:& 0x3Fで12/24時間モードビットをクリアします(24時間モードを想定)。

主要な概念

よくある落とし穴とデバッグのヒント

推奨される拡張機能

実際に試してみよう!

実験の準備はできましたか?Velxioでライブサンプルを開き、シミュレーションを実行してください。シリアルモニタに毎秒時刻が表示されます。コードを変更して更新間隔を変更したり、新しい機能を追加したりできます。

Pico I2C RTC Readサンプルを起動する

楽しいシミュレーションを!


共有:
David Montero

執筆者

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

関連記事


前の記事
Pico I2C EEPROM 読み書き:ブラウザで不揮発性メモリをシミュレート
次の記事
Pico I2C スキャナー:バス上のデバイスを検出する