前回、arduino版センサー付きラジオをESP32に載せ替えて、ソフトの移植作業まで行った。
さて、いよいよこれからが本番なのである。
ESP32をWi-Fiにつなげて、いろんなことをしたいと思うのである。
ざっくり、最終的にやりたいこと↓
Wi-Fiに繋いで、スマホでセンサーの値を見たり、ラジオの操作が出来るようにしたい。
![](https://stat.ameba.jp/user_images/20231122/22/2110pu/e6/80/j/o0514028115367793162.jpg?caw=800)
まずは、ESP32をWi-Fiに繋いで、NTPサーバー(時間を提供する)から時刻情報を取得して、時間を表示できるようにしたい。
今回の目標仕様
・自宅のWi-Fiに繋いでNTPサーバーで取得した時間データを表示する。
・ラジオon時、off時ともLCD右下に時分を「19:32」のように表示
・ラジオoff時にBand切替スイッチを押すと、年月日時分秒を表示
さらにもう一度Band切替スイッチを押すと、DSPラジオに割り当てられたIPアドレスを表示
まずは、ESP32をWi-Fiに接続する。
こちらのページを参考に、というかコピペして、Wi-Fiに接続してするコードを追加
WiFi.hをインクルードして、自宅Wi-FiのSSIDとパスワードを設定
#include <WiFi.h>
char ssid[] = "ssid";
char pass[] = "password";
(実際にはちゃんと自宅のWiFi環境を設定)
setup()でWi-Fiに接続、そのあと、
GetWiFiConfig()で現状の状態を読み取って、シリアルモニター用に出力
SetWiFiConfig()で自宅のWi-Fiの環境内で、固定IP(192.168.10.200)に再設定
再度、GetWiFiConfig()で現状の状態を読み取って、シリアルモニター用に出力
//----------------------
// Wi-Fiに接続
//----------------------
WiFi.begin(ssid, pass);
while(WiFi.status() != WL_CONNECTED){
delay(500);
}
Serial.println("WiFi Connected");
GetWiFiConfig();
SetWiFiConfig();
GetWiFiConfig();
GetWiFiConfig()と、SetWiFiConfig()はこちら
//------------------------
// Get Wi-Fi configuration
//------------------------
//
void GetWiFiConfig() {
Serial.print("IP address:");
Serial.println(WiFi.localIP());
Serial.print("default gateway:");
Serial.println(WiFi.gatewayIP());
Serial.print("subnetmask:");
Serial.println(WiFi.subnetMask());
Serial.print("DNS Server1:");
Serial.println(WiFi.dnsIP(0));
Serial.print("DNS Server2:");
Serial.println(WiFi.dnsIP(1));
}
//------------------------------
// Set WiFi IP Address
//------------------------------
//
void SetWiFiConfig() {
WiFi.config(IPAddress(192,168,10,200),
WiFi.gatewayIP(),
WiFi.subnetMask(),
WiFi.dnsIP(0),
WiFi.dnsIP(1));
}
これで、一旦動かしてみる。arduino IDEのシリアルモニタで確認。
すると、ちゃんと動いた。
IPアドレスの再設定も上手く動いているようだ。
むむむむ、組み込み用の安い基板で、ここまで簡単につながるとは!!
おじさんが知らない間に、世の中はこんなに進歩していたのね・・・・
ちなみに、プログラム上でWi-FiのSSIDとパスワードを埋め込んでいるが、SmartConfigで設定する方法もあるらしい。↓
次に、NTPサーバーに繋いで、時刻情報を取得してみる。
最初に時間情報のための宣言
// 時間情報
struct tm timeInfo;//時刻を格納するオブジェクト
char S_YMD[11]; //年月日文字格納用
char S_HMS[10]; //時分秒文字格納用
setup()でNTPの設定を追加
//NTP設定
configTime(9 * 3600L, 0,
"ntp.nict.jp",
"time.google.com",
"ntp.jst.mfeed.ad.jp");
loop()内で1秒おきに以下のNTP_server_read()とSET_LCD_Clock();を呼ぶように変更
//------------------------------
// NTP sever read
//------------------------------
void NTP_server_read(){
getLocalTime(&timeInfo); //tmオブジェクトのtimeInfoに現在時刻を入れ込む
sprintf(S_YMD, "%04d/%02d/%02d",
timeInfo.tm_year + 1900,
timeInfo.tm_mon + 1,
timeInfo.tm_mday);
sprintf(S_HMS, "%02d:%02d:%02d",
timeInfo.tm_hour,
timeInfo.tm_min,
timeInfo.tm_sec);
Serial.println(S_YMD); //年月日をシリアルモニタへ出力
Serial.print(S_HMS); //時分をシリアルモニタへ出力
}
//----------------------------
// LCDに時刻を表示
//----------------------------
void SET_LCD_Clock(){
if (Radio_on_flag == true){ //ラジオがon
lcd.setCursor(11,1);
lcd.print(S_HMS);
}
else{
if (Display_mode == 0){ //CO2表示
lcd.setCursor(11,1);
lcd.print(S_HMS);
}
if (Display_mode == 1){ //時刻表示
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(3,1);
lcd.print(S_HMS);
}
}
}
結果、うまく動作している。
ラジオon時
ラジオoff CO2表示モード
ラジオoff 時刻表示モード
ラジオoff IPアドレス表示
ただ、1秒ごとにNTPサーバーに繋いで時刻表示しているのは、どうなんだろう?
今後Wi-Fiを使っていろんなことをするにあたって、無駄にネットワーク負荷を高くしたくないような気もする。
普通なら、RTC(リアル・タイム・クロック)を使うことになる。
ちなみにESP32にはRTCが内蔵されていて、使うこともできるようなのだが、内蔵RTCは低精度のクロックソースを使っているので、1日に数分は軽くずれるらしい。
なので、世の中の人は外付けRTCを接続するか、何とか高精度の時計用クリスタルを実装して基本プログラムをビルドし直す等、しているようだ。
そこで、急遽amazonで以下のI2CのRTCを購入。
注文したら次の日に届いた。すごい世の中になったもんである。
ブレッドボードに挿してI2Cラインに繋げる
次に、
こちらのページを参考にというか、またまたコピペして使わせていただく。
まず、Arduino IDEのライブラリマネージャーから DS3232RTC by Jack Christensen を検索してインストール。依存関係インストールするか聞いてきたのでそれもインストール。
ライブラリをインクルード
#include <time.h>
#include <DS3232RTC.h>
ライブラリを生成
//DS3232ライブラり
DS3232RTC myRTC(false);
setup()でRTCを起動してNTPサーバーから時刻を取得してRTCに時刻をセット
//RTC
myRTC.begin();
//
getLocalTime(&timeInfo);
setTime(timeInfo.tm_hour,
timeInfo.tm_min,
timeInfo.tm_sec,
timeInfo.tm_mday,
timeInfo.tm_mon + 1,
timeInfo.tm_year + 1900);
myRTC.set(now());
loop()内で1秒おきに以下のSET_LCD_Clock();を呼ぶように変更
//----------------------------
// LCDに時刻を表示
//----------------------------
void SET_LCD_Clock(){
tmElements_t tm;
myRTC.read(tm); //RTC読み込み
sprintf(S_YMD, "%04d/%02d/%02d",
tm.Year + 1970,
tm.Month,
tm.Day);
sprintf(S_HMS, "%02d:%02d:%02d",
tm.Hour,
tm.Minute,
tm.Second);
if (Radio_on_flag == true){ //ラジオがon?
lcd.setCursor(11,1);
lcd.print(S_HMS);
}
else{
if (Display_mode == 0){ //CO2表示
lcd.setCursor(11,1);
lcd.print(S_HMS);
}
if (Display_mode == 1){ //時刻表示
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(3,1);
lcd.print(S_HMS);
}
}
}
loop()内で86400秒(24H)ごとにNTPサーバーからRTCへ書き込むようにした
if (timer_count2 >= 86400){ // 24H(60*60*24)経過?
NTP_to_RTC(); //NTPサーバーからRTCへセット
timer_count2 = 0;
}
NTPサーバーの値をRTCに書き込む関数
//------------------------------
// Write NTP server value to RTC
//------------------------------
void NTP_to_RTC(){
getLocalTime(&timeInfo); //tmオブジェクトのtimeInfoに現在時刻を入れ込む
setTime(timeInfo.tm_hour,
timeInfo.tm_min,
timeInfo.tm_sec,
timeInfo.tm_mday,
timeInfo.tm_mon + 1,
timeInfo.tm_year + 1900);
myRTC.set(now());
}
動かしてみると、ちゃんと、まったく同じように時刻を表示する。
RTCに置き換えた後の動作も良さそうだ。
全ての動作確認は出来ていませんが、Ver0.2の回路図とスケッチを置いておきますので、興味のある方はどうぞ
今年の更新はここまで。
来年はもっと、ちゃんと、作っていきたいもんである。
「おいらが猫の手を貸してやるニャ」