Arduinoと SHT31センサと RTCモジュールRX8900を使って 温湿度計と時計を一つのLCDモジュールに表示

Arduino Uno Rev3とSHT31センサモジュールを使ったLCD温湿度計とRX8900CEを搭載したRTC(リアルタイムクロック)モジュールを使ったLCD時計を別々に作りましたが、 両モジュールをI2CバスでArduinoにつないで一つのLCDモジュール(ACM1602NI-FLW-FBW-M01)にまとめて表示しました。

温湿度計と時計を一つの液晶モジュールに表示
  
目次

集めたパーツ(2021/12/13追記)

ネット通販(今回は秋月電子通商)でパーツを集めてブレッドボード上で結線しました。 テスト時にはArduino Uno Rev3を使いましたが、ケース組み込み時には小型で安価なNano互換ボードを使っています。
電気二重層コンデンサ(EDLC)によるRTCモジュールのバッテリーバックアップ回路を追加しました(2021/12/131)。

#パーツ仕様個数備考
1Arduino Uno Rev3ATmega3281M-07385
※テスト時利用
ELEGOO
Arduino用Nanoボート
(CH340/ATmega328P)
※個入りの1個を利用
1※ケース組込時
2RTCモジュールRX8900CE UA DIP化モジュール1K-13009
3温湿度センサモジュールSENSIRION社SHT31-DISセンサ1K-12125
4LCDモジュールI2C接続 16×2行
白色バックライト
[ACM1602NI-FLW-FBW-M01]
1P-05693
5半固定ボリューム3362P 10KΩ1P-03277
6電気二重層コンデンサ
(EDLC)
1.5F 耐電圧 5.5V(タテ型)1P-04300
7抵抗200Ω1手持ち
8ブレッドボードEIC-8011P-00315
9ジャンパーワイヤオス-オス 10cmセット1C-05371
10スイッチングACアダプタ9V 1.3A 100~240V
※PCとUSB接続のみの場合は不要
1M-00030

Arduinoの開発環境「Arduino IDE」のセットアップ手順

Arduinoの公式サイトからArduino IDEをダウンロードしてPCにインストールします。 

Arduinoボードの開発環境となる「Arduino IDE」のインストール、各種センサやLCDといったモジュールとArduinoとの接続を容易にする「ライブラリ」を活用したスケッチ作成までの手順メモです。

あわせて読みたい
Arduinoの開発環境「Arduino IDE」のセットアップ手順 Arduinoボードの開発環境となる「Arduino IDE」のインストール、各種センサや液晶ディスプレイといったモジュールとArduinoとの接続を容易にする「ライブラリ」を活用し...

モジュールのI2Cアドレスピンアサインの確認

各モジュールのI2Cアドレスと、モジュール上のコネクタに割り当てられたSCL 信号 とSDA信号のピン番号のメモです。

#モジュールI2C
SCL
I2C
SDA
I2C
アドレス
1SHT31 センサ3番ピン2番ピン0x45
※ADR(4番ピン)解放の場合
2RX8900CE RTC6番ピン5番ピン0x32
3LCD
(ACM1602NI-FLW-FBW-M01)
4番ピン5番ピン0xa0

  
ArduinoサイトにI2Cアドレスをスキャンするスケッチ Arduino Playground – I2cScanner があります。このスケッチを Arduino IDE(1.8.16)で実行すると、各デバイスのI2Cアドレスはコメントにあるように「見つかったデバイスの7ビットのアドレスを16進数で表示」されます。

LCDモジュールのI2Cアドレスは 0x50 と検出されました。 データシートでも「7ビットのスレーブアドレス 1010000 が1つだけ予約されています」とあり、1010000( 7bit 、0x50) です。
今回使ったライブラリでは最下位ビットに0(マスターからスレーブへの書き込み)の識別値を加えた 10100000(8bit、0xa0)が I2C スレーブアドレスとなるようです。

i2c_scannerスケッチの実行結果
i2c_scannerスケッチの実行結果

ブレッドボードで組み立て(2021/12/13追加)

