前回、I2C通信を使いArduinoに接続したLCDディスプレイに文字を表示させてみました。
シリアル通信となるI2C通信では、SCL(シリアルクロック)・SDA(シリアルデータ)の2本の信号線のみの接続(電源としてVcc・GNDも必要です)でデータのやり取りができLCDディスプレイに文字を表示させることができました。
パラレル通信方式と比べ少ない配線での接続が実現でき、さらに他のI2C対応デバイスの接続を増やしていくのも容易にできます。
I2C通信では各デバイスに割り振られたI2Cアドレスによりマスタ側(Arduino)に繋いだデバイス(スレーブ)を識別しているので、1つまたは複数のI2C対応デバイスを2つの信号線のみの接続で制御することが出来ます。
前回、1602 LCDモジュールを繋ぎI2C通信により文字を表示させてみました。
そしてArduinoは時刻機能を持たないので今回はさらにI2C対応デバイスとしてRTC(リアルタイムクロック)モジュールを繋げLCDディスプレイに時刻を表示させシンプルな時計として機能させてみたいと思います。
I2C通信の復習的な内容となります。
目次
【I2C】RTC(リアルタイムクロック)モジュールDS3231を使い時刻情報を取得する!
今回の目的
I2C(アイ・スクエアド・シー)通信は、SCL(シリアルクロック)とSDA(シリアルデータ)の2本の信号線を使いデータのやり取りを行う通信方式となります。
実際には電源も必要なので、Vcc・GND・SCL・SDAの計4本をArduinoと接続しやり取りが行われます。
パラレル通信と比べ接続する配線の数が少なく、そしてI2C対応デバイスにはI2Cアドレスが個別に割り振られていてこれをもとに制御するため複数のI2C対応デバイスを接続し同時に制御することも出来ます。
マスタ側とスレーブ側を分け、マスタ側が全ての制御を行う構造となっています。
ここでマスタ側とは全てを制御するArduinoとなり、スレーブ側にはI2Cに対応した各デバイス(LCDモジュールやセンサー、ドライバーなど)を接続しこれを制御するものとなります。
マスタ側が常に制御を行い(権限を持っている)、マスタが送信するクロック信号(SCL)を基準にデータ信号がSDAライン上でやり取りされるというものです。
ここまでは前回の復習となり、1602 LCDモジュールを接続し文字を表示させてみました。
そして今回は、さらにI2C対応デバイスを追加し複数のI2Cデバイスを同時に制御してみたいと思います。
RTC(リアルタイムクロック)モジュールDS3231を使い時刻情報を取得し、LCDディスプレイに時間を表示させシンプルな時計として機能させてみるのを今回の目標としたいと思います。
RTC(リアルタイムクロック)とは?
Arduinoは時刻情報を取得するための機能を持っていないため、時計など時刻を刻むものを作りたい場合にはRTC(リアルタイムクロック)モジュールが必要となります。
RTC(リアルタイムクロック)はそのような時計機能(時刻情報)を取得できる回路を実装したモジュールとなります。
Arduinoなどマイコンボードとは独立して動作しボタン電池などのバッテリーバックアップ機能があり電源を切っても時刻情報を保持することができ、いつでもリアルタイムの時刻情報を取得できるというものとなります。
RTCからの時刻情報をArduinoで読み取り時計やタイマーなどに利用することが出来ます。
RTCモジュールにはいろいろとあるようですが、今回RTC DS3231というRTCモジュールを使ってみたいと思います。
Arduinoやラズパイなどのマイコンボードでよく使われるRTCモジュールとなります。
RTC DS3231 リアルタイムクロック
こちらがRTC DS3231リアルタイムクロックモジュールとなります。
I2C接続に対応したRTCとなります。
Arduinoの電源オフ時も内蔵ボタン電池で時刻情報を保持でき、いつでも時刻を読み取る事ができます。
接続端子をみるとGND・Vcc・SDA・SCL・SQW・32Kがあります。
時計機能以外にも方形波信号出力や指定日時に割り込めるアラーム機能、温度センサーや4KバイトのEEPROMなども実装されています。
今回使うのはVcc・GND・SCL・SDAの4本となりI2Cでの接続で使います。
前回ご紹介したI2CScannerを使いI2Cアドレスを確認してみます。
I2C Scanner
Scanning…
I2C device found at address 0x57 !
I2C device found at address 0x68 !
done
I2Cアドレスとして0x68と0x57が表示されました。
0x57はEEPROM(AT24C32)のアドレスとなるので0x68の方がRTCのI2Cアドレスとなります。
- I2Cに対応
- I2Cアドレス(DS3231 : 0x68 / EEPROM : 0x50~0x57)
- 温度センサー内蔵
- 4KバイトのEEPROM(AT24C32)搭載
- 時刻保持用電池(ボタン電池)の充電回路が付いている
上記がRTC DS3231モジュールの特徴となりますが、注意が必要な箇所があります。
本記事を書くにあたりRTC DS3231モジュールに関して少し調べたのですが、時刻保持用電池への充電回路が内蔵されているようです。
これまで意識することなく使ってきて特に問題はなかったのですが・・・
このモジュールには時刻保持用にCR2032ボタン電池を搭載することができます。
そしてモジュール内にはこの電池を充電するための回路が付けられているようです。
充電できる二次電池LIR2032を使う場合は問題ありませんが、充電出来ない一次電池CR2032を使う場合は注意が必要なようです。
長時間の使用では電池の膨らみや故障の原因になるようです。
充電できない一次電池CR2032電池を使用する際は、充電回路と繋がった抵抗かダイオードを取り外すのが望ましくなるようです。
内部回路はこのようにバッテリー(CR2032電池)と繋がっているようです。
RTC DS3231モジュールは多種販売されているようなので使用の際は一度チェックしてみるのがいいかと思います。
電池を外しモジュールを起動(Vcc/GNDに供給)した状態でテスターで計測した際に5Vが来ていれば充電回路が入っている事が分かります。
ダイオード or 抵抗を外して同様に計測してみるとほぼ0Vとなりました。
このように一次電池CR2032を使われる際は抵抗 or ダイオードを外してしまった方がいいかと思います。
充電できる二次電池LIR2032を使用される場合は問題ありません。
もともと二次電池を使用する事を想定して作られたモジュールのようですね。
電池が付属していないものの販売が多いのはそのような理由からだと思われます。
RTC DS3231の接続
それではRTC DS3231モジュールをArduinoと接続し時刻情報を取得してみます。
このモジュールはI2C対応デバイスなのでArduinoとの接続は簡単です。
Arduino(こちらではArduino Unoで説明していきます)のSCL・SDAピンは下記の位置となります。
アナログ入力ピンA4・A5はSDA・SCLとしても使えます。
そして電源Vcc・GNDは今回Arduino側から直接取りました。
DS3231 | Arduino |
SCL | SCL(またはA5ピン) |
SDA | SDA(またはA4ピン) |
Vcc | Vcc |
GND | GND |
I2C機器の接続は簡単ですね!
時刻情報の書き込み
まずはRTC DS3231モジュールに現在の時刻を書き込みます。
RTCモジュールで使える「DS3232RTC」というライブラリを使います。
こちらからダウンロード(ZIP形式)し、ライブラリをインストールします。
参考 DS3232RTCGithub時刻書き込み用のスケッチはこのようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // Arduino入門編⑲ RTCモジュールに時刻情報を書き込む // https://burariweb.info #include <DS3232RTC.h> void setup(){ ///// 時刻の設定 ///// setTime(18, 3, 23, 18, 5, 2021); // 時,分,秒,日,月,年の順となっています RTC.set(now()); // 時刻情報を書き込む setSyncProvider(RTC.get); // RTCから時刻を取得する関数 } void loop(){ } |
時刻情報を書き込むと以後モジュールに付けた電池により保持されるので、上記スケッチは時刻変更の時にのみ使うスケッチとなります。
setTime()内の数字を変え現在時刻に合わせて下さい!
110 111 | setTime(18, 3, 23, 18, 5, 2021); // 時,分,秒,日,月,年の順となっています RTC.set(now()); // 時刻情報を書き込む |
シリアルモニタに時刻を表示させてみる
これでRTC DS3231モジュール内に現在時刻が書き込まれました。
電源を切っても内蔵ボタン電池により時刻情報は保持されています。
次にArduinoからRTC DS3231の時刻情報を読み取って表示させてみたいと思います。
まずはシリアルモニタに表示させてみます。
スケッチ内に先程の時刻を書き込むプログラムを書いていますがコメントアウト(//)させています。
時刻修正の際はこのコメントアウトを外し時刻を設定する形で使って下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | // Arduino入門編⑲ 時刻情報を読み取りシリアルモニタに表示 // https://burariweb.info #include <DS3232RTC.h> // ライブラリのインクルード const char *weekStr[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; void setup(){ ///// 時刻の設定 ///// // 時刻設定時のみ以下2行のコメントアウト(//)を外して下さい。 // setTime(12, 26, 30, 16, 5, 2021); // 時,分,秒,日,月,年の順で設定 // RTC.set(now()); // RTCモジュールに時刻情報を書き込む Serial.begin(115200); // シリアル通信の開始 setSyncProvider(RTC.get); // RTCから時刻情報を取得する関数 } void loop(){ // year(),monty(),day(),hour(),minute(),second()でそれぞれを読み取る Serial.print(year()); Serial.print("年"); Serial.print(month()); Serial.print("月"); Serial.print(day()); Serial.print("日 "); Serial.print(weekStr[weekday()-1]); Serial.print(" "); Serial.print(hour()); Serial.print("時"); Serial.print(minute()); Serial.print("分"); Serial.print(second()); Serial.println("秒"); delay(1000); // 1秒間隔で表示させる } |
シリアルモニタにはこのように表示されていると思います。
2021年5月18日 Tue 18時18分56秒
2021年5月18日 Tue 18時18分57秒
2021年5月18日 Tue 18時18分58秒
2021年5月18日 Tue 18時18分59秒
2021年5月18日 Tue 18時19分0秒
2021年5月18日 Tue 18時19分1秒
I2C通信では接続する各デバイスのI2Cアドレスを指定して制御することは先述しました。
このRTC DS3231モジュールのI2Cアドレスは0x68であることは先程確認しました。
しかしスケッチ(プログラム)内にこのアドレスが書かれていませんが、これは使用した「DS3232RTCライブラリ」内に書かれているため省略することが出来ます。(DS3232RTC.h内にアドレス0x68が書かれています)
他のI2Cデバイスを接続する際は競合しないように注意が必要です!
1602 LCDディスプレイに時刻を表示させてみる
それでは最後に今回の目標である1602 LCDディスプレイに時刻を表示させてみようと思います。
I2C対応デバイスを追加で接続するには、同様にSCLピン・SDAピンにさらに繋げるだけなので簡単です。
1602 LCDモジュールにはLiquidCrystal_I2Cライブラリを使います。
LiquidCrystal_I2Cライブラリの使い方は前回の内容を参照して下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | // Arduino入門編⑲ LCDディスプレイに時刻を表示させる // https://burariweb.info #include <DS3232RTC.h> // ライブラリのインクルード #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); const char *weekStr[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; void setup(){ ///// 時刻の設定 ///// // 時刻設定時のみ以下2行のコメントアウト(//)を外して下さい。 // setTime(12, 26, 30, 16, 5, 2021); // 時,分,秒,日,月,年の順で設定 // RTC.set(now()); // RTCモジュールに時刻情報を書き込む setSyncProvider(RTC.get); // RTCから時刻情報を取得する関数 lcd.init(); // LCDの初期化 lcd.backlight(); // LCDバックライトの点灯 } void loop(){ lcd.setCursor(0, 0); lcd.print(year()); lcd.print("/"); if(month() < 10){ lcd.print("0"); } lcd.print(month()); lcd.print("/"); if(day() < 10){ lcd.print("0"); } lcd.print(day()); lcd.print(" "); lcd.print(weekStr[weekday()-1]); lcd.setCursor(0, 1); if(hour() < 10){ lcd.print("0"); } lcd.print(hour()); lcd.print(":"); if(minute() < 10){ lcd.print("0"); } lcd.print(minute()); lcd.print(":"); if(second() < 10){ lcd.print("0"); } lcd.print(second()); delay(1000); // 1秒間隔で表示させる } |
先程のスケッチのserial.printがlcd.print等に置き換わっているだけなので簡単ですね。
取得した数字が1桁の場合、先頭に”0″を付け2桁表示にさせています。(条件式ifの部分です)
Arduinoを使ったシンプルな時計の出来上がりです。
I2Cデバイスの接続は簡単で、スケッチも対応したライブラリを使えば主要部分はライブラリが担当してくれるので比較的に出来ます。
今回2つのI2C対応デバイスを使いシンプルな時計を作ってみましたが、I2Cに対応したセンサーやドライバなどをさらに増やしていくのも基本的にSCL・SDAに繋げ追加していくだけなので簡単です。
RTCモジュールを使った応用例
Arduinoで時刻情報が扱えるようになるRTCモジュールですが、いろいろと面白いことに応用ができます。
これは以前作ったPlotclockというRTCから得た時刻情報をもとにサーボモーターを動かし時間を描くという面白い時計となります。
この投稿をInstagramで見る
今回使ったアイテム
DS3231 RTCモジュール
I2C通信に対応したArduinoではよく使われるポピュラーなRTCモジュールとなります。
1602 LCDモジュール
Arduinoでよく使われるポピュラーなLCDモジュール(16×2)となります。
I2Cシリアルインターフェースボードモジュールが付属したこちらを使用しました。
Arduino UNO
Arduinoはオープンソースのハードウェアなので正規品以外にも互換品が多数メーカーから販売されています。
互換品でも正規品と比べて特に問題なく使用でき数百円程度で購入が可能なのでArduino学習用としていいですね!
Arduino スターターキット
これからArduino学習を進めていくにあたりArduino UNO(互換品)やブレッドボード、ジャンパーピンなどがセットになったスターターキットが販売されています。
私はGeekcreit製のスターターキットを使っていますが、ELEGOO製のものは国内Amazonなどでも購入可能で人気があるようです。(セット内容はほぼ同じです!)
そしてELEGOOのサイトからスターターキット用サンプルスケッチのダウンロードも可能です。(Geekcreitのキットでも使えます)
参考 チュートリアルダウンロードELEGOO基本的にこれからこのセットで出来るものから紹介していこうと考えていますが、かなり多くのことが出来ます。
電子工作を始めるにはまずブレッドボードやジャンパーピン、メインとなるArduino UNOやサーボ、LEDなどの基本的なパーツがないと実際に動かすことが出来ませんが、個々にパーツを購入して回路を組んでとなるとかなりの手間がかかります。
スターターキットがあればArduinoの初歩的なことはかなりの数こなすことが出来るのでオススメです!
そこからスキルアップに伴い個別でセンサーなど必要なものを増やしていくのがいいと思います。
最後に!
シリアル通信の1つであるI2C通信はその概要が分かれば、それぞれI2C対応デバイスを制御するための専用ライブラリが用意されているので比較的簡単に動かすことが出来ます。
今回I2C通信で複数の対応デバイスを動かす例としてRTCモジュールを使いシンプルな時計として動かしてみました。
時刻情報を取得する機能を持たないArduinoではRTCモジュールを使うのが基本となり、今後いろいろと使える場面が多いかと思います。
コメントを残す