LED 調光を、SPIFFS を使用して HTML を別ファイルにする。
方法:
"ESP32/arduino : SPIFFS アップローダーを使用する "に従って HTML を別ファイルにする。
変数部分(
LEDの明るさ :led_brightness) は、送信前に変数名の文字列を数値に置換して送信する。2019/06/26追加XHR を多重で発行すると通信がハングアップする事があるようなので、レスポンスが返るまで発行しない様に修正。
→ 本問題は、Arduino core for the ESP32 の Ver 1.0.2 の問題と思われる。
Ver.1.0.3 以降では問題無い。 例: (スケッチ、HTML、レスポンス用HTML )/*
* WiFi LED ON/OFF TEST
* PWM Control
* slider control2
*/
#include <WiFi.h>
#include "FS.h"
#include <SPIFFS.h>
#define DEBUG
const char* ssid = "hogehoge";
const char* password = "hogehogepaswd";
IPAddress ip(192, 168, 1, 32); // for fixed IP Address
IPAddress gateway(192,168, 1, 1); //
IPAddress subnet(255, 255, 255, 0); //
IPAddress DNS(192, 168, 1, 90); //
WiFiServer server(80);
String html_1;
String resp_1;
byte led_brightness = 0 ;
void setup()
{
Serial.begin(115200);
SPIFFS.begin(); //SPIFFSを開始
pinMode(2, OUTPUT); // set the LED pin mode
WiFi.config(ip, gateway, subnet, DNS); // Set fixed IP address
delay(10);
// We start by connecting to a WiFi network -----------------------------
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
//index.htmlファイルの読み込み
File index1 = SPIFFS.open("/test_pwm_slid.html", "r");
if(!index1)
Serial.println("file open failed");
else{
html_1 = index1.readString(); //index.htmlをstringで読み込み
index1.close(); //ファイルを閉じる
}
//resp.htmlファイルの読み込み
File index2 = SPIFFS.open("/resp_slid.html", "r");
if(!index2)
Serial.println("file open failed");
else{
resp_1 = index2.readString(); //index.htmlをstringで読み込み
index2.close(); //ファイルを閉じる
}
// for LED PWM Control ---------------------------------------------------
ledcSetup(0, 5000, 13); // setup channel 0 with frequency 5000 Hz, 13 bit precission for LEDC timer
ledcAttachPin(2,0); // attach pin 2 to channel 0
ledcWrite(0, 0); // initialize channel 0 to off
}
void loop(){
WiFiClient client = server.available(); // listen for incoming clients
int pos ;
int val ;
int xhr ;
String cmd = "" ;
String htmlwk = "" ;
String respwk = "" ;
if (client) { // if you get a client,
# ifdef DEBUG
Serial.println("***** Client access start *****"); // print a message out the serial port
#endif
xhr = 0 ;
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
String line = client.readStringUntil('\n'); // Get Line data until '\n'
# ifdef DEBUG
Serial.println(line);
#endif
if ((pos= line.indexOf("GET /?slid")) != -1) {
pos += 11 ;
while((line.charAt(pos) >='0') & (line.charAt(pos) <='9')) {
cmd += line.charAt(pos++) ;
}
val = cmd.toInt() ;
if (val>256) val = 255 ;
led_brightness = (byte)val ;
xhr=1;
# ifdef DEBUG
Serial.print("led_brightness : ");
Serial.println(led_brightness) ;
#endif
}
if ((pos= line.indexOf("GET /?led_v")) != -1) {
pos += 12 ;
while((line.charAt(pos) >='0') & (line.charAt(pos) <='9')) {
cmd += line.charAt(pos++) ;
}
val = cmd.toInt() ;
if (val>256) val = 255 ;
led_brightness = (byte)val ;
# ifdef DEBUG
Serial.print("led_brightness : ");
Serial.println(led_brightness) ;
#endif
}
if ((pos=line.indexOf("GET /?on")) != -1) { // Client request was "GET /?on"
led_brightness += 1 ;
# ifdef DEBUG
Serial.print("led_brightness : ");
Serial.println(led_brightness);
#endif
}
if ((pos=line.indexOf("GET /?off")) != -1) { // Client request was "GET /?off"
led_brightness = 0 ;
# ifdef DEBUG
Serial.print("led_brightness : ");
Serial.println(led_brightness);
#endif
}
ledcWrite(0, 8191*led_brightness/255) ; // set PWM value to channel#0
if (line.length() == 1 && line[0] == '\r'){ // end of HTTP request
if (xhr == 0) {
htmlwk = html_1 ;
htmlwk.replace("$led_brightness",String(led_brightness)) ;
send_html(client,htmlwk) ; // send response to client
} else {
respwk = resp_1 ;
respwk.replace("$led_brightness",String(led_brightness)) ;
send_html(client,respwk) ; // send response to client
}
break; // break while loop
}
}
}
delay(1); // give the web browser time to receive the data
// close the connection:
client.stop();
# ifdef DEBUG
Serial.println("Client Disconnected.");
Serial.println("--------------------------------------------------");
#endif
}
}
// ------------------------------------------------------------------
void send_html(WiFiClient client, String html ) {
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
client.print(html) ;
# ifdef DEBUG
Serial.println( " --- send html --- ");
#endif
}
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>
<style>input.button {margin:8px;width:100px;}
input.button2 {margin-left:8px; width:40px;}
input.text {margin-left:8px; width:25px;}
input.slid {width:230px;}
div {font-size:16pt;text-align:center;width:250px;border:solid 4px #93ff93;}
</style>
<title>Color LED Controller</title></head>
<body>
<div><p>LED ON/OFF</p>
<form method='get' style='text-align:left' >
<span style='padding-left:15pt; font-size:8pt ;text-align:left'> LED brightness (0-255)</span>
<input class='text' type='text' name='led_v' id='led_v' value=$led_brightness >
<input class='button2' type='submit' name='set' value='SET'>
</form>
<form name='slidform' method='get' style='text-align:left'>
<input class='slid' type='range' name='led_s' value=$led_brightness min='80' max='255' step='1' onchange='setval(this.value)' oninput='setval(this.value)' >
</form>
<form method='get'>
<input class='button' type='submit' name='on' value='UP'><input class='button' type='submit' name='off' value='OFF'><br>
</form>
</div>
<script>
var xhr_busy = 0 ;
function setval(ledval){
if (xhr_busy == 0) {
xhr_busy = 1 ;
var xhr = new XMLHttpRequest();
xhr.open('get', '?slid='+ledval );
xhr.timeout = 1000 ;
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT');
xhr.responseType = 'document' ;
xhr.onreadystatechange = function() {
if( (xhr.readyState == 4) && (xhr.status == 200) ) {
document.getElementById('led_v').value = xhr.response.getElementById('output1').innerHTML;
xhr_busy = 0 ;
}
}
xhr.ontimeout = function(e) {
xhr.abort() ;
xhr_busy = 0 ;
}
xhr.send();
}
}
</script>
</body>
</html>
<!DOCTYPE html><html lang='ja'>
<head> <title>Color LED Controller</title></head>
<html> <body>
<output id='output1'>$led_brightness</output>
</body> </html>
以下、変更点の覚書など。
--- < スケッチ > ---
( 行# 8,9 )
SPIFFS を使用するための include。
( 行# 23,24 )
HTML本体,レスポンス用HTML を格納する String 変数。
( 行# 30)
SPIFFS ファイルシステムのマウントを行う。
( 行# 55~62)
HTML本体を読み込み、String 変数に格納。
( 行# 64~71)
レスポンス用HTMLを読み込み、String 変数に格納。
( 行# 85,86 )
変数部分を値に置き換える為の ワーク用 HTML本体,レスポンス用HTML を格納する String 変数。
( 行# 144~146 )
HTML本体を送信する。
フラッシュメモリから読みだした HTML をワーク用の String 変数にコピーした後、変数部分(値を変えたい部分) を値に置き換え、送信する。
( 行# 148~150 )
レスポンス用 HTMLを送信する。
フラッシュメモリから読みだした HTML をワーク用の String 変数にコピーした後、変数部分(値を変えたい部分) を値に置き換え、送信する。
( 行# 168~178 )
HTML送信用関数。
--- < HTML本体 > ---
( 行# 14,19 )
変数部分は、$付きの名前にした。
2019/06/26追加 ( 行# 30,33,34,45,50 )XHR 発行中を示すフラグ xhr_busy を準備。
XHR 発行中は '1' にして 多重で発行しない様にする。
--- < レスポンス用HTML > --- ( 行# 4 )
変数部分は、$付きの名前にした。
過去のプログラムは動作確認ができて、内容も順番に確認してきました。
返信削除このプログラムで悩んでます。
アップロードできているはずです。Hard resetting via RTS pin...
thlmのファイル名は、index.htmlとresp.htmlで良いですか?WiFi connected.
+IPaddressの表示は、OK
ブラウザー表示しません。接続エラーのメッセージも無。
F5の更新で
GET /favicon.ico HTTP/1.1
Host: 192.168.0.123
Connection: keep-alive
Pragma: no-cache
のメッセージの表示?
お助けお願いしたいです。よろしくお願いします。
ESP32をもう少し、勉強していきます。
参考にして頂き、ありがとうございます。
削除HTML のファイル名は、test_pwm_slid.html と resp_slid.html になります。
スケッチ本体の 56行目 と 65行目 でファイル名を指定しています。
2つの HTML のファイルは "DATA" ディレクトリ の下に格納します。
ファイル名 もしくは スケッチ本体の記述を変更して 試してください。
よろしくお願いいたします。
早い回答ありがとうございます。返答がいただけるだけでも助かるのに・・・
削除ファイル名の件、確認実行します。
(現在までのプログラムはすべて動いているので大丈夫と思います。)
よく、プログラムを見なければいけませんね!
コメント記載か何かで、思い込んでいました。
「まず、動かして!」「次は理解」の考えではどこかで詰まりますね!
現在、「スマホからIPアドレス等のWiFi設定を行う」を勉強中です。
全てが目からウロコです。
passwordの間違いでなかなか動きませんでしたが、(1,l)お恥ずかしい!
それで現在、何度かの再接続でAPモードに戻るを追加してみようと試行中です。
俺のレベルで行けるかな?
問題がも山の様に有りますが、一つづつ解決していきたいと思ってます。
カベを乗り越えれない場合は。また御指南をお願いしたいです。
私に判る事であれば、答えたいと思います。(と言っても私も素人ですし、すぐには応答出来ない事もあるかと思いますが、、)
削除問題等ありましたら、投稿ください。
温かいコメントありがとうございます。
返信削除よろしくお願いします。
「スマホからIPアドレス等のWiFi設定を行う」には、ほど遠く
「 LED調光_WEBからと外付けのボリュームからを切り替えて調光」
のお勉強中ですが、"GET /?pol"は、何の動作で?
THLMも少しがじった程度で、scripの復習を行おうと思っています。
local 時、定期的にgetval() を実行(109,128行目)し、XHR で GET /?pol を発行して led_brightness (ボリュームの値) を取得します。
削除返信ありがとうございます。
返信削除XHRは、THMLのscriptですね!復習中です。
「接続不具合(Arduino core for the ESP32 Ver 1.0.2)」でHTMLも書き換えました。
ボリュームの習得は100msで割り込み。ローカル判断で演算。割り込み可。でわないですか?
「get/polを発行してVR取得」????凡人には理解できるようにお願いします。
あと、resp_slidのhtmlの勉強中です。が?、
get/?pol の発行が多くてシリアルモニターの更新が早すぎて、
確認が大変でしたのでお聞きした次第です。
質問ばかりですみません。頑張って理解していますが自分の技量では?見捨てないでください。
ボリュームの値の取得は理解されている通り、100mS毎の割込み(Ticker) で取得し、
返信削除演算(0~255 の範囲に変換)し、変数(led_brightness) に保持します。
( Local 時は、ボリュームの値を 一度'0'にした後でないと更新しません )
XHR(XMLHttpRequest)は ブラウザのボリューム値(brightbess value) を更新するために使用します。 (ESP32側からこの値のみを更新することができない為)
ブラウザのボリューム値更新は、
ブラウザ側:
local 時、Javascript で定期的(100mS毎)に getval を実行。
(setInterval(getval,100))
getval は XHR で GET /?pol を発行し、レスポンスを待つ。
ESP32:
GET /?pol 受信により、レスポンス用HTML を使用して led_brightness の値を
返す。
ブラウザ側:
レスポンスで帰ってきた値 (led_brightness) を brightness value (id:o1) に
セットする。
という流れになります。
( Local 時、ブラウザ側から100mS毎に GET /?pol が発行され、ボリューム値を応答する。)
以上で判るでしょうか?
XMLHttpRequest については、いろいろ解説されているサイトがありますので、調べてください。
忙しいと思われる中、くわしわかるように返答を頂いて助かります。
削除出先なので、帰って良く理解します。
鉄道模型をやられる方なのですね。
自分も友達の手伝いをしているときに、この世界にのめり込みました。
初めは、配線の手伝いだけでしたが、順番に制御などを。踏切などから作りだしました。PICで行っていたのが懐かしいです。
ESP32は、PCやモバイルで制御や確認ができるので、PIC環境を離れESP32に移行中です。
周りには、相談出来る人もおらず独学でやっています。
なので、返答を頂けて本当に嬉しくおもっています。
話しがそれますたが、これからもよろしくお願いします。
現在、WiFiモード切替など勉強中です。