卓上時計
前回記事でRTCモジュールから日時の情報が取り出せるようになり、時刻合わせもできるようになりました。定番のLCD 1602(I2C通信)をつないで「卓上時計」にしてみます。
LiquidCrystal I2C
Arduino IDEでのライブラリマネージャから、LiquidCrystal I2Cというのを検索してインストールしておきます。
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);//アドレス0x3Fの場合もある。
初期化
lcd.init(); //初期化
lcd.backlight();//バックライト点ける
書き込み位置指定
lcd.setCursor(0, 0);// 1行目の頭なら
//lcd.setCursor(0, 1);//2行目の頭なら
書き込み
lcd.print();//引数に数値や文字列
これだけ知っていればとりあえず使えそうです。
配線
I2C の配線ではSDAはArduinoUNOのA4ピン SCLはA5ピンにつなぎます。I2C の配線参考
http://www.musashinodenpa.com/arduino/ref/index.php?f=1&pos=341
サンプルコード
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);//アドレス0x3Fの場合もある。
#define SCLK 6 //(基板上CLK⇒6番ピン)
#define IO 7 //(基板上DAT⇒7番ピン)
#define CE 8 //(基板上RST⇒8番ピン)
struct DateTime{
int Seconds;
boolean CH; //1でClockHalt(停止)だが、0を入れてこの機能使わない前提
int Minutes;
int Hour;
boolean Mode12; //1で12時間表示だが、0を入れて24時間表示で使う前提
int Date;
int Month;
int Day;
int Year;
boolean WP; //1でWriteProtectだが0を入れてこの機能使わない前提
};
String DayString[]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
void setup() {
lcd.init();
lcd.backlight();
pinMode(CE, OUTPUT);
pinMode(SCLK, OUTPUT);
};
void loop() {
byte RTC_clock_image[8];//クロックデータの読み込み用。1バイト×8の配列
DateTime myDateTime;
read_rtc_byte(RTC_clock_image);//読みだしてバイト列を格納
extract_datetime(RTC_clock_image,myDateTime);//抽出してmyDateTime
//lcd.clear()
lcd.setCursor(0, 0);
lcd.print(dig2(myDateTime.Hour));lcd.print(":");
lcd.print(dig2(myDateTime.Minutes));lcd.print(":");
lcd.print(dig2(myDateTime.Seconds));
lcd.setCursor(0, 1);
lcd.print(myDateTime.Year);lcd.print("-");
lcd.print(dig2(myDateTime.Month));lcd.print("-");
lcd.print(dig2(myDateTime.Date));lcd.print("(");
lcd.print(DayString[myDateTime.Day-1]);lcd.print(")");
delay(200);//0.2秒(200ミリ秒)ごと更新。
}
//正の1桁数の場合の2桁表示(例:0⇒00 2⇒02)
String dig2(int value){
String strvalue=String(value);
if(strvalue.length()==1){
strvalue = "0"+strvalue;
}
return(strvalue);
}
//RTCからクロックデータをまるごと読みだし、
byte read_rtc_byte(byte image[]){
pinMode(IO, OUTPUT);//IOのpinmodeをまず送信用で準備
digitalWrite(CE, LOW);wait();//最初はCE下げた状態
digitalWrite(CE, HIGH);wait();//開始(CE 上げ)
write_1byte(0xbf);//バーストモードのコマンド0xbf送信
//読み出しに移るのでIOのピンモード切り替える。SCLK上げのまま
pinMode(IO, INPUT);
//8byte分続けて読みbyte配列のimageに入れる
for (int i=0; i<=7; i++){
read_1byte(image[i]);
}
//CE下げる
digitalWrite(CE, LOW); wait();
}
void write_1byte(byte data){
//コマンド等送信 1ビットずつ繰り返し8ビット(1バイト)分送る
for (int i=0; i <= 7; i++){
digitalWrite(SCLK, LOW);wait(); //LOW確認
digitalWrite( IO, bitRead(data, i));wait();
digitalWrite(SCLK, HIGH);wait(); //クロック(LOWからHIGH)で書き込む
//クロック上げたままで関数を抜ける。
}
}
void read_1byte(byte &data){
//データ受信 1ビットずつ繰り返し8ビット(1バイト)分読みだす
data = 0;
for (int i=0; i<=7; i++){
digitalWrite(SCLK, HIGH);wait();//clock上げ。(上げたまま引き継いだ時はそのまま)
digitalWrite(SCLK, LOW);wait();//clock下げて、
bitWrite( data,i, digitalRead(IO));//読む
//クロック下げた状態で関数を抜ける
}
}
void setImage(byte command, byte image){ //コマンド、書き込みデータ
pinMode(IO, OUTPUT);//IOのpinmodeを送信用で準備
digitalWrite(CE, LOW);wait();//最初はCE下げた状態
digitalWrite(CE, HIGH);wait();//開始(CE 上げ)
write_1byte(command);
write_1byte(image);
digitalWrite(SCLK, LOW);wait();//clock下げて、
digitalWrite(CE, LOW);wait();//最後はCE下げる
}
void getImage(byte command, byte &image){
pinMode(IO, OUTPUT);//IOのpinmodeを送信用で準備
digitalWrite(CE, LOW);wait();//最初はCE下げた状態
digitalWrite(CE, HIGH);wait();//開始(CE 上げ)
write_1byte(command);
pinMode(IO, INPUT);//IOのpinmodeを受信用に切り替え
read_1byte(image);
digitalWrite(CE, LOW);wait();//最後はCE下げる
}
void wait(){
//Vcc5Vなのでデータシート11ページから待ち時間は1μ秒分とっておけばよい。
delayMicroseconds(1);
}
//byte配列からの情報抽出
void extract_datetime(byte image[], DateTime &TempDateTime){
int data10, data1;
//秒
data10 = (image[0]>>4)&7; //上位4ビットを0111でマスクする。
data1 = image[0] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Seconds = (data10 * 10) + data1;
TempDateTime.CH = image[0]>>7;
//分
data10 = (image[1]>>4)&7; //上位4ビットを0111でマスクする。
data1 = image[1] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Minutes = (data10 * 10) + data1;
//時
data10 = (image[2]>>4)&3; //上位4ビットを0011でマスクする。
data1 = image[2] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Hour = (data10 * 10) + data1;
TempDateTime.Mode12 = image[2]>>7; //12時間表示モード。0にして使わない。
//日
data10 = (image[3]>>4)&3; //上位4ビットを0011でマスクする。
data1 = image[3] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Date = (data10 * 10) + data1;
//月
data10 = (image[4]>>4)&1; //上位4ビットを0001でマスクする。
data1 = image[4] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Month = (data10 * 10) + data1;
//曜日
TempDateTime.Day =image[5];
//年
data10 = (image[6]>>4) & 15; //上位4ビットを1111でマスクする。
data1 = image[6] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Year = (data10 * 10) + data1 + 2000;
//WP
TempDateTime.WP =image[7]>>7;
}