Arduino ものづくり
基礎編
monodukuri-life.hatenablog.com
記事に広告(アフィリエイト広告)が含まれています。
こんにちは!今回は、電子工作の定番「Arduino」を使って、リアルタイムクロック(RTC)モジュールから現在時刻を取得する方法を共有します。
「サンプル通りにやったのに動かない…」という初心者あるあるな壁にぶつかったので、その解決策も含めて記録に残します。この記事が、誰かのモノづくりのハードルを下げるきっかけになれば嬉しいです。
Arduino本体には時計機能がありません(電源を切るとリセットされてしまいます)。そこで、外部のRTC(リアルタイムクロック)モジュールを使って、正確な時間を刻めるようにします。
Arduino UNO
クロックモジュール RTC
ジャンパー線
このブログでは ELEGOO(エレゴー)製の Arduino 互換品を使って実験しています。Arduino互換品と聞くと品質が心配になる方もいるかもしれませんが、ELEGOO の製品は「互換品とは思えない品質」 で、Arduino公式ボードと同じように問題なく使えます。それでいて 価格はかなりリーズナブル なのが魅力です。
特にスターターキットは、
といった 電子工作で必要なパーツが一式そろっており、初めてでもすぐに実験を始められる 便利なセットになっています。
シリアルモニタに、秒単位で現在時刻が表示されるようにします。


RTCモジュールは、水晶発振子を内蔵した時計専用のICです。 最大の特徴は、バックアップ用のボタン電池を搭載できる点です。これにより、Arduinoの電源を切っても、電池が切れるまで内部で時間を刻み続けてくれます。
接続は非常にシンプルです。RTCは「I2C(アイ・スクエア・シー)」という通信方式を使います。
| RTCピン | Arduinoピン | 役割 |
| VCC | 5V | 電源 |
| GND | GND | グランド |
| SDA | A4 (or SDA) | データ信号 |
| SCL | A5 (or SCL) | クロック信号 |

