はじめに
Arduinoプロジェクトにリアルタイムクロックを追加したいけれど、ハードウェアが手元にないと思ったことはありませんか?Velxioを使えば、ブラウザ上でI2C RTC(DS1307)をシミュレートできます。このチュートリアルでは、仮想のDS1307から現在の日時を取得し、シリアルモニタに表示するシンプルなI2Cリーダーを構築します。外部ライブラリは不要で、内蔵のWireライブラリのみを使用します。

回路の解説
この例は非常にシンプルです。DS1307は仮想のArduino Unoボードに既に統合されているため、外部コンポーネントや配線を追加する必要はありません。I2Cバス(SDAはA4、SCLはA5)は、アドレス0x68のDS1307に内部接続されています。唯一のコンポーネントはArduino Uno自体です。

まず、Velxioエディタを開き、コンポーネントピッカーからArduino Unoを選択します。DS1307はシミュレーション環境に組み込まれているため、別途追加する必要はありません。回路はすぐに使用できます。
コードの解説
コードをステップごとに詳しく見ていきましょう。
インクルードと定義
#include <Wire.h>
#define DS1307_ADDR 0x68
I2C通信用にWireライブラリをインクルードし、DS1307のI2Cアドレスを0x68と定義します。
BCDから10進数への変換
byte bcdToDec(byte val) {
return ((val >> 4) * 10) + (val & 0x0F);
}
DS1307は時刻値をBCD(2進化10進数)形式で保存します。このヘルパー関数はBCDバイトを通常の10進数に変換します。
セットアップ
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("===========================");
Serial.println(" DS1307 RTC Reader (I2C)");
Serial.println("===========================");
Serial.println();
}
I2Cバスとシリアル通信を9600ボーで初期化し、ヘッダーを表示します。
ループ
void loop() {
// Set register pointer to 0 (seconds)
Wire.beginTransmission(DS1307_ADDR);
Wire.write(0x00);
Wire.endTransmission();
// Request 7 bytes: sec, min, hr, dow, date, month, year
Wire.requestFrom(DS1307_ADDR, 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());
// Print formatted time
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: ");
if (date < 10) Serial.print("0");
Serial.print(date);
Serial.print("/");
if (month < 10) Serial.print("0");
Serial.print(month);
Serial.print("/20");
if (year < 10) Serial.print("0");
Serial.println(year);
} else {
Serial.println("Error: Could not read RTC");
}
delay(1000);
}
ループでは、まず1バイトの0x00を送信してDS1307のレジスタポインタを0(秒レジスタ)に設定します。次に、RTCから7バイトを要求します。DS1307は秒、分、時、曜日、日、月、年をBCDで返します。秒の最上位ビット(ビット7はクロック停止フラグ)と時の上位2ビット(ビット6-7はモード/AM-PM)をマスクします。変換後、先頭ゼロを付けて時刻と日付を表示します。7バイト未満しか利用できない場合はエラーを表示します。最後に1秒待機します。
主要な概念
- I2C通信: WireライブラリがI2Cプロトコルを処理します。
beginTransmission()で書き込みを開始し、write()でデータをキューに入れ、endTransmission()で送信します。requestFrom()でスレーブからバイトを読み取ります。 - BCD形式: DS1307は時刻をBCDで保存し、各ニブルが10進数の1桁を表します。
bcdToDec()関数で変換します。 - レジスタアドレッシング: DS1307の内部レジスタには、最初にレジスタアドレスを書き込み、その後データを読み書きすることでアクセスします。
- ビットマスキング: 秒レジスタの最上位ビット(CH)はクロック停止を示すため、
& 0x7Fでマスクします。時レジスタの上位ビットは12/24時間モードを示すため、& 0x3Fでマスクします。
よくある落とし穴とデバッグのヒント
- I2Cアドレスの誤り: アドレスが0x68(7ビット)であることを確認してください。8ビットアドレスを使用する場合は、1ビット左シフトします。
- プルアップ抵抗の欠如: 実際のハードウェアではI2Cラインにプルアップ抵抗が必要です。Velxioでは内部でシミュレートされています。
- シリアルモニタが表示されない: ボーレートが一致していることを確認してください(9600)。エディタツールバーのシリアルモニタアイコンをクリックします。

- コンパイルエラー:
Wire.hがインクルードされていることを確認してください。このコードは外部ライブラリを使用していません。 - RTCが応答しない: 「Error: Could not read RTC」と表示される場合、I2C通信が失敗している可能性があります。アドレスと配線を確認してください。
推奨拡張機能
- 時刻設定: シリアル入力からDS1307の時刻を設定するコードを追加します。
- LCD表示: I2C LCDを使用して時刻を表示します。
- アラーム機能: DS1307のアラームレジスタを使用してアラームを実装します。
- データロギング: タイムスタンプをEEPROMやSDカードに記録します。
実際に試してみよう
実際の動作を確認してみませんか?Velxioでライブサンプルを開き、Runボタンを押してください。シリアルモニタで毎秒更新される時刻が表示されます。

それでは、シミュレーションをお楽しみください!