hiro yamamoto works

マイコンハード、ソフトを作ったりしています。
お家や現場のお困りごと解決に!
内容利用は自己責任でお願いします。

アクセスポイント経由のリモートI/O(送信)wireless IO

2022-04-02 18:05:41 | マイコンソフトウェア

注意

delay(1)でloopしていますが、用途によってはdelayを大きくしたり、<br />入力変化時に送信する方式ても良いかもしれません。<br />専用アクセスポイントと送受信機1台づつという想定ですが、<br />アクセスポイントを複数の送受信機で共有したりすると<br />パケットロスによる問題が発生するかもしれません。

伝送接点数16 単方向(送信側→受信側への伝送のみ)
離れたところにある機器の信号を、電波が届く範囲で
配線無しで受け取ることができる。
アクセスポイント経由ESP32同士で通信します。
主な部品 ESP32開発ボード、I/OエキスパンダMCP23017
手動テストの様子
右側基板のスイッチを押すと接点信号が伝送され、左側基板の
LEDが点灯します。

右側が送信、左側が受信となっています。
スイッチ基板で信号を作ってMCP23017へ 入力しています。
MCP23017のデジタル入力を読み込み、16進数を文字配列
としてUDPで送信
受信した文字配列を16進数へ変換してMCP23017でデジタル
出力します。
Wi-Fi接続試行中GPIO2 LED250mS周期点滅 接続失敗でESP.restart()します。
通信中にアクセスポイントと通信できなくなった時もLED点滅700-300mS周期
ESP.restart()します。
準備
アクセスポイントとスケッチのIPアドレスを設定
アクセスポイントとSSIDとパスワードをあわせる
WiFiUDPClient.inoをベースにした送信側スケッチを紹介しておきます。
#include行の<>は半角に修正必要です

#include <WiFi.h>
#include <WiFiUdp.h>
#include <esp_wifi.h>
#include "Adafruit_MCP23017.h"//16bitIOExpander
// WiFi network name and password:
const char * ssid = "network name";
const char * password = "network password";
//IP address to send UDP data to:
// either use the ip address of the server or
// a network broadcast address
// UDPデータの送信先IPアドレス:
const char * udpAddress = "192.168.1.3";//受信側のIPアドレス
const int udpPort = 1234;//受信側と合わせる
//Are we currently connected?
boolean connected = false;
//The udp library class
WiFiUDP udp;
Adafruit_MCP23017 mcp;
void setup() {
  // Initilize hardware serial:
  Serial.begin(115200);
  Wire.begin();//Wire.setClockのために必要と思う
  Wire.setClock(400000);//Fast-mode400kHzにする時(デフォルトは100kHz記述不要)
  pinMode(2, OUTPUT);//Wi-Fi接続試行中点滅し接続完了で消灯
  mcp.begin(); // use default address 0 MCP23017をデフォルトアドレスで使う
  IPAddress local_IP(192, 168, 1, 4);//送信側(自機)IPアドレス
  IPAddress gateway(192, 168, 1, 1); //
  IPAddress subnet(255, 255, 255, 0);
  WiFi.mode(WIFI_STA);//Wi-Fi子機モート
  WiFi.config(local_IP, gateway, subnet);
  Serial.println("Connecting to WiFi network: " + String(ssid));
  // delete old config
  WiFi.disconnect(true);
  //register event handler イベントハンドラーの登録
  WiFi.onEvent(WiFiEvent);
  //Initiate connection
  WiFi.begin(ssid, password);
  Serial.println("Waiting for WIFI connection...");
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++
    digitalWrite(2, HIGH);
    delay(250);
    digitalWrite(2, LOW);
    delay(250);
    Serial.print(".");
  }
  if (i == 21) { // Wi-Fi接続不能を回避 10秒待ってESPをリスタートする。
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
  Serial.println(WiFi.status() == WL_CONNECTED ? "WiFi connected!" : "Failed!");

  //Connect to the WiFi network
  //connectToWiFi(networkName, networkPswd);
  //udp.begin(udpPort);           // UDP通信開始
  for (int i = 0; i
    mcp.pinMode(i, INPUT);    // mcp23017の全ピンをPULLUPを有効
    mcp.pullUp(i, HIGH);  // turn on a 100K pullup internally
  }
}
void loop() {
  //only send data when connected接続時にのみデータを送信する
  //if (WiFi.status() == WL_CONNECTED) {
  if (connected) {
    //connected がfalseになった時はdelay(5000)後ESP.restart()している
    //Send a packet
    udp.beginPacket(udpAddress, udpPort);
    /*Serial.printf("%05x", mcp.readGPIOAB()); Serial.println();*/
    udp.printf("%05x", mcp.readGPIOAB());//桁を揃えて送るため0埋め
    //udp.printf(" Seconds since boot: %lu", millis() / 1000);//使い方の例
    udp.endPacket();
  }
  //Wait for
  delay(1);
}
/*void connectToWiFi(const char * ssid, const char * pwd) {
  Serial.println("Connecting to WiFi network: " + String(ssid));
  // delete old config
  WiFi.disconnect(true);
  //register event handler
  WiFi.onEvent(WiFiEvent);
  //Initiate connection
  WiFi.begin(ssid, pwd);
  Serial.println("Waiting for WIFI connection...");
  }*/