ブレッドボードにSHT31センサモジュールとRX8900CEモジュール、LCDモジュール(ACM1602NI-FLW-FBW-M01)とコントラスト調整用の半固定抵抗を実装し、 Arduino uno Rev3の該当ピン からI2C線(SCLとSDAの2線)、3.3V線とGND線を延長して配線します。

RX8900モジュールに電気二重層コンデンサ(EDLC)によるバッテリーバックアップを実装しました(2021/12/13追加)。

温湿度計と時計を一つの液晶モジュールに表示
ケーブル色は、SCLは緑、SDAは白、3.3Vは赤、GNDは黒、バックライト調整は黄色。EDLCは電気二重層コンデンサ。

温湿度計&LCD時計のスケッチ作成

SHT31センサモジュール用のスケッチとライブラリは秋月電子通商サイトのAE_SHT31.zipを、RX8900CEモジュールは秋月電子通商サイトの RX8900_SAMPLE.zipとcitrienaサイトのRX8900RTC-master.zipを参考にさせていただきました。
シリアルポート出力から今回使ったLCDモジュール(ACM1602NI-FLW-FBW-M01)への出力に変更しました。このLCDモジュール用のI2Cライブラリは「構想100年」サイトの LcdCore_20120528.zipLCD_ACM1602NI_20120528.zipを利用させていただきました。

SHT31センサモジュールとRX8900CEモジュールの出力をマージして一つのLCDモジュールに温湿度計とLCD時計を表示するスケッチです。

スケッチ1:日付、曜日、時刻と 温湿度をコンパクトに表示(2022/03/26修正)

日付、曜日、時刻を上下2段に表示し、 温度と湿度は小数点以下を四捨五入して2段目の右下にコンパクトに表示します。

バッテリーバックアップ対応のスケッチ修正を行いました。 曜日を追加。月、日、時、分、秒が0~9の1桁の場合、1桁目に 空白 もしくは 0 を追加して、右寄りの2桁で表示するように修正しました。

スケッチ1 を実行中のLCD時計&温湿度計
スケッチ1 を実行中のLCD時計&温湿度計

2022/03/26:loop処理を機能単位に分割、秒表示に飛びがあったのでdelay値を調整
2021/12/17:曜日の演算に不具合があったのでスケッチを修正

Arduino_SHT31_RX8900_LCD-C.ino  ※ここをクリックするとコード表示を開閉できます。
#include <Arduino.h>
#include <Wire.h>
#include <TimeLib.h>       // https://github.com/PaulStoffregen/Time
#include <RX8900RTC.h>     // https://github.com/citriena/RX8900RTC
#include <LcdCore.h>       // LCDコアライブラリ
#include <LCD_ACM1602NI.h> // 秋月I2C液晶用のI/Oライブラリ
#include <AE_SHT31.h>      // 秋月SHT31用のライブラリ

RX8900RTC RTC;
LCD_ACM1602NI lcd(0xa0);   // 0xa0は液晶モジュールのI2Cアドレス
AE_SHT31 SHT31(0x45);

void setup() {
Wire.begin();         // I2C初期化
lcd.begin(16, 2);     // ディスプレイの行数(16)と桁数(2)
RTC.init();           // RTC初期化
//RTC.get()よりcompileTime()が新しい時はcompiletimeをRTC.set
time_t time_now, compiletime;;
time_now = RTC.get();
compiletime = compileTime();
if (time_now < compiletime)
{
RTC.set(compiletime); // set compiled time to RTC
// tmElements_t tm = {0, 0, 12, 0, 5, 5, CalendarYrToTm(2020)}; // second, minute, hour, week, day, month, year
// RTC.write(tm);
}
SHT31.SoftReset();    // SHT31をソフトリセット
SHT31.Heater(0);      // 内蔵ヒーター 0:OFF 1:ON
}

void loop() {
serialTime(RTC.read());
serialTempHum();
delay(10);  // 調整
}

// 秋月I2C液晶ディスプレイに表示(温度,湿度)
void serialTempHum() {
SHT31.GetTempHum();   // SHT31から温湿度データを取得
lcd.setCursor(9, 1);
lcd.print(SHT31.Temperature(),0);// 温度をLCDに表示、四捨五入
lcd.setCursor(11, 1);
lcd.print("c");
lcd.setCursor(13, 01);
lcd.print(SHT31.Humidity(),0);   // 湿度をLCDに表示、四捨五入
lcd.setCursor(15, 1);
lcd.print("%");
}

