Wi-Fi接続とNTPクライアントの実験
ESP32

概要

Arduino core for the ESP32を使った、ESP-WROOM-32開発ボードのWi-Fi接続とNTPクライアント機能についての実験です。

ついでに、NTPサーバから取得した時刻を、I2C接続の有機ELキャラクタディスプレイに表示してみました。

Arduino core for the ESP32のインストールのページはこちら

有機ELキャラクタディスプレイの実験のページはこちら

実験

WiFi接続

ESP-WROOM-32を、Wi-Fiアクセスポイントに接続し、DHCPサーバからIPアドレスを取得する実験を行いました。

サンプルスケッチ(例えばWiFiClient)等を見ると、WiFi.hをインクルードすると、WiFiという変数(インスタンス)が利用でき(実体はWiFi.cppで定義されています)、WiFi.begin()を呼び出すと、IPアドレスを取得できます。ただし、IPアドレスを取得するまでに少し時間がかかるので、WiFi.status()という関数を呼び出し、接続状態になるのを待つという感じです。

なお、DHCPを使ってIPアドレスを設定するのではなく、自分でIPアドレスを設定する場合は、WiFiSTAClass::config()を利用します。サンプルは、WiFiClientStaticIPを参照してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <WiFi.h>
 
const char* ssid     = "your-ssid";
const char* password = "your-password";
 
Serial.begin(115200);
delay(10);
 
WiFi.begin(ssid, password);
   
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}

NTPクライアント

Arduino core for the ESP32のcoresを眺めていると、NTPサーバとの時刻同期と、同期した時刻の取得ができそうでした。

1
2
3
4
5
struct tm timeInfo;

configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
configTzTime("JST-9", "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
getLocalTime(&timeInfo);

configTime()

configTime()は、NTPサーバから時刻を取得するする関数です。最初の引数は、long gmtOffset_secという変数名だったので、UTCとの時差を秒単位で設定するものと想像し、試してみたところ、9 * 3600 秒でJSTになりました。以前は、-9*3600秒のオフセットでしたが、2017年10月1日のコミットで、正負が入れ替わり9*3600となったようです。

二番目の引数は、daylightOffset_secとなっており、おそらく夏時間関係の引数なので0を設定しました。

この関数内で、最終的には、環境変数TZを設定して、tzset()を呼び出します。

残りはNTPサーバのFQDNで、API仕様上は最大3個まで設定できるようです。メソッド定義を見る限りは、最低一つ設定しておけばよさそうです。ただし、 Arduino core for the ESP32 2.0.0では、hardware/esp32/2.0.0/tools/sdk/esp32/sdkconfigで、CONFIG_LWIP_DHCP_MAX_NTP_SERVERSが1に定義されていることから、実際には最初の1個だけが有効だと思われます。参考

configTzTime()

2017年9月に、configTzTime()という関数が導入されました。上記のconfigTime()は、UTCとの時差を秒単位で設定するものでしたが、こちらはタイムゾーン名を使うものです。夏時間関係の情報は環境変数に含まれるので、configTime()とは異なり、daylightOffset_secに相当する引数はありません。

NTPサーバの設定は、configTime()と同じです。

最終的には、環境変数TZを設定して、tzset()を呼び出します。

getLocalTime()

getLocalTime()は、時刻を取得する関数で、時刻の情報をstruct tm形式で取得できます。

getLocalTime()は2つの引数を持っていて、2つ目の引数はミリ秒単位のリトライ時間を指定します。デフォルトでこの値は5000と設定されています。省略可能なので、指定しなくても動作します。取得した時刻情報のうち、tm_yearが、2016より大きいかを判断していて、2016以下であれば、10msずつ待って、再度時刻を取得します。リトライ時間を超えると、その時点で、tm_yearが2016以下でも時刻情報を返すようです。正しい時刻が設定されているのかを判断しているようです。

getLocalTime()は、内部で、time()とlocaltime_r()を利用しているので、わざわざこの関数を利用する必要はないかもしれませんが、この関数はArduino.hに定義されているので、Arduinoを使うときはこちらを使えということなのかもしれません。

スケッチ

NTPサーバから取得した日時を、I2C接続の有機ELキャラクタディスプレイに表示するプログラムを書いてみました。I2C接続の有機ELキャラクタディスプレイの実験はこちらを参照してください。Arduino Dueで利用したものがそのまま使えました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <WiFi.h>
#include "SO2002A_I2C.h"
 
const char *ssid = "your-ssid";
const char *password = "your-password";
 
SO2002A_I2C oled(0x3c);
 
void setup() {
  // put your setup code here, to run once:
  oled.begin(20, 2);
  oled.clear();
  delay(10);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }
 
  configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
}
 
void loop() {
  // put your main code here, to run repeatedly:
  struct tm timeInfo;
  char s[32];
 
  getLocalTime(&timeInfo);
  sprintf(s, " %04d/%02d/%02d %02d:%02d:%02d",
          timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
          timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
  oled.setCursor(0, 0);
  oled.print(s);
 
  delay(10);
}

バージョン

Hardware:ESP-WROOM-32
Software:Arduino 1.8.16/Arduino core for the ESP32

最終更新日

March 21, 2022

inserted by FC2 system