後々のメンテナンスを考え、各種設定パラメータをプログラム本体から分離して外部ファイルからスケッチに読み込む形に改造した。JSON形式の外部ファイル(config.json)を作成し、そこへ納める形にしてある。ついでに新規のパラメータ srv_deg0、srv_deg1、srv_defo を追加したが、各々下記(※部)の用途となっている。サーボ定位は、ポイントそれぞれの定位をL側にするかR側にするかの指定用である。これを使い、システム起動時に初期状態として、サーボ及びリレーを定位側に切り替えておくようにした。
[ config.json ]
{ "data":[
{ "pnt_number":1,"rel_pin":26,"srv_pin":16,"srv_deg0":0,"srv_deg1":0,"srv_defo":0 },
{ "pnt_number":2,"rel_pin":27,"srv_pin":17,"srv_deg0":0,"srv_deg1":0,"srv_defo":1 },
{ "pnt_number":3,"rel_pin":32,"srv_pin":18,"srv_deg0":0,"srv_deg1":0,"srv_defo":0 }
]}
※ pnt_number=ポイント番号, rel_pin=リレーピン番号, srv_pin=サーボピン番号, srv_deg0=サーボL側補正, srv_deg1=サーボR側補正, srv_defo=サーボ定位
[ スケッチ:Esp32_AsyncWebServer_OTA2 ]
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <ArduinoJson.h>
// for Servo
#include <ESP32Servo.h>
#include <ServoEasing.hpp>
// for OTA
#include <ESPmDNS.h>
#include <NetworkUdp.h>
#include <ArduinoOTA.h>
// SPIFFS
#include "FS.h"
const char ssid[] = "********";
const char pass[] = "********";
const IPAddress ip(192,168,3,17);
const IPAddress gateway(192,168,1,1); // デフォルトゲートウェイ
const IPAddress subnet(255,255,255,0);
const int pnt_max = 8;
int rel_pins[pnt_max]; // リレーパラメータ用配列
int srv_pins[pnt_max]; // サーボパラメータ用配列
int srv_deg0[pnt_max]; // サーボL側微調整用配列
int srv_deg1[pnt_max]; // サーボR側微調整用配列
int srv_defo[pnt_max]; // サーボデフォ位置用配列
const int srv_min = 1450;
const int srv_max = 2400;
const int srv_deg = 150;
const int srv_sec = 4000;
const uint32_t BUF_SIZE = 255; // SPIFFS
String file_name = "/config.json"; // ファイル名の指定
String readStr;
AsyncWebServer server(80); // ポート設定
// Jsonオブジェクトの初期化
StaticJsonDocument<512> doc;
// ブラウザから受信する変数
uint8_t pnt_number; // ポイント配置番号
uint8_t pnt_status; // ポイント状態制御(0=L / 1=R)
// for Servo
ServoEasing servo[pnt_max]; // オブジェクト配列定義
void setup() {
Serial.begin(115200);
Serial.println("***** SRR Point System Start *****");
// SPIFFSのセットアップ
if(!SPIFFS.begin(true)){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
WiFi.config(ip, gateway, subnet);
WiFi.mode(WIFI_STA); // for OTA
WiFi.begin (ssid, pass);
// for OTA
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_SPIFFS
type = "filesystem";
}
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) { Serial.println("Auth Failed"); }
else if (error == OTA_BEGIN_ERROR) { Serial.println("Begin Failed"); }
else if (error == OTA_CONNECT_ERROR) { Serial.println("Connect Failed"); }
else if (error == OTA_RECEIVE_ERROR) { Serial.println("Receive Failed"); }
else if (error == OTA_END_ERROR) { Serial.println("End Failed"); }
});
ArduinoOTA.begin();
// 各種情報を表示
Serial.print("SSID: ");
Serial.println(ssid);
Serial.print("AP IP address: ");
Serial.println(ip);
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");
server.onNotFound(notFound);
// Pointの制御変数の変更リクエスト
server.on(
"/post_test",
HTTP_POST,
[](AsyncWebServerRequest * request){},
NULL,
[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
String resjson = "";
for (size_t i = 0; i < len; i++) {
//Serial.write(data[i]);
resjson.concat(char(data[i]));
}
Serial.println(resjson);
DeserializationError error = deserializeJson(doc, resjson);
if(error){
Serial.println("deserializeJson() faild");
request->send(400);
}
else{
pnt_number = doc["PNT_NUMBER"];
pnt_status = doc["PNT_STATUS"];
request->send(200);
}
});
pnt_number = 0;
pnt_status = 0;
// Read Config
Serial.println("Config read.");
if (SPIFFS.exists(file_name)) { // ファイルが存在すれば
File fr = SPIFFS.open(file_name.c_str(), "r"); //データ読み込み
readStr = fr.readStringUntil('\0'); //EOFまで読み出し
fr.close();
} else {
Serial.println("Error : File not found.");
}
StaticJsonDocument<512> docjson;
DeserializationError error = deserializeJson(docjson, readStr);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
else {
for (JsonObject data_item : docjson["data"].as()) {
int data_item_pnt_number = data_item["pnt_number"];
rel_pins[data_item_pnt_number] = data_item["rel_pin"];
srv_pins[data_item_pnt_number] = data_item["srv_pin"];
srv_deg0[data_item_pnt_number] = data_item["srv_deg0"];
srv_deg1[data_item_pnt_number] = data_item["srv_deg1"];
srv_defo[data_item_pnt_number] = data_item["srv_defo"];
}
}
// for Servo
Serial.println("Initialize start.");
for(int i =1; i < pnt_max; i++) {
pinMode(rel_pins[i], OUTPUT); // pinを出力設定に
pinMode(srv_pins[i], OUTPUT); // pinを出力設定に
servo[i].attach(srv_pins[i], srv_min, srv_max); // attach(int pin, int min, int max)
servoGo(i, srv_defo[i], 200); // initialize
relayGo(i, srv_defo[i]); // initialize
}
setEasingTypeForAllServos(EASE_CUBIC_IN_OUT); // EASE_LINEAR is default
// サーバースタート
Serial.println("Server start.");
server.begin();
Serial.println("***** SRR Point System Ready *****");
} // End setup()
void loop() {
ArduinoOTA.handle(); // for OTA
if(pnt_number > 0) {
// Servo
if (srv_pins[pnt_number] > 0) { servoGo(pnt_number, pnt_status, srv_sec); }
// Relay
if (rel_pins[pnt_number] > 0) { relayGo(pnt_number, pnt_status); }
}
pnt_number = 0;
delay(10);
} // End loop()
void servoGo(int pnt_number, int pnt_status, int srv_sec) {
int deg = 0;
if (pnt_status == 0) { deg = srv_deg0[pnt_number]; }
else { deg = srv_deg + srv_deg1[pnt_number]; }
Serial.println(String(pnt_number) + " : deg=" + String(deg));
servo[pnt_number].setEaseToD(deg, srv_sec);
synchronizeAllServosStartAndWaitForAllServosToStop();
}
void relayGo(int pnt_number, int pnt_status) {
if(pnt_status == 0){
digitalWrite(rel_pins[pnt_number], LOW);
} else {
digitalWrite(rel_pins[pnt_number], HIGH);
}
}
void notFound(AsyncWebServerRequest *request){
if (request->method() == HTTP_OPTIONS){
request->send(200);
}else{
request->send(404);
}
}