時間の表示が出来るようになったので、更に、温度・湿度を測定し表示させることにした。温湿度センサは当初はBME280を利用する予定でしたが、BME280は動作電圧が3.3Vで、測定値の補正計算も面倒そうなので、5Vで動作し、データもリニアでそのまま使えるHDC1050を使うことにした。
HDC1050のデータは全て16ビットで、最初に動作設定をConfiguration(0x02)に書き込み、温度(0x00)または湿度(0x01)にアドレス指定すると温湿度の測定が開始され、測定終了後に温度や湿度の16ビットデータ(有効データは上位14ビット)読み込み、測定範囲で浮動小数点データに変換するだけである(温度は-40℃オフセットが必要)。HDC1050では温度と湿度を同時に測定し、温度と湿度を続けて読み込むこともできるが、ここでは温度と湿度を個別に測定し、読み込む方法を用いた。
左ボタンは「温湿度/時刻表示」切替えボタン、右ボタンは「秒/曜日・温度表示桁」切替ボタンとした。LCD表示時の注意として、UNOではsprintfでformat文に"%f"が使えないので、dtostrf()を利用した(指数表示できるdtostre()もある)。なお、標準で温度表示は4桁で、5桁以上になると右端の”C"が表示されない。この場合、右ボタンを押すと”C"を含めて正しく表示される
なお、RTCの内部データはBCDデータとなっているので、整数データをBCDに変換して書き込み、読み出し時には2進数に変換した。また、プッシュボタンを押すと、「秒表示」と「曜日表示」を変更できる。
1秒毎の測定にはRTCの一定周期割り込みも使えるが、RTCのCLOCKOUTに1Hzが出力されるように設定し、これをUNOの2番ピンに接続し、UNOの外部割り込み(立ち上がり)を利用した。割込ルーチンではrtc_int_flgをセットし、メインルーチンで常にrtc_int_flgをチェックし、フラグが立っていたら各データを取り込んで、LCDに表示している。これにより1秒毎に時計と温湿度データを取込み、表示している。RTCのINT出力はRTC基板のLED表示に利用した(1秒毎にON/OFF)。
char *dtostrf( double val, signed char width, unsigned char prec, char *s ) 【変数】val :変換する値 width :小数点や符号を含んだ変換後の総文字数(負の数を指定すると左詰めとなる) prec :小数点以下の桁数 s :変換後の文字列を格納する変数を指定 戻り値 :戻り値は、変換後の文字列を格納する変数(sと同じ)
//********** interrupt routin *****
void rtc_intr(){ // 割込処理ルーチン
rtc_int_flg = true; // 割込フラグをセット
}
・・・
attachInterrupt( 0, rtc_intr, FALLING ); // 割込設定(H->L))
・・・
![]() |
![]() |
![]() |
| 温湿度測定表示回路図 | ブレッドボード配線 (左:温度/時刻、右:秒/曜) |
温湿度データ読み込み・表示中 |
// 温度・湿度測定+RTC+LCD( HDC1050 + rtc-8564nb + LCD ) #include |
//***** 液晶表示 ********(使用電源によりどちらか選択)
//#define BOOST 0x04 // 3.3V用 AQM0802
#define BOOST 0x00 // 5.0V用 AQM0802
int contrast = 0x20; // コントラスト初期値
void lcd_cmd(byte cmd){
Wire.beginTransmission(LCD_Adr);
Wire.write(0x00); // コマンド指定
Wire.write(cmd); // コマンド出力
Wire.endTransmission(); // ストップ
if((cmd == 0x01)||(cmd == 0x02)) // ClearかHomeか
delay(2); // 2msec待ち
else
delayMicroseconds(30); // 30μsec待ち
}
void lcd_data(byte data){
Wire.beginTransmission(LCD_Adr); // スタート
Wire.write(0x40); // 表示データ指定
Wire.write(data); // 表示データ出力
Wire.endTransmission(); // ストップ
delayMicroseconds(30); // 遅延
}
void lcd_setCursor(byte clm,byte row){
if(row==0) lcd_cmd(0x80+clm); // カーソル位置
if(row==1) lcd_cmd(0xc0+clm);
}
void lcd_begin(void){ // LCDの初期化
Serial.println("LCD_begin");
delay(10);
lcd_cmd(0x38); // 8ビット2行 標準モード
lcd_cmd(0x39); // 8ビット2行 拡張モード
lcd_cmd(0x14); // OSC 183Hz BIAS 1/5
lcd_cmd((byte)(0x70 + (contrast & 0x0F)));
lcd_cmd((byte)(0x58 + BOOST + (contrast >> 4)));
lcd_cmd((byte)0x6B); // Follwer for 3.3V
delay(1);
lcd_cmd((byte)0x38); // 標準モードへ
lcd_cmd((byte)0x0C); // 表示開始
lcd_cmd((byte)0x01); // 画面消去
delay(1);
}
void lcd_clear(void){
lcd_cmd(0x01); // 全消去コマンド出力
delay(2);
}
void lcd_print(char* ptr){ // 文字列表示関数
while(*ptr != 0) // 文字取り出し
lcd_data(*ptr++); // 文字表示
}
void lcd_print(int num){ // 整数表示関数
sprintf(s_buf,"%d",num);
lcd_print(s_buf);
}
//***** HDC1050 ********
#define HDC_TEMP 0
#define HDC_HUME 1
#define HDC_CONFIG 2
void hdc_write(byte adr, word data){
Wire.beginTransmission(HDC_Adr);
Wire.write(adr); // アドレス指定
Wire.write((byte)(data >> 8)); // データ書込み(MSD8)
Wire.write((byte)(data % 0xff)); // データ書込み(LSD8)
Wire.endTransmission();
delay(1);
}
unsigned int hdc_read(byte adr){
word rd_dat;
Wire.beginTransmission(HDC_Adr);
Wire.write(adr); // アドレス指定
Wire.endTransmission();
Wire.requestFrom(HDC_Adr,2); // データ1バイト送信要求
while ( Wire.available()== 0 );
rd_dat = Wire.read() << 8 ; // データ取得(MSD8)
rd_dat = rd_dat | Wire.read(); // データ取得(LSD8)
return rd_dat;
}
void hdc_trigger(byte adr){
Wire.beginTransmission(HDC_Adr);
Wire.write(adr); // アドレス指定
Wire.endTransmission();
delay(1);
}
unsigned int hdc_read_data(){
word rd_dat;
Wire.requestFrom(HDC_Adr,2); // データ1バイト送信要求
rd_dat = Wire.read() << 8 ; // データ取得(MSD8)
rd_dat = rd_dat | Wire.read(); // データ取得(LSD8)
return rd_dat;
}
|
void hdc_begin(){ //****** 条件により選択
Serial.println("HDC_begin");
//hdc_write(HDC_CONFIG, 0x0000); // TH単独、14bit、ヒートoff
//hdc_write(HDC_CONFIG, 0x1000); // TH同時、14bit、ヒートoff
hdc_write(HDC_CONFIG, 0x2000); // TH単独、14bit、ヒートon
//hdc_write(HDC_CONFIG, 0x3000); // TH同時、14bit、ヒートon
delay(1);
sprintf(s_buf,"HDC device: %x", hdc_read(0xff) );
Serial.println(s_buf);
}
//********** interrupt routin *****
void rtc_intr(){ // 割込処理ルーチン
rtc_int_flg = true; // 割込フラグをセット
Serial.println("interrupt!"); // 周期割込確認用
}
//********* setup ***********
void setup(){
Serial.begin(9600); // シリアルモニタON
pinMode(MdBtn_Pin, INPUT_PULLUP); // モード選択ボタン
pinMode(THBtn_Pin, INPUT_PULLUP); // 時間・温度選択ボタン
Wire.begin(); // I2C通信開始
delay(1);
rtc_begin(); // RTCの初期化
lcd_begin(); // LCDの初期化
hdc_begin();
attachInterrupt( 0, rtc_intr, FALLING ); //割込設定
Serial.println("-- setup end");
}
//********* main loop ***********
unsigned int temp;
unsigned int hum;
float f_buf;
char buf[10] = "";
void loop(){
if ( digitalRead(MdBtn_Pin) == LOW ){;
dsp_md = dsp_md ^ 0x01; // ビット0を反転
while( digitalRead(MdBtn_Pin) == LOW ); // highまで待つ
}
if ( digitalRead(THBtn_Pin) == LOW ){;
dsp_md = dsp_md ^ 0x02; // ビット1を反転
while( digitalRead(THBtn_Pin) == LOW ); // highまで待つ
}
hdc_trigger( HDC_TEMP );
delay(10);
temp = hdc_read_data();
//temp = 0xffff; // 表示テスト用
hdc_trigger( HDC_HUME );
delay(10);
hum = hdc_read_data();
if ( rtc_int_flg == true ){ // 割込フラグが立っているか?
rtc_read_data(); // RTCからデータを読む
switch ( dsp_md ){
case 0:
case 1:
sprintf( s_buf,"%02d/%02d/%02d",years,months,days );
break;
case 2:
f_buf = (float)temp / 65536.0 * 165.0 - 40.0;
dtostrf( (double)f_buf,4,1,buf); // "%f"の代わり
sprintf( s_buf,"T:%4s\337C",buf );
break;
case 3:
f_buf = (float)temp / 65536.0 * 165.0 - 40.0;
dtostrf( (double)f_buf,5,1,buf); // "%f"の代わり
sprintf( s_buf,"T%5s\337C",buf );
break;
}
lcd_setCursor(0,0); // カーソルを0行目の先頭に
lcd_print(s_buf); // LCDに年月日を表示
Serial.println( s_buf ); // 表示テスト・確認用
switch ( dsp_md ){
case 0:
sprintf( s_buf,"%02d:%02d:%02d",hours,minutes,seconds );
break;
case 1:
sprintf( s_buf,"%02d:%02d%3s",hours,minutes,wk_dt[weeks] );
break;
case 2:
case 3:
f_buf = (float)hum / 65536.0 * 100.0;
dtostrf( (double)f_buf,4,1,buf); // "%f"の代わり
sprintf( s_buf,"H:%4s %%",buf );
break;
}
lcd_setCursor(0,1); // カーソルを1行目の先頭に
lcd_print(s_buf); // LCDに時分秒を表示
Serial.println( s_buf ); // 表示テスト・確認用
rtc_int_flg = false; // 割込フラグ消去
}
delay(10);
}
|
温度・湿度−LCD表示スケッチ (hdc1050_rtc.ino), (hdc1050_rtc.zip)
郵便物などの宛名が残ったままゴミ箱に捨てた場合、個人情報が読み取られる場合があります。
このような場合、シュレッダーを使ったり、宛名部分を黒く塗りつぶす方法が行われています。郵便物など消す部分が小さい場合は、「コココロケシコロ」「ケシポン」などのローラースタンプが便利です。特にMAXの「コロコロケシコロwithレターオープナー」は宛名消しと切り屑を出さずに封筒カットと両方出来るので、机の上に一つ置いておくと便利です
![]() |
| コロコロ消しコロwithレターオープナー |
毎年、砺波市で開催されているチューリップフェアに久しぶりに行きました。朝早かったので近くの駐車場に車を駐車できましたが、平日にも関わらず県外ナンバー車が多く止まっていました。
全体を俯瞰するためチューリップタワーに登り、大花壇を見ると、100回記念の花絵が綺麗に見えました。さらに、花の大谷、水上花壇、五輪揚水水車とまわり、ふるさと広場の屋台で昼食をとりました。次に訪れたチューリップ四季彩館では、チューリップが咲き揃うワンダーガーデン、特別展示のロイヤルコレクション(皇室に献上した品種)が展示されていました。カフェーかくれ庵でチューリップソフトをいただきました。チューリップの原産地はトルコで、宮殿やモスクのタイルに使われていたことや、球根では富山県、切り花では新潟県、どちらも県花、と勉強にもなりました。
![]() |
![]() |
![]() |
![]() |
| チュ-リップタワー | 大花壇 | 花の大谷 | 水上花壇 |
![]() |
![]() |
![]() |
![]() |
| 五輪揚水水車 | 水車の説明 | ふるさと広場 | チューリップ色彩館 |
![]() |
![]() |
![]() |
![]() |
| ちゅーりっぷソフト | ワンダーガーデン | ロイヤルコレクション | トルコのチューリップ |
![]() |
![]() |
![]() |