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)。
# | パーツ | 仕様 | 個数 | 備考 |
1 | Arduino Uno Rev3 | ATmega328 | 1 | 【M-07385】 ※テスト時利用 |
ELEGOO Arduino用Nanoボート | (CH340/ATmega328P) ※個入りの1個を利用 | 1 | ※ケース組込時 | |
2 | RTCモジュール | RX8900CE UA DIP化モジュール | 1 | 【K-13009】 |
3 | 温湿度センサモジュール | SENSIRION社SHT31-DISセンサ | 1 | 【K-12125】 |
4 | LCDモジュール | I2C接続 16×2行 白色バックライト [ACM1602NI-FLW-FBW-M01] | 1 | 【P-05693】 |
5 | 半固定ボリューム | 3362P 10KΩ | 1 | 【P-03277】 |
6 | 電気二重層コンデンサ (EDLC) | 1.5F 耐電圧 5.5V(タテ型) | 1 | 【P-04300】 |
7 | 抵抗 | 200Ω | 1 | 手持ち |
8 | ブレッドボード | EIC-801 | 1 | 【P-00315】 |
9 | ジャンパーワイヤ | オス-オス 10cmセット | 1 | 【C-05371】 |
10 | スイッチングACアダプタ | 9V 1.3A 100~240V ※PCとUSB接続のみの場合は不要 | 1 | 【M-00030】 |
Arduinoの開発環境「Arduino IDE」のセットアップ手順
Arduinoの公式サイトからArduino IDEをダウンロードしてPCにインストールします。
Arduinoボードの開発環境となる「Arduino IDE」のインストール、各種センサやLCDといったモジュールとArduinoとの接続を容易にする「ライブラリ」を活用したスケッチ作成までの手順メモです。
モジュールのI2Cアドレスとピン番号の確認
各モジュールのI2Cアドレスと、モジュール上のコネクタに割り当てられたSCL 信号 とSDA信号のピン番号のメモです。
# | モジュール | SCL | I2CSDA | I2Cアドレス | I2C
1 | SHT31 センサ | 3番ピン | 2番ピン | 0x45 ※ADR(4番ピン)解放の場合 |
2 | RX8900CE RTC | 6番ピン | 5番ピン | 0x32 |
3 | LCD (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 スレーブアドレスとなるようです。
ブレッドボードで組み立て(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追加)。
温湿度計&LCD時計のスケッチ作成
SHT31センサモジュール用のスケッチとライブラリは秋月電子通商サイトのAE_SHT31.zipを、RX8900CEモジュールは秋月電子通商サイトの RX8900_SAMPLE.zipとcitrienaサイトのRX8900RTC-master.zipを参考にさせていただきました。
シリアルポート出力から今回使ったLCDモジュール(ACM1602NI-FLW-FBW-M01)への出力に変更しました。このLCDモジュール用のI2Cライブラリは「構想100年」サイトの LcdCore_20120528.zipとLCD_ACM1602NI_20120528.zipを利用させていただきました。
SHT31センサモジュールとRX8900CEモジュールの出力をマージして一つのLCDモジュールに温湿度計とLCD時計を表示するスケッチです。
スケッチ1:日付、曜日、時刻と 温湿度をコンパクトに表示(2022/03/26修正)
日付、曜日、時刻を上下2段に表示し、 温度と湿度は小数点以下を四捨五入して2段目の右下にコンパクトに表示します。
バッテリーバックアップ対応のスケッチ修正を行いました。 曜日を追加。月、日、時、分、秒が0~9の1桁の場合、1桁目に 空白 もしくは 0 を追加して、右寄りの2桁で表示するように修正しました。
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桁で表示するように修正しました。
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を実行しています。