//wifi event handler
void WiFiEvent(WiFiEvent_t event) {
  switch (event) {
    case SYSTEM_EVENT_STA_GOT_IP:
      //When connected set
      Serial.print("WiFi connected! IP address: ");
      Serial.println(WiFi.localIP());
      Serial.print("ESP Mac Address: "); Serial.println(WiFi.macAddress());
      //initializes the UDP state
      //This initializes the transfer buffer
      udp.begin(WiFi.localIP(), udpPort);
      connected = true;
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      connected = false;
      //connected がfalseになった時はdelay(5000)後ESP.restart()している
      for(int i = 0; i <= 5; i++){
      digitalWrite(2, HIGH);
      delay(700);
      digitalWrite(2, LOW);
      delay(300);
      }
      ESP.restart();
    default: break;
  }
}

スケッチ作例を公開している方々へ感謝します。


ESP32pcntカウンタをテストしてみた

2021-12-09 17:25:00 | マイコンソフトウェア

ESP32でpcntカウンタでパルスをただ数えるだけ。
16bitの符号付きの高速なパルスカウンタです。
もっと詳しい事を知りたい方は
esp32 pcntで検索するとなにか見つかると思います。

桁数が足らないので工夫しています。
素人の書いたコードなので間違いがあるかも知れません。

#include "driver/pcnt.h"

#define PULSE_INPUT_PIN 32 //パルスの入力ピン
#define PULSE_CTRL_PIN 33 //制御ピン
#define PCNT_H_LIM_VAL 32768 //カウンタの上限32768 16bit Counter 65536
#define PCNT_L_LIM_VAL -32768 //カウンタの下限-32768

int16_t count = 0; //カウント数
unsigned long currentCount = 0;
unsigned long previousCount = 0;
unsigned long addCount = 0;

unsigned long previousMillis = 0;
const long interval = 1000;

void setup() {
pcnt_config_t pcnt_config;//設定用の構造体の宣言
pcnt_config.pulse_gpio_num = PULSE_INPUT_PIN;
//pcnt_config.ctrl_gpio_num = PULSE_CTRL_PIN;//制御信号入力GPIO番号
pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
pcnt_config.lctrl_mode = PCNT_MODE_REVERSE;//_REVERSE:invert counter mode(increase -> decrease, decrease -> increase)
pcnt_config.hctrl_mode = PCNT_MODE_KEEP;//_KEEP:won’t change counter mode
// PCNT_MODE_DISABLE:Inhibit counter(counter value will not change in this condition)
pcnt_config.channel = PCNT_CHANNEL_0;
pcnt_config.unit = PCNT_UNIT_0;
//pcnt_config.pos_mode = PCNT_COUNT_INC;//positive edge count mode _INC:Increase counter value
pcnt_config.pos_mode = PCNT_COUNT_DEC;//positive edge count mode _INC:Increase counter value
//pcnt_config.neg_mode = PCNT_COUNT_DEC;//negative edge count mode _DEC:Decrease counter value
pcnt_config.neg_mode = PCNT_COUNT_DIS;//negative edge count mode _DEC:Decrease counter value
pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;

pcnt_unit_config(&pcnt_config); //ユニット初期化
pcnt_counter_pause(PCNT_UNIT_0); //カウンタ一時停止
pcnt_counter_clear(PCNT_UNIT_0); //カウンタ初期化
Serial.begin(115200);
pcnt_counter_resume(PCNT_UNIT_0); //カウント再開
}