// 秋月I2C液晶ディスプレイに表示(年月日,曜日,時分秒)
void serialTime(tmElements_t tm) {
//  年月日の表示
lcd.setCursor(0, 0);
lcd.print(tmYearToCalendar(tm.Year));
lcd.setCursor(4, 0);
lcd.print("/");
lcd.setCursor(5, 0);
lcdzeroSup(tm.Month);
lcd.setCursor(7, 0);
lcd.print("/");
lcd.setCursor(8, 0);
lcdzeroSup(tm.Day);
// 曜日の表示 0=日曜  1=月曜  2=火曜  3=水曜  4=木曜  5=金曜  6=土曜
int day_week ;
char DayWeekData[7][4] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"} ;
day_week = getDayWeek(tmYearToCalendar(tm.Year), tm.Month, tm.Day) ;
lcd.setCursor(11, 0);
lcd.print("(");
lcd.print(DayWeekData[day_week]) ;
lcd.print(")");
//時分秒の表示
lcd.setCursor(0, 1);
lcdzeroSup(tm.Hour);
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(3, 1);
lcdzeroSup(tm.Minute);
lcd.setCursor(5, 1);
lcd.print(":");
lcd.setCursor(6, 1);
lcdzeroSup(tm.Second);
}

// 曜日の計算(ツェラー(Zeller)の公式)
int getDayWeek(int year,int month,int day) {
int w ;
if(month < 3) {
year = year - 1;
month = month + 12 ;
}
w = (year + (year/4) - (year/100) + (year/400) + (13*month+8)/5 + day ) % 7;
return w;
}

// 月、日、時、分、秒が0~9の場合、1桁目を 空白 もしくは 0 に置換
void lcdzeroSup(int digit) {
if(digit < 10)
lcd.print(' ');  // 現在「空白」
lcd.print(digit);
}

// function to return the compile date and time as a time_t value
// from alarm_ex1.ino in Arduino DS3232RTC Library sample sketch by Jack Christensen.
time_t compileTime() {
const time_t FUDGE(10);    //fudge factor to allow for upload time, etc. (seconds, YMMV)
const char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char compMon[4], *m;
strncpy(compMon, compDate, 3);
compMon[3] = '\0';
m = strstr(months, compMon);
tmElements_t tm;
tm.Month = ((m - months) / 3 + 1);
tm.Day = atoi(compDate + 4);
tm.Year = atoi(compDate + 7) - 1970;
tm.Hour = atoi(compTime);
tm.Minute = atoi(compTime + 3);
tm.Second = atoi(compTime + 6);
time_t t = makeTime(tm);
return t + FUDGE;        //add fudge factor to allow for compile time
}

スケッチ2:日付、時刻と 温湿度を小数点以下1桁で上下に表示 (2022/3/26修正)

曜日を削除して 日付、時刻と左側の上下に、温度と湿度を少数点以下1桁まで右側の上下に表示します 。

月、日、時、分、秒が0~9の一桁の場合、1桁目に 空白 もしくは 0 を追加して、右寄りの2桁で表示するように修正しました。

スケッチ2 を実行中のLCD時計&温湿度計
スケッチ2 を実行中のLCD時計&温湿度計
Arduino_SHT31_RX8900_LCD-W.ino  ※ここをクリックするとコード表示を開閉できます。
#include <Arduino.h>
#include <Wire.h>
#include <TimeLib.h>       // https://github.com/PaulStoffregen/Time
#include <RX8900RTC.h>     // https://github.com/citriena/RX8900RTC
#include <LcdCore.h>       // LCDコアライブラリ
#include <LCD_ACM1602NI.h> // 秋月I2C液晶用のI/Oライブラリ
#include <AE_SHT31.h>      // 秋月SHT31用のライブラリ

RX8900RTC RTC;
LCD_ACM1602NI lcd(0xa0);   // 0xa0は液晶モジュールのI2Cアドレス
AE_SHT31 SHT31(0x45);

