2019年7月3日水曜日

ESP32/arduino : WiFi 接続不具合(Arduino core for the ESP32 Ver 1.0.2)

目的:

WEBからの XHR アクセス を繰り返していると ESP32 へ接続ができなくなることがある為、原因/対策を探る。

現象:

WEB から スライダーで値の送信 や、ESP32 の状態のポーリング を XHR を使用して行っていると、途中で ESP32 への接続ができなくなる。
 ( 例えば、 LED調光_WEBからと外付けのボリュームからを切り替えて調光 )  


原因:

原因は不明。

[2019/11/28 追記]
Arduino core for the ESP32 の Ver 1.0.2 の問題と推定。
Ver 1.0.3 では 問題は発生しない模様。

要因等:

短時間の確認しかできていないが、XHR で複数の要求が発生した場合に 接続できなくなる模様。XHR の発行を 1つだけに制限すると 現象が発生しない 頻度が下がる。

また、Arduino core for the ESP32 の Ver 1.0.2 で発生し、Ver 1.0.0, 1.01 では 継続して動作できる。
Arduino core for the ESP32 Ver 1.0.2 の問題と推定。

対応方法:


 (1) Ver 1.0.0 又は 1.01  1.03 以降で コンパイルする。
   但し、自分の環境では、1.0.1 は softAP での接続が できない。
 (2) XHR の発行を 1つに制限。(但し、頻度が下がるのみ)
    "LED調光_WEBからと外付けのボリュームからを切り替えて調光" の HTML での 修正例を以下に示す。

HTML本体
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>
<style>
       #base          {font-size:16pt;text-align:center;width:300px;border:solid 4px #93ff93; }
       #radio_box     {font-size:12pt;float:left ;text-align:left; width:45%; }
       #disp_box      {font-size:12pt;float:right;text-align:left; width:50%; }
       #brightness    {font-size:12pt;text-align:right; }
       #val_box       {font-size:12pt;text-align:center; clear:both ;}
       #ctl_box       {text-align:center; }
       input.radio    {margin-left:8px; width:30px;}
       input.value    {margin-left:8px; width:30px;}
       input.setbutton{margin-left:8px; width:40px;}
       input.slider   {margin-left:8px; width:250px;}
       input.button   {margin:0px 15px; width:100px;}
       </style>
 
<title>Color LED Controller</title></head>
 
<body>
<div id="base">
  <p>LED ON/OFF</p>
  <div id="radio_box">
    <form method="get">
      <input class='radio' type='radio' name='remote' id="rad_lo" value='local' $checked_lo onclick='disp_ctrl(this.value); submit(this.value)'>local<br>
      <input class='radio' type='radio' name='remote' id="rad_rm" value='remote' $checked_rm onclick='disp_ctrl(this.value); submit(this.value)'>remote<br>
    </form>
  </div>
  <div id="disp_box">
      <span> brightness value</span><br>
      <div id="brightness"><output id="o1">$led_brightness</output></div>
  </div>
  <div id="val_box">
    <form method="get">
      <span style="font-size:10pt;"> LED brightness (0-255)</span>
      <input class='value'  type='text' name='led_v' value=$led_brightness id='led_v' disabled>
      <input class='setbutton' type='submit' name='set' id='set' value='SET' disabled>
    </form>
    <form method='get'>
      <input class="slider" type="range" name='led_s' id='led_s' value=$led_brightness min="0" max="255" step="1" disabled
        onchange="setval(this.value);" oninput="setval(this.value)"; onmouseup="submit(this.form)": ontouchend="submit(this.form)">
    </form>
  </div>
  <div id="ctl_box">
    <form method='get'>
      <input class='button' type='submit' name='on' id="on" value='ON' disabled >
      <input class='button' type='submit' name='off' id="off" value='OFF' disabled><br>
    </form>
  </div>
</div>
 
 
<script>
var polling = null ;
var sendbusy = 0 ;
 
function setval(ledval){
  if (sendbusy == 0) {
    sendbusy = 1 ;
    var xhr = new XMLHttpRequest();
    xhr.open("get", "?slid="+ledval );
    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;
        document.getElementById('o1').innerHTML = xhr.response.getElementById("output1").innerHTML;
        setTimeout( function() { sendbusy = 0 ; },100) ;
      }
    }
 
    ntimeout = function(e) {
      xhr.abort() ;
      setTimeout( function() { sendbusy = 0 ; },100) ;
    }
    xhr.send();
  }
}
 
 
function getval(){
  if (sendbusy == 0) {
    sendbusy = 1 ;
    var xhrget = new XMLHttpRequest();
    xhrget.open("get", "?pol" );
    xhrget.setRequestHeader('Cache-Control', 'no-cache');
    xhrget.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT');
    xhrget.responseType = 'document' ;
 
    xhrget.onreadystatechange = function() {
      if( (xhrget.readyState == 4) && (xhrget.status == 200) ) {
        document.getElementById('o1').innerHTML = xhrget.response.getElementById("output1").innerHTML;
        setTimeout( function() { sendbusy = 0 ; },100) ;
      }
    }
 
    ntimeout = function(e) {
      xhrget.abort() ;
      setTimeout( function() { sendbusy = 0 ; },100) ;
    }
 
    xhrget.send();
  }
}
 
function disp_ctrl( radioid ) {
   if(radioid == 'remote') {
      document.getElementById('led_v').disabled = false;
      document.getElementById('set').disabled = false;
      document.getElementById('led_s').disabled = false;
      document.getElementById('on').disabled = false;
      document.getElementById('off').disabled = false;
      clearInterval(polling);
   } else {
      document.getElementById('led_v').disabled = true;
      document.getElementById('set').disabled = true;
      document.getElementById('led_s').disabled = true;
      document.getElementById('on').disabled = true;
      document.getElementById('off').disabled = true;
      polling = setInterval(getval,100) ;
   }
 
}
 
window.onload = function() {
    if(document.getElementById("rad_rm").checked) {
      document.getElementById('led_v').disabled = false;
      document.getElementById('set').disabled = false;
      document.getElementById('led_s').disabled = false;
      document.getElementById('on').disabled = false;
      document.getElementById('off').disabled = false;
      clearInterval(polling);
    } else if(document.getElementById("rad_lo").checked) {
      document.getElementById('led_v').disabled = true;
      document.getElementById('set').disabled = true;
      document.getElementById('led_s').disabled = true;
      document.getElementById('on').disabled = true;
      document.getElementById('off').disabled = true;
      polling = setInterval(getval,100) ;
    }
}
 
</script>
 
</body>
</html>

XHR 送信中のフラグを用意し、送信中は新たな送信を行わない様にする。
XHR は スライダーでの送信と ボリューム値のポーリングの 2種を行っているが、フラグは共通で、常に 1つしか送信しない様にしている。
応答受信後、少しまってから フラグを解除する必要がある。(この例の待ち時間 100mS は暫定値。どの程度待てばよいかは未確認)




0 件のコメント:

コメントを投稿