void loop() {
pcnt_get_counter_value(PCNT_UNIT_0, &count);

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;

currentCount = count;
if ( currentCount > previousCount) { //以前値より現在値が大きい時
//16bitカウンタ(-32,768〜+32,768)では1日の生産数の途中でオーバーフローするので、
//一定時間毎にカウント値の差を算出して変数へ加算する
//addCount:カウント値を加算するための変数
addCount += currentCount - previousCount; //現在値-以前値をaddCountへ加算
} else if (currentCount < previousCount) { //カウンタオーバーフローで以前値より現在値が小さい
addCount += currentCount - previousCount - 4294934529; //カウンタオーバーフロー時の
}
Serial.println(addCount); //カウント値加算する変数を表示
//if(count > 100) pcnt_counter_clear(PCNT_UNIT_0);
//if(count < -100) pcnt_counter_clear(PCNT_UNIT_0);
Serial.print("Counter value: ");

Serial.println(count); //
previousCount = currentCount;
//delay(50);
}
}


ESP32 HTTPサーバからのダウンロード速度UP(調査中)

2021-10-22 11:15:00 | マイコンソフトウェア

調査継続中ですが

わかったことを載せておきます。

SD.begin(5, SPI, 24000000, "/sd");//24000000=24Mhz デフォルト 4Mhz

SPI.begin(); // start up the SPI bus
SPI.setFrequency(6000000);//6000000=6Mhz デフォルト 1Mhz

デフォルト設定でのテスト結果
平均 230 KB/s
ESP-WROOM-02では
平均 150 KB/s(120〜180 KB/s)

設定変更後
平均 366 KB/s(416〜330 KB/s)
SPIの変更効果は?再検証予定

条件
約8MBファイルをRasPi4(4GB)のLXTerminalでwgetで
ダウンロード


シリンダ移動時間測定器(完)

2021-10-08 08:53:00 | マイコンソフトウェア

間違いを修正しました2023/05</ br>RP2040への移植でトラブル発生!!</ br>最終版スケッチ

センサ1だけを使って往復合計時間を測定するモードを
追加しました。
切換えはクリアスイッチを押しながら電源をいれ、約2秒
後に離すことでできるようにしました。

気になる点
スケッチ実行速度が測定値にどのくらい影響するか
わからない。


通常測定
シリンダセンサをシリンダの両ストロークエンドに取り付け
ONすることを確認します。測定前はどちらかのセンサが
ONしている状態にします。クリアを押してからシリンダを
動作させて測定します。
Push、Pull時間を表示します。


1センサ往復測定
クリアスイッチを押しながら電源をいれ、約2秒
後に離す。
センサ1取り付け位置は通常測定と同様(センサ2有無不問)
測定前はセンサ1がONしている状態にします。
クリアを押してからシリンダを動作させて測定します。
時間を表示します。




ターミナルブロックに自作センサと電源を接続


電源スイッチと表示クリアスイッチ

稚拙スケッチの紹介
注意 コピペ後#includeの後の不等号を半角に直します。
   コメント表現の揺れあります。
/*
millis()約50日でオーバーフローは考慮しない
PORTBは、Arduinoのデジタルピンの8番から13番に対応する。
ポートBをすべて入力
D8(sensor0) アクチェータの出(push)側端
D9(sensor1) アクチェータの戻り(pull)側端
Bit0,1(D8,9)入力はプルアップすること。active LOW*/
#include
#include

LiquidCrystal_PCF8574 lcd(0x27); // set the LCD address to 0x27 for a 16 chars and 2 line display

uint8_t buttonState = 0;
uint8_t lastButtonState = 0;
unsigned long pushStartTime = 0;
unsigned long pushEndTime = 0;
unsigned long pushTime = 0;
unsigned long pullStartTime = 0;
unsigned long pullEndTime = 0;
unsigned long pullTime = 0;
unsigned long PP_Time = 0;
const uint8_t clearPBS = 2;//測定値クリアプッシュスイッチ
bool PPMode = false;