void setup() {
Wire.begin();         // I2C初期化
lcd.begin(16, 2);     // ディスプレイの行数(16)と桁数(2)
RTC.init();           // RTC初期化
//RTC.get()よりcompileTime()が新しい時はcompiletimeをRTC.set
time_t time_now, compiletime;;
time_now = RTC.get();
compiletime = compileTime();
if (time_now < compiletime)
{
RTC.set(compiletime); // set compiled time to RTC
// tmElements_t tm = {0, 0, 12, 0, 5, 5, CalendarYrToTm(2020)}; // second, minute, hour, week, day, month, year
// RTC.write(tm);
}
SHT31.SoftReset();    // SHT31をソフトリセット
SHT31.Heater(0);      // 内蔵ヒーター 0:OFF 1:ON
}

void loop() {
serialTime(RTC.read());
serialTempHum();
delay(10);  // 調整
}

// 秋月I2C液晶ディスプレイに表示(温度,湿度)
void serialTempHum() {
SHT31.GetTempHum();            // SHT31から温湿度データを取得
lcd.setCursor(11, 0);
lcd.print(SHT31.Temperature());// 温度をLCDに表示
lcd.setCursor(15, 0);
lcd.print("c");
lcd.setCursor(11, 1);
lcd.print(SHT31.Humidity());   // 湿度をLCDに表示
lcd.setCursor(15, 1);
lcd.print("%");
}

// 秋月I2C液晶ディスプレイに表示
void serialTime(tmElements_t tm) {
//  年月日の表示
lcd.setCursor(0, 0);
lcd.print(tmYearToCalendar(tm.Year));
lcd.setCursor(4, 0);
lcd.print("/");
lcd.setCursor(5, 0);
lcdzeroSup(tm.Month);
lcd.setCursor(7, 0);
lcd.print("/");
lcd.setCursor(8, 0);
lcdzeroSup(tm.Day);
//時分秒の表示
lcd.setCursor(0, 1);
lcdzeroSup(tm.Hour);
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(3, 1);
lcdzeroSup(tm.Minute);
lcd.setCursor(5, 1);
lcd.print(":");
lcd.setCursor(6, 1);
lcdzeroSup(tm.Second);
}

// 月、日、時、分、秒が0~9の場合、1桁目を 空白 もしくは 0 に置換
void lcdzeroSup(int digit) {
if(digit < 10)
lcd.print(' ');  // 現在「空白」
lcd.print(digit);
}

// function to return the compile date and time as a time_t value
// from alarm_ex1.ino in Arduino DS3232RTC Library sample sketch by Jack Christensen.
time_t compileTime() {
const time_t FUDGE(10);    //fudge factor to allow for upload time, etc. (seconds, YMMV)
const char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char compMon[4], *m;
strncpy(compMon, compDate, 3);
compMon[3] = '\0';
m = strstr(months, compMon);
tmElements_t tm;
tm.Month = ((m - months) / 3 + 1);
tm.Day = atoi(compDate + 4);
tm.Year = atoi(compDate + 7) - 1970;
tm.Hour = atoi(compTime);
tm.Minute = atoi(compTime + 3);
tm.Second = atoi(compTime + 6);
time_t t = makeTime(tm);
return t + FUDGE;        //add fudge factor to allow for compile time
}

Arduino Nano互換ボードで小型化して二合枡ケースに取り付け(2022/7/9 写真入替え)

Arduino Uno Rev3をELEGOO Arduino用Nanoボードで小型化しました。NanoのI2C通信用ピンは、SDA:A4ピン、SCL:A5ピンです。電源(ACアダプタ 9V)は、Nno互換ボードの外部電源用のポートVinから給電します。
構成変更を行うこともあるのでブレッドボードのまま二合枡に組み込んでいます。スケッチ1を実行しています。

温湿度計と時計を一つの液晶モジュールに表示
Arduino Nano互換ボードで小型化して二合枡に組み込んだLCD温湿度・時計(2022/7/9 写真入替え)
二合枡に組み込んだLCD温湿度・時計
二合枡に取り付けたACアダプタ(9V)差し込み用の2.1mm標準DCジャック
よかったらシェアしてね!
  • URLをコピーしました!
目次