時計の作り方 [Arduino]
Arduinoで「リアルタイムクロック」(RTC)と「液晶ディスプレイ」(LCD)を使用して「時計」を作る方法です。
Windowsやスマホなどのソフトウェアだと数行で時計を作れますが、ハードウェアだと15本程度の配線と150行ぐらいのプログラムコードが必要となります。(ハードウェア屋さんはタイヘン)
※LCDの液晶部分は透明の保護フィルムを貼ったままですので、少し見ずらいかも知れません。
関連記事:リアルタイムクロック LCD(液晶ディスプレイ)
使用部品・材料
総額で約1,620円です。(Arduino本体の値段を除く)
部品/材料 | 値段 | 備考 |
---|---|---|
ブレッドボード | ¥270 | 秋月電子の通販コード(P-00315) |
LCDキャラクタディスプレイモジュール 16x2行 バックライト付白抜き | ¥800 | 秋月電子の通販コード(P-02919) |
リアルタイムクロック(RTC) モジュール | ¥500 | 秋月電子の通販コード(I-00233) |
半固定ボリューム 10kΩ [103] | ¥50 | 秋月電子の通販コード(P-08012) |
カーボン抵抗器 | 数円 | 1kΩ(2個)を使用。 |
配線図
※詳細は記事冒頭の関連記事を参照。
スケッチ(プログラム)
2017年12月25日(月) 12時20分15秒から時計を開始します。
#include <Wire.h> #include <LiquidCrystal.h> // ピン番号を指定してライブラリを初期化する LiquidCrystal lcd(5,6,7,10,11,12,13); // 外部割り込みの状態 volatile int state = LOW; // RTCのレジスタテーブル(16byte) int RegTbl[16]; // スレーブアドレス byte SLAVE_ADDRESS = 0x51; // 2進化10進数(BCD)を10進数に変換 byte BCDtoDec(byte value){ return ((value >> 4) * 10) + (value & 0x0F) ; } // 外部割り込みが発生した時に動作します。 void myInterrupt() { state = !state; } void setup() { // LCDの列と行を設定する lcd.begin(16, 2); // 2ピンの状態がLOWからHIGHに変化した場合に外部割り込みを発生させる attachInterrupt(digitalPinToInterrupt(2), myInterrupt, RISING); // マスタとしてI2Cバスに接続する Wire.begin(); // I2Cスレーブに対して送信処理を開始する Wire.beginTransmission(SLAVE_ADDRESS); // レジスタのアドレスを指定する(0-15の内、先頭から) Wire.write(0x00); // --------------------------------- // コントロールレジスタ // --------------------------------- // [00]Control1 Wire.write(0x00); // [01]Control2 Wire.write(0x00); // --------------------------------- // 時計・カレンダーレジスタ // --------------------------------- // アドレスの[02-05]及び[08-11]は2進化10進数(BCD)で指定します。 // [02]Seconds(15秒) Wire.write(0x15); // [03]Minutes(20分) Wire.write(0x20); // [04]Hours(12時) Wire.write(0x12); // [05]Days(25日) Wire.write(0x25); // [06]Weekdays(月) // 0:日 1:月 2:火 3:水 4:木 5:金 6:土 Wire.write(0x01); // [07]Month/Century(21世紀の12月) // ・Month(01-12) BCD形式 // ・Century(先頭bit 0:20世紀[19xx年代],1(0x80):21世紀[20xx年代]) Wire.write(0x12 | 0x80); // [08]Years(2017年) Wire.write(0x17); // --------------------------------- // アラームレジスタ // --------------------------------- // 0x80はアラーム対象外となる // [09]Minutes Alarm Wire.write(0x80); // [0A]Hours Alarm Wire.write(0x80); // [0B]Days Alarm Wire.write(0x80); // [0C]Weekdays Alarm Wire.write(0x80); // --------------------------------- // クロック出力レジスタ // --------------------------------- // [0D]CLKOUT Frequency // ・クロック出力機能を有効にする。 // ※有効:0x80 無効 :0x00 // ・クロック周波数は1Hz(1秒間に1回)とする // ※0x00:32768Hz, 0x01:1024Hz, 0x02:32Hz, 0x03:1Hz // // 次の設定だと2ピン[CLKOUT]から1秒に1回、クロック出力される Wire.write(0x80 | 0x03); // I2Cスレーブへの送信完了 Wire.endTransmission(); } void loop(){ int i; String myClock= ""; // 外部割込みが発生した場合 if(state == HIGH){ // このメソッドは画面をクリアする便利な機能ですが、 // 毎秒、実行すると画面がちらつきます。 // lcd.clear(); // レジスタのアドレスを先頭にする Wire.beginTransmission(SLAVE_ADDRESS); Wire.write(0x00); Wire.endTransmission(); // スレーブの16byteのレジスタデータを要求する Wire.requestFrom(SLAVE_ADDRESS,16); // 16byteのデータを取得する for (i=0; i<16; i++){ while (Wire.available() == 0 ){} RegTbl[i] = Wire.read(); } // 現在の年月日 myClock += String(BCDtoDec(RegTbl[8])+ 2000) + "/"; myClock += String(BCDtoDec(RegTbl[7] & 0x1F)) + "/"; myClock += String(BCDtoDec(RegTbl[5] & 0x3F)) + ""; switch(RegTbl[6] & 0x07){ case 0 : myClock += "(Sun)";break; case 1 : myClock += "(Mon)";break; case 2 : myClock += "(Tue)";break; case 3 : myClock += "(Wed)";break; case 4 : myClock += "(Thu)";break; case 5 : myClock += "(Fri)";break; case 6 : myClock += "(Sat)";break; } // LCDの1行目 lcd.setCursor(0,0); lcd.print(myClock); myClock = ""; // 現在の時刻 myClock += String(BCDtoDec(RegTbl[4] & 0x3F)) + ":"; myClock += String(BCDtoDec(RegTbl[3] & 0x7F)) + ":"; // 秒が1桁の場合は2桁にする // ※時/分も同じようにして下さい。 String s = String(BCDtoDec(RegTbl[2] & 0x7F)) ; if(s.length()==1){ s = "0" + s; } myClock += s; // LCDの2行目 lcd.setCursor(0,1); lcd.print(myClock); state = !state; } }
以上です。
スポンサーリンク
掲示板
ArduinoやRaspberry Piなどの電子工作の掲示板を作成しました。質問やわからない事は電子工作 (Arduino・ラズパイ等)でユーザー同士で情報を共有して下さい。
関連記事
公開日:2017年05月27日 最終更新日:2017年08月20日
記事NO:02398