void setup() {
//Serial.begin(115200);
Wire.begin();
//Wire.setClock(100000);//400kHzでも動きそうだが(デフォルトは100kHz 100000)
pinMode(clearPBS, INPUT_PULLUP);//測定値クリアボタンスイッチ
DDRB = B00000000; // ポートBをすべて入力
//
//電源投入時に測定値クリアボタンスイッチHIGHなら従来通りPush-Pull測定モード
//LOWだったら、往復測定モードとする。
lcd.begin(16, 2); //initialize the lcd *修正
lcd.setBacklight(1);//1でも255でも明るさは変化しません
if (digitalRead(clearPBS) == LOW) {
//フラグを立てる
PPMode = true;
//Push-Pull Modeのlcd初期表示
//lcd.begin(16, 2);//間違だが動いてたbegin()をsetBacklight(1)の前に移動 *修正
lcd.clear();//
lcd.setCursor(0, 0); lcd.print("Push-Pull(Sen1)");
lcd.setCursor(5, 1); lcd.print(PP_Time);
lcd.setCursor(14, 1); lcd.print("mS");

} else {

lcd.begin(16, 2); // initialize the lcd
lcd.clear();//
lcd.setCursor(0, 0); lcd.print("Push ");
lcd.setCursor(5, 0); lcd.print(pushTime);
lcd.setCursor(14, 0); lcd.print("mS");
lcd.setCursor(0, 1); lcd.print("Pull ");
lcd.setCursor(5, 1); lcd.print(pullTime);
lcd.setCursor(14, 1); lcd.print("mS");
}
}

void loop() {

/*B PORT入力ピンレジスタの下位2Bitだけ(D8,D9)使う
入力との論理積を取ることで必要以外bitの影響を受けないようにする & 0x03 00000011
*/
if (PPMode == false) {
buttonState = PINB & 0x03; // D8:PortB Bit0 D9 Bit1 磁気検出ON = L

//D9,D8どちらかがLOWになったときから始める
if (buttonState != lastButtonState) {//以前と現在が違う時

/*D9pull端戻り限ONの時LOW,D8push端出限ONの時LOW PORT Bのbit0がD8,bit1がD9*/
/*現在D9H,D8H(移動中) && 以前D9L(pull端戻り限ON),D8H*/
if ((buttonState == 0x03) && (lastButtonState == 0x01)) {
pushStartTime = millis(); //戻り限から出発した時間を変数に記録
/*現在D9H,D8L(push端出限ON) && 以前D9H,D8H(移動中)*/
} else if ((buttonState == 0x02) && (lastButtonState == 0x03)) {
/*出限到着時間 - 戻り限出発時間 = 戻り〜出移動時間 変数へ記録*/
pushEndTime = millis();
pushTime = pushEndTime - pushStartTime;//移動中H,Hから到着H,L(D8push端出限)
lcd.setCursor(5, 0); lcd.print(" ");
lcd.setCursor(5, 0); lcd.print(pushTime);
/*現在D9H,D8H(出限から戻り限へ移動中) && 以前D9H(pull端戻り限OFF)D8L(push端出限ON)*/
} else if ((buttonState == 0x03) && (lastButtonState == 0x02)) {
pullStartTime = millis();//出限を出発した時間を変数に記録
/*現在D9L(pull端戻り限ON),D8H(push端出限OFF) && 以前D9H,D8H(出限から戻り限へ移動中)*/
} else if ((buttonState == 0x01) && (lastButtonState == 0x03)) {
/*戻り限到着時間(現在時間) - 出限出発時間 = 出〜戻り移動時間 変数へ記録*/
pullEndTime = millis();
pullTime = pullEndTime - pullStartTime;
lcd.setCursor(5, 1); lcd.print(" ");
lcd.setCursor(5, 1); lcd.print(pullTime);
}
/*clearBPSが押されて変数は0になっても、millis()カウントは電源投入から進んでいるので
clearBPS使い方 sensor1,2のいずれかがONする位置で押して下さい。sensor1,2両方がOFF状態で
押すと、アクチェータを移動してsensor1,2のいずれかがONした時に、数値が表示されてしまいます。
再度clearBPを押すと数値がクリアされ測定できます。 */
}
lastButtonState = buttonState;
if (digitalRead(clearPBS) == LOW) {//20210904>
buttonState = 0;
lastButtonState = 0;
pushStartTime = 0;
pushEndTime = 0;
pushTime = 0;
pullStartTime = 0;
pullEndTime = 0;
pullTime = 0;
PP_Time = 0;
lcd.clear();//LCDに表示されている情報を消す
delay(100);
lcd.setCursor(0, 0); lcd.print("Push ");
lcd.setCursor(5, 0); lcd.print(pushTime);
lcd.setCursor(14, 0); lcd.print("mS");
lcd.setCursor(0, 1); lcd.print("Pull ");
lcd.setCursor(5, 1); lcd.print(pullTime);
lcd.setCursor(14, 1); lcd.print("mS");
}
} else {
buttonState = PINB & 0x03; // D8:PortB Bit0 D9 Bit1 磁気検出ON = L

//D9,D8どちらかがLOWになったときから始める
if (buttonState != lastButtonState) {//以前と現在が違う時

/*D9pull端戻り限ONの時LOW,D8push端出限ONの時LOW PORT Bのbit0がD8,bit1がD9*/
/*現在D9H,D8H(移動中) && 以前D9L(pull端戻り限ON),D8H*/
if ((buttonState == 0x03) && (lastButtonState == 0x01)) {
pushStartTime = millis(); //戻り限から出発した時間を変数に記録

} else if ((buttonState == 0x01) && (lastButtonState == 0x03)) {
/*戻り限到着時間(現在時間) - 出限出発時間 = 出〜戻り移動時間 変数へ記録*/
pullEndTime = millis();
PP_Time = pullEndTime - pushStartTime;//1センサで往復時間を測定
lcd.setCursor(5, 1); lcd.print(" ");
lcd.setCursor(5, 1); lcd.print(PP_Time);
}
/*clearBPSが押されて変数は0になっても、millis()カウントは電源投入から進んでいるので
clearBPS使い方 sensor1,2のいずれかがONする位置で押して下さい。sensor1,2両方がOFF状態で
押すと、アクチェータを移動してsensor1,2のいずれかがONした時に、数値が表示されてしまいます。
再度clearBPを押すと数値がクリアされ測定できます。*/
}
lastButtonState = buttonState;
if (digitalRead(clearPBS) == LOW) {
buttonState = 0;
lastButtonState = 0;
pushStartTime = 0;
pushEndTime = 0;
pushTime = 0;
pullStartTime = 0;
pullEndTime = 0;
pullTime = 0;
PP_Time = 0;
lcd.clear();//LCDに表示されている情報を消す
delay(100);
lcd.setCursor(0, 0); lcd.print("Push-Pull(Sen1)");
lcd.setCursor(5, 1); lcd.print(PP_Time);
lcd.setCursor(14, 1); lcd.print("mS");
}
} //PPMode == true
}