※配線時の注意点
SDAとSCLの接続先を間違えないようにしましょう。Arduino UNOの場合、SDAはA4、SCLはA5ピンです(専用のSDA/SCLピンがある基板でも、内部的にはA4/A5と繋がっています)。
今回、ELEGOO社製のキットに付属していたサンプルコード(DS3231ライブラリ使用)を試したところ、ライブラリのアップデートの影響か、うまく動作しませんでした。 そこで今回は、より汎用性が高く安定している DS3232RTCライブラリ(JChristensen製) を使用します。
DS3231(NorthernWidget製)かつての定番ですが、最近の環境ではコンパイルエラーや動作不良が報告されることがあります。DS3232RTC(JChristensen製) DS3231とDS3232の両方に対応しており、メンテナンスも継続されています。Timeライブラリとの親和性が高く、コードが書きやすいのが特徴です。
比較表:DS3232RTC vs DS3231(NorthernWidget)
| 比較項目 | DS3232RTC (JChristensen) | DS3231 (NorthernWidget) |
| 主な目的 | Arduinoのシステム時間管理 | チップの機能(ハードウェア)制御 |
| 依存ライブラリ | TimeLib.h (Time) が必須 |
Wire.h (標準) のみでOK |
| 時間の扱い |
Unixタイム(1970年からの秒数) ※計算や比較が非常に得意 |
年・月・日・時・分 がバラバラ ※そのまま表示するのに便利 |
| 温度センサー | △ 取得可能だが、メイン機能ではない | ◎ 非常に簡単 (getTemperature関数あり) |
| アラーム機能 | ○ 強力だが、設定コマンドが専門的 | ◎ 専用の関数が用意されており直感的 |
| 向いている用途 |
・データロガー(記録) ・複雑なタイマー処理 ・時間の計算が必要なとき |
・デジタル時計の表示 ・温湿度計 ・目覚まし時計(アラーム) |
Arduino IDEのライブラリマネージャーで「DS3232RTC」をインストールして使用してください。
/*
DS3232RTC ライブラリを使用したサンプル
特徴:ArduinoのTimeライブラリと同期して動作します
*/
#include // http://github.com/JChristensen/DS3232RTC
#include // http://playground.arduino.cc/Code/Time
#include
DS3232RTC RTC; // RTCクラス
void setup() {
Serial.begin(9600);
Wire.begin(); // ハードウェアI2C初期化
// --- 時刻設定エリア (初回のみ実行し、2回目以降はコメントアウト推奨) ---
// 時, 分, 秒,日,月,年 (例: 2026年1月30日 12時00分00秒)
// setTime(21, 58, 0, 31, 1, 2026);
// RTC.set(now()); // Arduinoのシステム時刻をRTCに書き込む
// -------------------------------------------------------------
// Arduinoのシステム時刻の基準(Sync Provider)としてRTCを指定
// これにより、now()関数を呼ぶだけでRTCの正確な時間が返ってきます
// setSyncProvider(RTC.get);
setSyncProvider([]() {
return RTC.get();
});
if (timeStatus() != timeSet) {
Serial.println("RTCとの同期に失敗しました");
} else {
Serial.println("RTCと同期しました");
}
}
void loop() {
// 日付と時刻を表示する関数を呼び出し
digitalClockDisplay();
delay(1000); // 1秒待機
}
void digitalClockDisplay() {
// TimeLibの機能で簡単に表示できます
Serial.print(year());
Serial.print("/");
printDigits(month());
Serial.print("/");
printDigits(day());
Serial.print(" ");
printDigits(hour());
Serial.print(":");
printDigits(minute());
Serial.print(":");
printDigits(second());
Serial.println();
}
// 数字が1桁の場合に頭に0をつける関数 (例: 1 -> 01)
void printDigits(int digits) {
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
このプログラムの主な目的は、「外部のリアルクロックモジュール(DS3232)から正確な時刻を読み取り、Arduino内部の時計を自動的に補正(同期)しながら、シリアルモニタに日時を表示し続けること」です。
起動時(Setup):
I2C通信を開始し、Arduinoに対して「時刻の基準(親)はDS3232だよ」と教えます。
動作中(Loop):
1秒ごとに現在の日付(年/月/日)と時刻(時:分:秒)をきれいに整形してPCの画面(シリアルモニタ)に送信します。
一度プログラムを書き込めば、RTCにボタン電池が入っている限り、Arduinoの電源を切っても時刻は維持されます。
このコードには、効率的かつスマートに時刻を扱うための重要なテクニックが3つ隠されています。
setSyncProvider による自動同期このコードの最大の肝は setSyncProvider(...) という関数です。
通常、Arduinoの時間は電源を入れると0からスタートしてしまいますが、この関数を使うことで「定期的にRTCへ時間を聞きに行き、Arduino内部の時間を自動で合わせる」という処理を裏側で勝手に行ってくれます。これにより、ユーザーはズレを気にせず now() や hour() を呼ぶだけで正確な時間を取得できます。
setSyncProvider の引数に注目してください。
setSyncProvider([]() {
return RTC.get();
});
ここで []() { ... } という書き方(ラムダ式)が使われています。これは「名前のない関数」をその場で作るテクニックです。「RTCから時間を取得する関数」を直接プロバイダとして渡すことで、コードを簡潔に保っています。
コード内の // 時刻設定エリア がコメントアウト(無効化)されています。これは非常に重要なベストプラクティスです。
初回: コメントを外して時刻を書き込む(RTCに時間をセット)。
2回目: すぐにコメントアウトして再度書き込む。
こうしないと、Arduinoを再起動するたびに、毎回「2026年1月30日...」に時間が巻き戻ってしまうからです。このコードはその運用を見越して書かれています。
それでは、コードをブロックごとに分けて詳しく見ていきましょう。
#include <TimeLib.h> // Arduino内部で時間を扱うための標準ライブラリ
#include <Wire.h> // I2C通信(SCL, SDAピン)を行うライブラリ
DS3232RTC RTC; // RTCを操作するための「RTC」という名前のオブジェクトを作成
ここでは必要な道具箱(ライブラリ)を揃えています。DS3232RTC と TimeLib は相性抜群の組み合わせです。
void setup() {
Serial.begin(9600); // PCとの通信開始
Wire.begin(); // I2C通信の開始(これがないとRTCと話せません)
// --- 時刻設定エリア ---
// setTime(21, 58, 0, 31, 1, 2026);
// RTC.set(now());
// --------------------
// ★ここが最重要ポイント
// Arduinoの時刻合わせ係としてRTCを指定します
setSyncProvider([]() {
return RTC.get();
});
// 同期がうまくいったか確認
if (timeStatus() != timeSet) {
Serial.println("RTCとの同期に失敗しました");
} else {
Serial.println("RTCと同期しました");
}
}
setSyncProvider によって、Arduinoは「あ、自分は時計を持っていないから、定期的に RTC.get() を実行して時間を合わせればいいんだな」と理解します。
void loop() {
digitalClockDisplay(); // 下で作った表示用の関数を呼び出す
delay(1000); // 1秒待つ
}
loop の中は非常にシンプルです。表示処理を別の関数(digitalClockDisplay)に分けたことで、メインの処理が見やすくなっています。
void digitalClockDisplay() {
Serial.print(year());
Serial.print("/");
printDigits(month());
// ... (省略) ...
printDigits(second());
Serial.println(); // 改行
}
void printDigits(int digits) {
if (digits < 10)
Serial.print('0'); // 1桁なら頭に0をつける
Serial.print(digits);
}
printDigits 関数は、例えば「9時5分」を「09:05」と表示するための工夫です。これがあるだけで、ログデータの見やすさが格段に上がります。
コード内で使われている専門的な関数を、分かりやすく翻訳しました。
| 関数名 | 役割 | 引数と戻り値 |
| RTC.get() | RTCモジュールから現在のハードウェア時刻を読み取ります。 | 戻り値: time_t 型(1970年1月1日からの経過秒数)。 |
| setSyncProvider(関数) | TimeLibに対し「時間の基準となる関数」を登録します。 |
引数: 時間を返す関数。 効果: これ以降、定期的にその関数が呼ばれ、システム時刻が補正されます。 |
| now() | 現在のシステム時刻を取得します。 | 戻り値: time_t 型。同期設定済みなら、実質的にRTCの正確な時間が返ります。 |
| timeStatus() | 現在の時刻同期の状態を確認します。 | 戻り値: timeSet(同期完了)、timeNeedsSync(要同期)、timeNotSet(未設定)のいずれか。 |
| year(), month(), day()... | time_t 型の時間データから、「年」「月」「日」などの要素を取り出します。 |
引数: なし(自動で now() の結果を使います)。 |
一度プログラムで時刻を書き込むと、RTC内の電池のおかげで、時刻設定用のコード(setup内のコメント部分)を削除してプログラムを再書き込みしても、正しい時刻を保持して出力されることが確認できました。
ArduinoのUSBケーブルを抜いて放置し、数分後に再度繋いでも「今の時間」から再開されるのは、独立した時計を持っている安心感がありますね。

今回はRTCモジュールの基本について解説しました。 「付属のサンプルが動かない」というのは電子工作ではよくあることですが、別のライブラリを探すことで解決できる場合が多いです。
今後の応用案:
特定の時間になったらアラームを鳴らす「目覚まし時計」
植物への「自動水やり機」のスケジュール管理
SDカードと組み合わせて、時間付きの「温度ログ記録(データロガー)」
皆さんもぜひ、時間に連動したガジェット作りに挑戦してみてください!