Arduinoで遊ぶページ

Arduinoで遊んだ結果を残すページです。
garretlab
WiFi接続とNTPクライアントの実験(ESP-WROOM-32)

概要

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

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

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

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

実験

WiFi接続

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

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

#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(".");
}

ただ、私の環境では、WiFi.status()がずっと、WL_CONNECTEDにならないという現象が多発しました。

WiFi.begin()の戻り値を調べると、255が返ってくることが多く、255は、WL_NO_SHIELDというシンボルになっていました。一方で、サンプルスケッチのWiFiScanは、常に成功しているようで、このスケッチを眺めてみると、WiFi.begin()は行ってませんが、WiFi.mode(WIFI_STA)でステーションモードにした後、WiFi.disconnect()で接続を切っているようでした。

このため、WiFi.begin()の前に、前述の2つの関数を呼び出してみると、WiFi.begin()が255を返さなくなりました。正しい対処方法なのかはわかりませんが… ご存知の方は教えていただけると助かります。

いつのころからわかりませんが、この部分は改善されたように思えます。このため、下記の操作はなくても大丈夫だと思います。

#include <WiFi.h>
WiFi.mode(WIFI_STA);
WiFi.disconnect();

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
  delay(500);
}

NTPクライアント

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

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を設定しました。

残りはNTPサーバのFQDNで、最大3個まで設定できるようです。メソッド定義を見る限りは、最低一つ設定しておけばよさそうです。

configTzTime()

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

NTPサーバの設定は、configTime()と同じで、最大3個まで設定できます。

getLocalTime()

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

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

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

スケッチ

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

#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.mode(WIFI_STA);
  WiFi.disconnect();

  if (WiFi.begin(ssid, password) != WL_DISCONNECTED) {
    ESP.restart();
  }

  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[20];

  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);
}

バージョン

Arduino 1.8.2/Arduino core for the ESP32/ESP-WROOM-32



メニューを表示するためにJavaScriptを有効にしてください。

Arduinoで遊ぶページ
Copyright © 2017 garretlab all rights reserved.
inserted by FC2 system