NTPで取得した時刻をRTCへセットする(ESP32)

2021-06-28 14:09:00 | マイコンソフトウェア

ESP-WROOM-32でやってみました。
調査結果により書き直したので、記事タイトルと内容に
ズレがあります。

調べてわかったこと

起動時のNTP時刻取得後は、1時間毎のgetLocalTime()時に
NTP時刻同期していました。
よって、提供される時刻の精度は問題ないと思われます。
つまり、NTP又はネットワーク内タイムサーバに接続できる
環境なら、RTCモジュール追加の必要はない?
かもしれません。タイムサーバ接続不可能な環境で使うなら
RTCは有ったほうが良いと思います。

getLocalTime()
ローカル時刻を取得する。
失敗時10ms毎に取得繰返し5000mS(デフォルト)でタイムアウト
取得成功でtrue返す。失敗でfalse返す。
例 getLocalTime(&timeinfo, 5000)

getLocalTime()後のsntp_get_sync_statusをシリアルモニタ
表示してみた。

前半 10分間隔 後半 11分間隔でgetLocalTime()してます。
約60分毎に sntp_get_sync_status = COMPLETED とあります。

スケッチ例 「SimpleTime」で実験中
(ESP32 Dev Module用のスケッチ例 ESP32→TIME→SimpleTime)

コメントとテストを追記したスケッチ(手直し中)
WiFi.disconnect(true);とWiFi.mode(WIFI_OFF);の2行は
接続を継続するため無効にしました。
include行は < から < へ修正して下さい。
#include <WiFi.h>
#include "time.h"

const char* ssid = "my-ssid";
const char* password = "my-password";

const char* ntpServer = "pool.ntp.org"; // NTPサーバ,IP Address指定できるか?
const long gmtOffset_sec = 9 * 3600; // 時差を秒で設定・・・9時間
const int daylightOffset_sec = 0; // サマータイム設定・・・0

void printLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo, 5000)) {
// コメント追記 タイムアウトデフォルト5000mS
Serial.println("Failed to obtain time");
return;
}
//追記 NTP同期確認のため ・・・COMPLETEDで同期完了と思う
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) {
Serial.println("sntp_get_sync_status = COMPLETED");
Serial.println(&timeinfo, "%A, %B %m %d %Y %H:%M:%S");
// コメント追記 A 曜日英語表記,B 月英語表記,m 月の数字,d 日,Y 年,H時:M分:S秒
}
}
void setup() {
Serial.begin(115200);

//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");

//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();

//disconnect WiFi as it's no longer needed
//WiFi.disconnect(true); //無効にしました
//WiFi.mode(WIFI_OFF); // 無効にしました
}

void loop() {
//delay(1000); // 無効にしました
printLocalTime();
delay(660000); // 追記しました
}

(スケッチ例を公開している方々に感謝します。)

RTC時刻合わせするスケッチもよかったらどうぞ
#include <WiFi.h>
#include "time.h"
#include <Wire.h>
#include <RTClib.h>

const char* ssid = "my-ssid";
const char* password = "my-password";

const char* ntpServer = "pool.ntp.org"; // pool.ntp.org
const long gmtOffset_sec = 9 * 3600; // 時差を秒で設定・・・9時間
const int daylightOffset_sec = 0; // サマータイム設定・・・0

unsigned long interval_t = 60000 * 61 * 1; // 60000(mS)*60*1=1h 60000(1min)
unsigned long previousMillis_t = 0;
unsigned long previous_t = 0;

char date_ymdhms[21]; // yyyy/mm/dd,hh:mm:ssn0

RTC_DS3231 rtc;//select use RTC DS3231

void printLocalTime() {
//sntp_get_sync_status()は時間同期のステータスを取得します。
//更新が完了すると、ステータスはSNTP_SYNC_STATUS_COMPLETEDとして返されます。
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return;
}
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) {
Serial.println("sntp_get_sync_status = COMPLETED");
Serial.println(&timeinfo, "%A, %B %m %d %Y %H:%M:%S");
}
}

void setup() {
Serial.begin(115200);
Wire.begin();

//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");

//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime(); // NTP時刻取得、同期ステータス表示、システム時刻表示

if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
}
// RTCが電源を失った時(電池切れ)getLocalTime()して取得成功の場合取得時刻をRTCにセットし、
// 失敗の場合コンパイル時刻をRTCにセットする。
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
struct tm timeInfo;
if (!getLocalTime(&timeInfo)) {
/* 失敗でメッセージを表示しコンパイル時刻をRTCへセット 取得成功で取得時刻をRTCへセット */
Serial.println("Failed to obtain time Set to compile time"); // 時間の取得に失敗しましたコンパイル時刻をセットします
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // コンパイル日時を仮設定
DateTime now = rtc.now();
sprintf(date_ymdhms, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
Serial.println(date_ymdhms);
} else {
rtc.adjust(DateTime(timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec));
//tm_year:1900年からの年数 tm_mon:1月からの月数
Serial.println("adjust RTC !!");
DateTime now = rtc.now();
sprintf(date_ymdhms, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
Serial.println(date_ymdhms);
}
}
//disconnect WiFi as it's no longer needed
//WiFi.disconnect(true);
//WiFi.mode(WIFI_OFF);
}
void loop() {
// 定期的にgetLocalTime()して同期できたらRTCをセットする
unsigned long currentMillis_t = millis();
if (currentMillis_t - previousMillis_t >= interval_t) { //interval_t 61分はOK60分はNG
previousMillis_t = currentMillis_t;
struct tm timeInfo;
if (getLocalTime(&timeInfo)) {
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) {
rtc.adjust(DateTime(timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec));
//tm_year:1900年からの年数 tm_mon:1月からの月数
Serial.println("adjust RTC !!");
} // else { Serial.println("NOT COMPLET"); }
} else {
Serial.println("Failed to obtain time");
}
}
//delay(1000);
// 10分毎にRTC時刻を取得して表示する。
unsigned long interval = 60000 * 10 *1; // 60000(1min)
unsigned long current_t = millis();
if (current_t - previous_t >= interval) {
previous_t = current_t;
//printLocalTime(); // このスケッチオリジナルの関数
DateTime now = rtc.now();
sprintf(date_ymdhms, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
Serial.println(date_ymdhms);
}
}

(スケッチ例を公開している方々に感謝します。)
無保証自己責任でよろしくおねがいします。