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 での 修正例を以下に示す。

<!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 件のコメント:

コメントを投稿