2019年4月16日火曜日

ESP32/arduino:MCP23017の使い方

目的:
MCP23017 の使い方(I2C接続) について、簡単にまとめておく。
また、各レジスタアクセス, レジスタダンプの スケッチを作成する。

接続回路:

  接続は、以前のI2Cの使用方法確認 の時と同じ。

2019/04/20 update :
  SCK,SDA を 3.3KΩで プルアップ追加
I2C プルアップについて: (2019/04/20 追記)
スケッチで wire.begin() を実行することで IO21(SDA),IO22(SCL) が弱プルアップ(30KΩ程度 ?) されるが、このプルアップでは動作不安定。(アクセスの繰り返しで誤動作発生。)
この為、外部プルアップ(3.3KΩ) を追加した。

使用方法:
 主な内容は、以下のとおり。
  1. スレーブアドレスは、0x2X。
    Pin A2,A1,A0 の設定で下位アドレスが決定。
    上回路図の場合、A2='L', A1='L', A1='H' で、0x21。
  2. 初期のレジスタアドレスマッピングは、IOCON.BANK=0 で、A/Bレジスタが連続アドレスになっている 。
  3. 各レジスタの意味は、下表のとおり。
  4. GPIO の使用は、IODIR, IPOL, GPPU を設定し、GPIO の ライト/リードで行う。
  5. 割込みは、GPINTEN,INTCON,DEFVAL を設定し、INTF, INTCAP を確認する。
  6. INTF は、INTCAP 又は GPIO のリードでクリアされる。
レジスタ一覧

レジスタ名 アドレス R/W 初期値 内容
IODIRA 0x00 R/W 0xFF I/O 方向。 0: 出力  1:入力
IODIRB 0x01 R/W 0xFF  
IPOLA 0x02 R/W 0x00 I/O 極性。 0:  0が'L'  1が'H' ,    1:  1が'L'  0 が 'H' 
IPOLB 0x03 R/W 0x00  
GPINTENA 0x04 R/W 0x00 状態変化割り込み 0:無効 1:有効
GPINTENB 0x05 R/W 0x00  
DEFVALA 0x06 R/W 0x00 状態変化割り込みの規定値。
DEFVALB 0x07 R/W 0x00 この値と逆になったら割り込み発生
INTCONA 0x08 R/W 0x00 状態変化割り込みの比較値
INTCONB 0x09 R/W 0x00 0: 前の値と比較  1:DEFV の値と比較
IOCON 0x0A R/W 0x00 コンフィグレーションレジスタ。欄外参照
IOCON 0x0B R/W 0x00 (アドレス a と b は同じレジスタ)
GPPUA 0x0C R/W 0x00 プルアップ制御
GPPUB 0x0D R/W 0x00 0: プルアップ無効  1:プルアップ有効
INTFA 0x0E R 0x00 割込みフラグレジスタ (INTCAP 又は GPIO リードでクリア)
INTFB 0x0F R 0x00 0: 割り込みなし  1:割り込み発生
INTCAPA 0x10 R 0x00 割込みキャプチャレジスタ
INTCAPB 0x11 R 0x00 割込み発生時の GPIO の値
GPIOA 0x12 R/W 0x00 ポートレジスタ
GPIOB 0x13 R/W 0x00 GPIOの値
OLATA 0x14 R/W 0x00 出力ラッチレジスタ
OLATB 0x15 R/W 0x00 出力ラッチの値

IOCON 内容
bit 7     BANK    レジスタのアドレス指定を制御する       
   1 = 各ポートに関連付けられているレジスタが別々のバンクに分かれる
 0 = レジスタが全部同じバンクに入れられる( アドレスが連続した状態)       
bit 6     MIRROR    INT ピンのMirror ビット       
   1 = INT ピン同士を内部接続する
   0 = INT ピン同士を接続しない。INTA はPORTA に関連付けられ、
   INTB はPORTB に関連付けられる。       
bit 5     SEQOP    シーケンシャル動作モードビット       
   1 = シーケンシャル動作が無効になり、アドレスポインタはインクリメントされない

   0 = シーケンシャル動作が有効になり、アドレスポインタがインクリメントされる       
bit 4     DISSLW    SDA 出力のスルーレート制御ビット       
   1 = スルーレートは無効
   0 = スルーレートは有効       
bit 3    HAEN    ハードウェア アドレス イネーブル ビット(MCP23S17 のみ)
   MCP23017は値に関わらず、アドレスピンは常に有効。       
bit 2    ODR    INT ピンをオープンドレイン出力として設定する       
   1 = オープンドレイン出力(INTPOL ビットよりも優先される)
   0 = アクティブ ドライバ出力( 極性はINTPOL ビットで設定する)       
bit 1    INTPOL    このビットでINT 出力ピンの極性を設定する       
   1 = アクティブHigh
   0 = アクティブLow       
bit 0     未実装    0」として読み出し       

尚、BANK を変更すると、アドレスマッピングが変更されるため、注意の事。
 ( 1バイトアクセスでライトすること。)

<レジスタアクセス スケッチ>
”softAP で WiFI設定” の スケッチをベースに レジスタへの ライト/リード 及び レジスタダンプを行うコードを作成。(内容は各スケッチのコメント参照)
設定ファイルが無い状態では APモード で立ち上がるため、
 SSID : ESP32_AP
   ( パスワード : password )
に接続し、ブラウザで IPアドレス 192.168.4.1 に アクセスして、WiFi 設定を行う。

WEB画面サンプル:

<HTML>
MAIN HTML (main.html)
WiFi設定 HTML (wifi_conf.html)
XHR 応答 HTML (resp_cnfld.html)
<スケッチ>
MAIN (変数定義, setup, loop 関数)
WIFI設定 (主に WiFI 設定用 の関数)
WIFI処理 (主に MAIN処理(レジスタアクセス)の WEB画面処理 )
MAIN処理 (主に I2Cアクセス の関数)

MAIN HTML (main.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>
<style>
    #base         {font-size:16pt; text-align:center; width:410px; border:solid 4px #93ff93; background-color:#f0f0f0; }
    #set_box1     {height:19pt;font-size:10pt; text-align:left; border:solid 0px #111111; }
    #set_box2     {height:15pt;font-size:10pt; text-align:left; border:solid 0px #111111; }
    #text_box     {font-size:10pt; margin : 3px 0px 0px 0px ;float:left ; text-align:left; width:150px;}
    #regname      {font-size:10pt; margin : 0px 0px 0px 0px ;float:left ; text-align:left; width:80px;border:solid 1px #000000;}
    #regadr       {font-size:10pt; margin : 0px 0px 0px 0px ;float:left ; text-align:left; width:40px;border:solid 1px #000000;}
    #regwdt       {font-size:10pt; margin : 0px 0px 0px 0px ;float:left ; text-align:left; width:100px;}
    #regrdt       {font-size:10pt; margin : 0px 3px 0px 0px ;float:left ; text-align:left; width:75px;border:solid 1px #000000;}
    #button       {font-size:12pt; margin : 10px 0px 10px 0px ;clear:both; }border:solid 1px #000000;
    #btn_conf     {font-size:12pt; margin : 10px 0px 10px 0px ;text-align:left  ; width:83%; }
    #text_in      {height: 12pt ; margin:14px 0px 0px 5px ; font-size:8pt; float:right; }
    #foot         {font-size:16pt; clear:both;}
    input         {margin:0px 8px 0px 8px ;width:50px;}
    input.button  {margin:0px 8px 0px 8px ;width:100px;}
    input.btncnf  {margin:0px 0px 0px 28px ;width:100px;}
    output        {margin:0px 8px 0px 8px ;}
    div           {font-size:16pt;text-align:center;}
</style>
 
<title>MCP23017 Access</title></head>
 
<body>
<div id="base">
  <p>MCP23017 レジスタ アクセス</p>
  <form method='get'>
    <div id=set_box1>
      <div id=text_box>スレーブアドレス</div>
      <div id=regwdt> <span>0x</span><input type='text' name='sadr' value=$s_adr > </div>
    </div>
  </form>
  <form method='get'>
    <div id=set_box1>
      <div id=text_box>レジスタアドレス</div>
      <div id=regwdt> <span>0x</span><input  type='text' name='regadr' value=$reg_adr > </div>
    </div>
    <div id=set_box1>
      <div id=text_box>ライトデータ</div>
      <div id=regwdt> <span>0x</span><input  type='text' name='wrdt' value=$wr_dt > </div>
    </div>
    <div id=set_box1>
      <div id=text_box>リードデータ</div>
      <div id=regwdt> <span>0x</span><output  name='rddt' >$rd_dt</output>  </div>
    </div>
    <div id=button>
      <input class=button type='submit' name='read' value='rd' >
      <input class=button type='submit' name='write' value='wr' >
    </div>
  </form>
      <span>レジスタダンプ</span>
    <div id=set_box2>
      <div id=regname>レジスタ名</div>
      <div id=regadr>adr</div>
      <div id=regrdt>データ</div>
      <div id=regname>レジスタ名</div>
      <div id=regadr>adr</div>
      <div id=regrdt>データ</div>
    </div>
    <div id=set_box2>
      <div id=regname> IODIRA</div>
      <div id=regadr> 00</div>
      <div id=regrdt> <span>0x</span><output name='rddt00' >$rdt00</output> </div>
      <div id=regname> IODIRB</div>
      <div id=regadr> 01</div>
      <div id=regrdt> <span>0x</span><output name='rddt01' >$rdt01</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> IPOLA </div>
      <div id=regadr> 02</div>
      <div id=regrdt> <span>0x</span><output name='rddt02' >$rdt02</output> </div>
      <div id=regname> IOOLB</div>
      <div id=regadr> 03</div>
      <div id=regrdt> <span>0x</span><output name='rddt03' >$rdt03</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> GPINTENA </div>
      <div id=regadr> 04</div>
      <div id=regrdt> <span>0x</span><output name='rddt04' >$rdt04</output> </div>
      <div id=regname> GPINTENB</div>
      <div id=regadr> 05</div>
      <div id=regrdt> <span>0x</span><output name='rddt05' >$rdt05</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> DEFVALA </div>
      <div id=regadr> 06</div>
      <div id=regrdt> <span>0x</span><output name='rddt06' >$rdt06</output> </div>
      <div id=regname> DEFVALB</div>
      <div id=regadr> 07</div>
      <div id=regrdt> <span>0x</span><output name='rddt07' >$rdt07</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> INTCONA </div>
      <div id=regadr> 08</div>
      <div id=regrdt> <span>0x</span><output name='rddt08' >$rdt08</output> </div>
      <div id=regname> INTCONB</div>
      <div id=regadr> 09</div>
      <div id=regrdt> <span>0x</span><output name='rddt09' >$rdt09</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> IOCON   </div>
      <div id=regadr> 0a</div>
      <div id=regrdt> <span>0x</span><output name='rddt0a' >$rdt0a</output> </div>
      <div id=regname> IOCON  </div>
      <div id=regadr> 0b</div>
      <div id=regrdt> <span>0x</span><output name='rddt0b' >$rdt0b</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> GPPUA   </div>
      <div id=regadr> 0c</div>
      <div id=regrdt> <span>0x</span><output name='rddt0c' >$rdt0c</output> </div>
      <div id=regname> GPPUB  </div>
      <div id=regadr> 0d</div>
      <div id=regrdt> <span>0x</span><output name='rddt0d' >$rdt0d</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> INTFA   </div>
      <div id=regadr> 0e</div>
      <div id=regrdt> <span>0x</span><output name='rddt0e' >$rdt0e</output> </div>
      <div id=regname> INTFB  </div>
      <div id=regadr> 0f</div>
      <div id=regrdt> <span>0x</span><output name='rddt0f' >$rdt0f</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> INTCAPA </div>
      <div id=regadr> 10</div>
      <div id=regrdt> <span>0x</span><output name='rddt10' >$rdt10</output> </div>
      <div id=regname> INTCAPB </div>
      <div id=regadr> 11</div>
      <div id=regrdt> <span>0x</span><output name='rddt11' >$rdt11</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> GPIOA </div>
      <div id=regadr> 12</div>
      <div id=regrdt> <span>0x</span><output name='rddt12' >$rdt12</output> </div>
      <div id=regname> GPIOB</div>
      <div id=regadr> 13</div>
      <div id=regrdt> <span>0x</span><output name='rddt13' >$rdt13</output> </div>
    </div>
    <div id=set_box2>
      <div id=regname> OLATA </div>
      <div id=regadr> 14</div>
      <div id=regrdt> <span>0x</span><output name='rddt14' >$rdt14</output> </div>
      <div id=regname> OLATB</div>
      <div id=regadr> 15</div>
      <div id=regrdt> <span>0x</span><output name='rddt15' >$rdt15</output> </div>
    </div>
  <form method='get'>
    <div id='button'>
      <input class='button' type='submit' name='dump' value='dmp' >
    </div>
  </form>
  <div id="btn_conf">
    <form method="get">
        <input class='btncnf' type='submit' name='config' id='config' value='WiFi設定画面'>
        <div id="text_in">
          <a href="#" onclick='cnfdl();'>設定をダウンロードする</a>
        </div>
     </form>
  </div>
</div>
 
<script>
  function cnfdl() {
    "use strict";
   
    var xhr = new XMLHttpRequest();
    xhr.open("get", "?cnfdl");
    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) ) {
        var filename = "config.txt" ;
        var str = xhr.response.getElementById("output").innerHTML ;
        var blob = new Blob([str],{type:'text/plain'}) ;
        if (window.navigator.msSaveBlob) {
        //window.navigator.msSaveBlob(blob, filename);
          window.navigator.msSaveOrOpenBlob(blob,filename) ;
        }
        else {
          var objectURL = window.URL.createObjectURL(blob);
          var link = document.createElement("a");
          document.body.appendChild(link);
          link.href = objectURL;
          link.download = filename;
          link.click();
          document.body.removeChild(link);
        }
      }
    }
    xhr.send();
  }
</script>
 
</body>
</html>

WiFi設定 HTML (wifi_conf.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
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>
<style>
    #base         {font-size:16pt; text-align:center; width:600px; border:solid 4px #00000000; background-color:#c0c0c0; }
    #text_box     {height: 25px; font-size:12pt; float:left ; text-align:left; width:45%;}
    #input_box    {height: 25px; font-size:12pt; float:right; text-align:left; width:55%;}
    #ip_box       {height: 25px; font-size:12pt; float:right; text-align:left; width:15%;}
    #radio_box    {font-size:12pt; clear:both; margin : 0% 20% ; width : 60% ;}
    #button       {font-size:12pt; clear:both; width 50%}
    #foot         {font-size:16pt; clear:both;}
    input.val     {width: 90%;}
    input.ip      {width: 20%;}
    input.button  {margin:10px 10% ; width: 25%;}
    input.radio   {margin:10px 0px 0px 15% ; }
</style>
 
<title>設定画面</title></head>
 
<body>
<div id="base">
  <p>設定画面</p>
  <div id="text_box">
    <span> WiFi 接続先 SSID </span>
  </div>
 <form method="get">
  <div id="input_box">
      <input class='val' type='text' name='ssid' id='ssid' value=$ssid>
  </div>
  <div id="text_box">
    <span> WiFi 接続先 PASSWORD </span>
  </div>
  <div id="input_box">
      <input class='val' type='text' name='pass' id='pass' value=$pass>
  </div>
  <div id="text_box">
    <span> WiFi 接続  IP アドレス </span>
  </div>
  <div id="input_box">
      <input class='ip' type='number' name='ip1' id='ip1' min=0 max=255 value=$ip1 >
      <input class='ip' type='number' name='ip2' id='ip2' min=0 max=255 value=$ip2 >
      <input class='ip' type='number' name='ip3' id='ip3' min=0 max=255 value=$ip3 >
      <input class='ip' type='number' name='ip4' id='ip4' min=0 max=255 value=$ip4 >
  </div>
  <div id="text_box">
    <span> WiFi 接続  サブネットマスク</span>
  </div>
  <div id="input_box">
      <input class='ip' type='number' name='sn1' id='sn1' min=0 max=255 value=$sm1 >
      <input class='ip' type='number' name='sn2' id='sn2' min=0 max=255 value=$sm2 >
      <input class='ip' type='number' name='sn3' id='sn3' min=0 max=255 value=$sm3 >
      <input class='ip' type='number' name='sn4' id='sn4' min=0 max=255 value=$sm4 >
  </div>
  <div id="text_box">
    <span> WiFi 接続  デフォルトゲートウェイ</span>
  </div>
  <div id="input_box">
      <input class='ip' type='number' name='gw1' id='gw1' min=0 max=255 value=$gw1 >
      <input class='ip' type='number' name='gw2' id='gw2' min=0 max=255 value=$gw2 >
      <input class='ip' type='number' name='gw3' id='gw3' min=0 max=255 value=$gw3 >
      <input class='ip' type='number' name='gw4' id='gw4' min=0 max=255 value=$gw4 >
  </div>
  <div id="text_box">
    <span> WiFi 接続  DNSアドレス</span>
  </div>
  <div id="input_box">
      <input class='ip' type='number' name='dns1' id='dns1' min=0 max=255 value=$dns1 >
      <input class='ip' type='number' name='dns2' id='dns2' min=0 max=255 value=$dns2 >
      <input class='ip' type='number' name='dns3' id='dns3' min=0 max=255 value=$dns3 >
      <input class='ip' type='number' name='dns4' id='dns4' min=0 max=255 value=$dns4 >
  </div>
  <div id="radio_box">
      <input class='radio' type='radio' name='wifi_stamode' id='rad_sta' value='sta' $checked_sta > STA MODE
      <input class='radio' type='radio' name='wifi_stamode' id='rad_ap' value='ap' $checked_ap > AP MODE
  </div>
  <div id="button">
      <input class='button' type='submit' name='set' id='set' value='設定'>
      <input class='button' type='submit' name='rtn' id='rtn' value='戻る'>
  </div>
 </form>
 <div id="foot">
   <span>$footer</span>
 </div>
</div>
</body>
</html>

XHR 応答 HTML (resp_cnfld.html)
1
2
3
4
5
<!DOCTYPE html><html lang='ja'>
  <head> <title>MCP23017</title></head>
  <html> <body>
    <output id='output'>$cnf_text</output>
  </body> </html>

MAIN (変数定義, setup, loop 関数)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/* +========================================================================+ */
/* | MCP23017 TEST                                                          | */
/* +========================================================================+ */
                                              //
#include <Wire.h>                             //
#include <WiFi.h>                             //
#include "FS.h"                               // SPIFFS 用
#include "SPIFFS.h"                           // SPIEES 用
                                              //
// +------------------------------------------------------------------------+
// | WiFi 設定用定義                                                        |
// +------------------------------------------------------------------------+
// AP モード用 WIFI 設定 ----------------------------------------------------
const char ssid[] = "ESP32_AP";               // SSID for softAP
const char pass[] = "password";               // password for softAP
const IPAddress ip(192, 168, 4, 1);           // IPアドレス for softAP
const IPAddress subnet(255, 255, 255, 0);     // サブネットマスク for softAP
// AP/STA 動作モードフラグ --------------------------------------------------
bool stamode = true ;                         // WiFi STA 接続モード : true
bool sta_exec = false ;                       // WiFi STA接続モード実行中フラグ
bool config_mode  = false ;                   // 初期設定モード ; true
bool config_exec = false ;                    // 初期設定実行中フラグ
// WiFi 設定ファイル用 ------------------------------------------------------
String s_config ;                             // 設定ファイル用 String
char wifi_ssid[128] = "" ;                    // SSID        for WiFi STA
char wifi_pass[128] = "" ;                    // password    for WiFi STA
IPAddress wifi_ip(192,168,1,66) ;             // IP Address  for WiFi STA
IPAddress wifi_gw(192,168,1,1)  ;             // gate way    for WiFi STA
IPAddress wifi_sm(255,255,255,0) ;            // subnet mask for WiFi STA
IPAddress wifi_dns(192,168,1,1) ;             // dns address for WiFi STA
char wifi_mode[16] = ""   ;                   // wifi mode
String foot_msg ="" ;                         // リブートメッセージ用
bool config_dl = false ;                      // 設定ファイルダウンロード要求フラグ
 
WiFiServer server(80);
 
String html_CONF ;                            // 設定用 HTML
String html_MAIN ;                            // メイン HTML
String html_resp ;                            // XHR レスポンス用
 
// --------------------------------------------------------------------------
 
// +------------------------------------------------------------------------+
// | MCP23017 用定義                                                        |
// +------------------------------------------------------------------------+
bool wadr      = false ;                      // 2B モードフラグ
bool rd_req    = false ;                      // リード要求フラグ
bool wr_req    = false ;                      // ライト要求フラグ
bool dmp_req   = false ;                      // ダンプ要求フラグ
byte sadr      = 0x21 ;                       // slave address
byte regadr    = 0x0  ;                       // regadr
byte wrdt      = 0x00 ;                       // write data
byte rddt      = 0x00 ;                       // read date
byte dmpdt[32] = {0,0,0,0,0,0,0,0,            // dump data
                  0,0,0,0,0,0,0,0,            //         
                  0,0,0,0,0,0,0,0,            //         
                  0,0,0,0,0,0,0,0 } ;         //         
byte IODIRA    = 0x00 ;                       // IODIRA Register Address
byte IODIRB    = 0x01 ;                       // IODIRB Register Address
byte GPPUA     = 0x0C ;                       // GPPUA Register Address
byte GPPUB     = 0x0D ;                       // GPPUA Register Address
byte GPIOA     = 0x12 ;                       // GPIOA Register Address
byte GPIOB     = 0x13 ;                       // GPIOA Register Address
 
/* +========================================================================+ */
/* | 初期設定                                                               | */
/* +========================================================================+ */
void setup()
{
  // +------------------------------------------------------------------------+
  // | Serial 出力用 SetUp                                                    |
  // +------------------------------------------------------------------------+
  Serial.begin(115200);                        // シリアル 開始
  SPIFFS.begin(true) ;                         // SPIFFS 開始
                                               //
  // +------------------------------------------------------------------------+
  // | WiFi 用 SetUp                                                          |
  // +------------------------------------------------------------------------+
  int res = 0 ;                                // 結果格納用 (ワーク)
                                               //
  // 初期設定用 HTML ファイルの読み込み ---------------------------------------
  res = rd_SPIFFS("/WiFi_Config.html",html_CONF) ;
                                               // html_CONF に Config.html を格納
  // 本体 HTML ファイルの読み込み ----------------------------------------------
  res = rd_SPIFFS("/main.html",html_MAIN) ;    // html_MAIN に main.html を格納
                                               //
  // レスポンス用HTML ファイルの読み込み ----------------------------------------
  res = rd_SPIFFS("/resp_cnfld.html",html_resp) ;
                                               // html_resp に resp_confld.html を格納
  // 初期設定ファイルを読み込み、グローバル変数に設定し、wifi,画面モードを決定 ---
  res = rd_config() ;                          //
                                               //
  // wifiモード(stamode) に応じて AP か STA かを選択してサーバー起動 -------------
  if (stamode == false) {                      // APモードの場合 softAP WiFi 開始
    start_AP_server() ;                        // APモードでサーバー起動
    sta_exec = false ;                         //
  } else {                                     // STAモードの場合 Wifi 開始
    start_STA_server() ;                       // APモードでサーバー起動
    sta_exec = true ;                          //
  }                                            //
                                               //
  // 実行中のモード (設定かメインか) を設定 -------------------------------------
  if (config_mode) config_exec = true ;        // config_mode なら config_exec を '1'
  else config_exec = false ;                   //
                                               //
  Serial.println("Server start!");             //
                                               //
  // +------------------------------------------------------------------------+
  // | メイン処理用設定                                                       |
  // +------------------------------------------------------------------------+
  Wire.begin();
 
  // set direction IOA,IOB
  //I2C_BWR(MCP23017,IODIRA,0xFE) ;   // set IOA0 : output
  //I2C_BWR(MCP23017,IODIRB,0x7F) ;   // set IOB7 : output
  //I2C_BWR(MCP23017,GPPUA,0x80) ;    // set IOA7 : PullUp
 
}
 
 
/* +========================================================================+ */
/* | メインループ                                                           | */
/* +========================================================================+ */
void loop()
{
  // +------------------------------------------------------------------------+
  // | WiFi 処理                                                              |
  // +------------------------------------------------------------------------+
  WiFiClient client = server.available();
  String htmlwk = "" ;                            // html 用 ワーク変数
  String line   = "" ;                            // クライアントからの入力用
  int xhr = 0 ;                                   // xhr 要求フラグ
  
  // HTML クライアント処理 ------------------------------------------------------
  if (client) {
    Serial.println(" +++++++++++++++++ new client! +++++++++++++++++ ");
    while (client.connected()) {                  // クライアントから接続されたとき
      if (client.available()) {                   //
        line = client.readStringUntil('\n');      // 1行分取得
//      # ifdef DEBUG_HTML                        //
          Serial.println(line) ;                  //
//      # endif                                   //
        if (line.indexOf("GET /?") != -1) {       // GET 処理
          if (config_mode)                        // 初期設定用 フォームデータ処理
            set_form2param(line) ;                //   フォームデータを変数に格納
          else {                                  // メイン用 処理
            xhr = proc_form(line) ;               //   フォームデータのメイン処理
          }                                       //
        }                                         //
        // 最終行(空行)を受信した時 -------------------------------------------
        if (line.length() == 1 && line[0] == '\r'){  // 最終行判定
          if (stamode != sta_exec) {             // sta_mode が変わった場合
            if (strcmp(wifi_mode,"ap") == 0){    //  リブートメッセージを設定
              foot_msg = "アクセスポイントモードに移行します。<br>" ;
              foot_msg += "この画面を閉じてアクセスポイントに接続して下さい。" ;
             }else{
             foot_msg = "ステーションモードに移行します。<br>";
               foot_msg += "この画面を閉じて 設定したアドレスに接続して下さい。" ;
             }
            if (config_exec) {                    //   初期設定中なら
              send_CONF_html(client) ;            //     初期設定 HTML 送信
            } else {                              //   メイン画面なら
              send_MAIN_html(client) ;            //     メイン HTML 送信
            }                                     //    ( その後 リブート)
          } else {                                // sta_mode が変わらない場合
            if (config_mode) {                    //   次に初期設定を表示するなら
              send_CONF_html(client) ;            //     初期設定 HTML 送信
              config_exec = true ;                //
            } else {                              //   次にメイン画面なら
              if (rd_req) {                       //     リード要求フラグが ON なら
                rddt = I2C_BRD(sadr,regadr) ;     //     リードを実行
                rd_req = false ;                  //
              }                                   //
              if (wr_req) {                       //     ライト要求フラグが ON なら
                I2C_BWR(sadr,regadr,wrdt) ;       //      ライトを実行
                rddt = I2C_BRD(sadr,regadr) ;     //      リードを実行
                wr_req = false ;                  //
              }                                   //
              if (dmp_req) {                      //     ダンプ要求フラグが ON なら
                reg_dmp() ;                       //      ダンプ動作を実行
                dmp_req = false ;                 //
              }                                   //
              if (xhr) {                          //     XHR 応答の場合
                send_resp_html(client) ;          //       XHR 応答 送信
              } else {                            //     HTML 送信なら
                send_MAIN_html(client) ;          //     メイン HTML 送信
                config_exec = false ;             //
              }                                   //
            }                                     //
          }                                       //
          # ifdef DEBUG_HTML                      //
            Serial.println("Send HTML") ;         //
          # endif                                 //
          break ;                                 // ループ終了
        }                                         //
        //-------------------------------------------------------------------
      }
    }
    // 接続が切れた場合 ------------------------------------------------------
    client.stop();
    Serial.println("client disonnected");
    Serial.println("----------------------------------------------------");
  }
 
  if (stamode != sta_exec) {                      // sta_mode が変わった場合
    Serial.println("------------------- リブートします------------------- ");
    delay(500);                                   //
    ESP.restart() ;                               // リブート
  } else {
  }
  // --------------------------------------------------------------------------
 
  // byte DATA ;
 
  // DATA = I2C_BRD(MCP23017,GPIOA) ;
  // if ( (DATA & 0x80) == 0x00 ) {
  //   I2C_BWR(MCP23017,GPIOA,0x01) ;   // set IOA0 = H
  //   I2C_BWR(MCP23017,GPIOB,0x00) ;   // set IOB7 = L
 
  //   DATA = I2C_BRD(MCP23017,GPIOA) ;
  //   Serial.print("REG GPIOA : 0x");
  //   Serial.println(DATA, HEX);
  //   DATA = I2C_BRD(MCP23017,GPIOB) ;
  //   Serial.print("REG GPIOB : 0x");
  //   Serial.println(DATA, HEX);
 
  //   delay(2000);           // wait 2 seconds for next
 
  //   I2C_BWR(MCP23017,GPIOA,0x00) ;   // set IOA0 = L
  //   I2C_BWR(MCP23017,GPIOB,0x80) ;   // set IOB7 = H
 
  //   DATA = I2C_BRD(MCP23017,GPIOA) ;
  //   Serial.print("REG GPIOA : 0x");
  //   Serial.println(DATA, HEX);
  //   DATA = I2C_BRD(MCP23017,GPIOB) ;
  //   Serial.print("REG GPIOB : 0x");
  //   Serial.println(DATA, HEX);
 
  //   delay(2000);           // wait 2 seconds for next
  // } else {
  //   I2C_BWR(MCP23017,GPIOA,0x00) ;   // set IOA0 = L
  //   I2C_BWR(MCP23017,GPIOB,0x00) ;   // set IOB7 = L
  //   delay(4000);           // wait 4 seconds for next
  // }   
}

WIFI設定 (主に WiFI 設定用 の関数)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
// *****************************************************************************
// *  初期設定ファイル をリードし、グローバル変数に値をセットする              *
// *****************************************************************************
int rd_config() {                                //
  File fp       ;                                // 設定ファイル用ファイルポインタ
  int result = 0 ;                               // 戻り値
                                                 //
  if (SPIFFS.exists("/config.txt")) {            // 設定ファイル存在確認
    // ファイルがあった場合 ---------------------//
    result = rd_SPIFFS("/config.txt",s_config) ; // s_config に config.txt を格納
  } else {                                       //
    // ファイルが無かった場合 -------------------//
    Serial.println("設定ファイルなし") ;         // 無かったら、APモード
    result = -1 ;                                //
  }                                              //
 
  // ファイルが読み込めたら、グローバル変数にセットする
  if (result == 0)                               //
    # ifdef DEBUG                                // デバッグ用表示
      Serial.println("--- s_config --- ") ;      //
      Serial.println(s_config ) ;                //
    # endif                                      //
    set_conf2param() ;                           // s_config の内容を変数に設定
  // 初期設定ファイルの状態で wifiモード, 画面モードを設定 ----------------------
  if (result != -1) {                          // 変数に設定できた場合
    if (( strcmp(wifi_ssid,"") ==0) || (strcmp(wifi_pass,"") ==0)) {
                                               // ssid,pass 設定なければ
      stamode = false ;                        //   APモード
      if ( strcmp(wifi_mode,"ap") == 0)        // wifi_mode が "ap" なら
        config_mode = false ;                  //   メイン画面
      else                                     // wifi_mode が "ap" でなければ
        config_mode = true ;                   //   初期設定画面
    } else {                                   // ssid,pass の設定があれば、
      config_mode = false ;                    //   メイン画面
      if ( strcmp(wifi_mode,"ap") == 0)        // wifi_mode が "ap" なら
        stamode = false ;                      //   APモード
      else                                     // "ap" でなければ
        stamode = true  ;                      //   STAモード
    }
  } else {                                     // 変数に設定できなかった場合
    stamode = false ;                          //   APモード
    config_mode  = true ;                      //   初期設定画面
  }
 
  return result ;                              //
}
 
// ----------------------------------------------------------------------------
// - 設定ファイルの内容を グローバル変数に 設定する                           -
// ----------------------------------------------------------------------------
void set_conf2param() {
  int    pos = 0 ;
  int    npos = 0 ;
  String s_work ;
  String s_name ;
  String s_data ;
  // 記載内容を順次処理 ( 設定情報を取り出し、グローバル変数に設定する ) ------
  while(1) {
    if (s_config.charAt(pos) == '/') {         // 先頭が '/' なら 次の行へ
      npos = s_config.indexOf('\n',pos) ;      //
      pos = npos + 1 ;                         //
    } else {                                   //
      npos = s_config.indexOf(':',pos) ;       // ':' までの文字をs_name に取得
      if (npos == -1) break ;                  //   見つからなければ終了
      s_name = s_config.substring(pos,npos) ;  //
      s_name.trim() ;                          //
      pos = npos+1 ;                           // ポインタを ':' の次へ
      npos = s_config.indexOf('\n',pos) ;      // '\n' までの文字をs_data に取得
      if (npos == -1) npos = s_config.length() ;  //
      s_data = s_config.substring(pos,npos) ;  //
      s_data.trim() ;                          //
      pos = npos+1 ;                           //
      set_param(s_name,s_data) ;               // 取得した内容をグローバル変数に設定
    }                                          //
  }                                            //
}                                              //
 
// - 設定内容を判定し、グローバル変数に設定 ------------------------------------
void set_param(String &name, String &data) {   //
  if (name.compareTo("wifi_ssid")==0) {        // 'wifi_ssid' の場合
    data.toCharArray(wifi_ssid,128) ;          //
  }                                            //
  if (name.compareTo("wifi_pass")==0) {        // 'wifi_pass' の場合
    data.toCharArray(wifi_pass,128) ;          //
  }                                            //
  if (name.compareTo("wifi_ip")==0) {          // 'wifi_ip' の場合
    wifi_ip = stoip(data) ;                    //  取得情報(文字列)をIPAddressに変換
  }                                            //
  if (name.compareTo("wifi_gw")==0) {          // 'wifi_gw' の場合
    wifi_gw = stoip(data) ;                    //
  }                                            //
  if (name.compareTo("wifi_sm")==0) {          // 'wifi_sm' の場合
    wifi_sm = stoip(data) ;                    //
  }                                            //
  if (name.compareTo("wifi_dns")==0) {         // 'wifi_dns' の場合
    wifi_dns = stoip(data) ;                   //
  }                                            //
  if (name.compareTo("wifi_mode")==0) {        // 'wifi_mode' の場合
    data.toCharArray(wifi_mode,16) ;           //
  }                                            //
}                                              //
 
// - 文字列 から IPAddress へ変換 ----------------------------------------------
IPAddress stoip(String &data) {                 //
  IPAddress ip ;
  String num = "" ;
  int pos = 0 ;
  while(data.charAt(pos) != '.') {             // 先頭から '.' までの文字を取得
    num += data.charAt(pos++) ;                //
  }                                            //
  ip[0] = num.toInt() ;                        // 数値に変換して 第1オクテット に 代入
  pos++ ;                                      // '.' の次から
  num="";                                      //
  while(data.charAt(pos) != '.') {             // '.' までの文字を取得
    num += data.charAt(pos++) ;                //
  }                                            //
  ip[1] = num.toInt() ;                        // 数値に変換して 第2オクテットに代入
  pos++ ;                                      // '.' の次から
  num="";                                      //
  while(data.charAt(pos) != '.') {             // '.' までの文字を取得
    num += data.charAt(pos++) ;                //
  }                                            //
  ip[2] = num.toInt() ;                        //
  pos++ ;                                      // '.' の次から
  num="";                                      //
  while(data.charAt(pos) != '.') {             // '.' または 最後まで の 文字を取得
    num += data.charAt(pos++) ;                //
    if (pos > data.length()) break ;           //
  }                                            //
  ip[3] = num.toInt() ;                        // 数値に変換して 第4オクテットに代入
                                               //
  return ip ;                                  // IPAddress を戻り値とする
}                                              //
 
// ****************************************************************************
// * アクセスポイント モードで サーバーを起動                                 *
// ****************************************************************************
void start_AP_server() {
  Serial.println(" AP Server exec") ;
  WiFi.softAP(ssid, pass);             // SSIDとパスの設定
  delay(100);                          // delayが必要
  WiFi.softAPConfig(ip, ip, subnet);   // IP address, gateway, subnetmask の設定
  IPAddress myIP = WiFi.softAPIP();    // WiFi.softAPIP()でWiFi起動
  server.begin();                      // サーバーを起動(htmlを表示させるため)
}
 
// ****************************************************************************
// * デバッグ表示用                                                           *
// ****************************************************************************
void disp_mode() {
  # ifdef DEBUG_HTML                              // デバッグ用表示
    Serial.print("config_mode - exec : ") ;       // 設定画面か メイン画面か
    if (config_mode)                              // 変数の状態と実行状況を表示
      Serial.print("Config MODE - ") ;            //
    else                                          //
      Serial.print("Main MODE - ") ;              //
    if (config_exec)                              //
      Serial.println("Config MODE") ;             //
    else                                          //
      Serial.println("Main MODE") ;               //
                                                  //
    Serial.print("wifi_mode - exec   : ") ;       // Wifi モードを
    if (stamode)                                  // 変数の状態と実行状況を表示
      Serial.print("STA - ") ;                    //
    else                                          //
      Serial.print("AP - ") ;                     //
    if (sta_exec)                                 //
      Serial.println("STA") ;                     //
    else                                          //
      Serial.println("AP") ;                      //
  # endif                                         //
}
 
// ****************************************************************************
// * クライアントからのフォームデータを変数にセットし、設定ファイルに書き出す *
// ****************************************************************************
void set_form2param(String &line) {
  String s_work ="" ;
 
  if (line.indexOf("set=") != -1) {               // stamode set
    // クライアントからのデータを グローバル変数にセットする。 ------------------
    if (line.indexOf("GET /?ssid=") != -1) {        // wifi_ssid
      s_work = getvalue_s(line,"?ssid=") ;          //   ssid に続く文字列を取得
      s_work.toCharArray(wifi_ssid,128) ;           //   変数にセット
    }
    if (line.indexOf("pass=") != -1) {              // wifi_pass
      s_work = getvalue_s(line,"pass=") ;           //   pass に続く文字列を取得
      s_work.toCharArray(wifi_pass,128) ;           //   変数にセット
    }
    if (line.indexOf("ip1=") != -1) {               // wifi_ip
      wifi_ip[0] = getvalue_i(line,"ip1=") ;        //   ip1 に続く数値を変数にセット
    }
    if (line.indexOf("ip2=") != -1) {               //
      wifi_ip[1] = getvalue_i(line,"ip2=") ;        //   ip2 に続く数値を変数にセット
    }
    if (line.indexOf("ip3=") != -1) {               //
      wifi_ip[2] = getvalue_i(line,"ip3=") ;        //   ip3 に続く数値を変数にセット
    }
    if (line.indexOf("ip4=") != -1) {               //
      wifi_ip[3] = getvalue_i(line,"ip4=") ;        //   ip4 に続く数値を変数にセット
    }
    if (line.indexOf("gw1=") != -1) {               // wifi_gw
      wifi_gw[0] = getvalue_i(line,"gw1=") ;        //   gw1 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("gw2=") != -1) {               //                      
      wifi_gw[1] = getvalue_i(line,"gw2=") ;        //   gw2 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("gw3=") != -1) {               //                      
      wifi_gw[2] = getvalue_i(line,"gw3=") ;        //   gw3 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("gw4=") != -1) {               //                      
      wifi_gw[3] = getvalue_i(line,"gw4=") ;        //   gw4 に続く数値を変数にセット
    }
    if (line.indexOf("sm1=") != -1) {               // wifi_sm
      wifi_sm[0] = getvalue_i(line,"sm1=") ;        //   sm1 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("sm2=") != -1) {               //                      
      wifi_sm[1] = getvalue_i(line,"sm2=") ;        //   sm2 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("sm3=") != -1) {               //                      
      wifi_sm[2] = getvalue_i(line,"sm3=") ;        //   sm3 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("sm4=") != -1) {               //                      
      wifi_sm[3] = getvalue_i(line,"sm4=") ;        //   sm4 に続く数値を変数にセット
    }
    if (line.indexOf("dns1=") != -1) {              // wifi_dns
      wifi_dns[0] = getvalue_i(line,"dns1=") ;      //   dns1 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("dns2=") != -1) {              //                      
      wifi_dns[1] = getvalue_i(line,"dns2=") ;      //   dns2 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("dns3=") != -1) {              //                      
      wifi_dns[2] = getvalue_i(line,"dns3=") ;      //   dns3 に続く数値を変数にセット
    }                                                                       
    if (line.indexOf("dns4=") != -1) {              //                      
      wifi_dns[3] = getvalue_i(line,"dns4=") ;      //   dns4 に続く数値を変数にセット
    }
    if (line.indexOf("stamode=") != -1) {           // stamode set
      s_work = getvalue_s(line,"stamode=") ;        //   ssid に続く文字列を取得
      s_work.toCharArray(wifi_mode,16) ;            //   変数にセット
      if (s_work == "sta") {                        //   設定値により、モードをセット
        stamode = true ;                            //
        config_mode = false ;                       //
      } else {                                      //
        stamode = false ;                           //
        config_mode = false ;                       //
      }
    }
    // グローバル変数を 設定ファイルに書き出す -----------------------------------
    wr_config() ;                           // 設定を初期設定ファイルに書き出し
  }
  if (line.indexOf("rtn") != -1) {                  // return
    config_mode = false ;                           //
  }
}
 
 
// -----------------------------------------------------------------------------
// - グローバル変数の内容を設定ファイルに書き出す                              -
// -----------------------------------------------------------------------------
void wr_config() {
  char s_work[128] ;
  File fp ;
 
  // String に 変数の内容を書き込む -------------------------------------------
  sprintf(s_work,"wifi_ssid : %s\n",wifi_ssid) ;  //
  s_config = String(s_work) ;                     //
  sprintf(s_work,"wifi_pass : %s\n",wifi_pass) ;  //
  s_config += String(s_work) ;                    //
  sprintf(s_work,"wifi_ip   : %3d.%3d.%3d.%3d\n",wifi_ip[0],wifi_ip[1],wifi_ip[2],wifi_ip[3]) ;
  s_config += String(s_work) ;                    //
  sprintf(s_work,"wifi_sm   : %3d.%3d.%3d.%3d\n",wifi_sm[0],wifi_sm[1],wifi_sm[2],wifi_sm[3]) ;
  s_config += String(s_work) ;                    //
  sprintf(s_work,"wifi_gw   : %3d.%3d.%3d.%3d\n",wifi_gw[0],wifi_gw[1],wifi_gw[2],wifi_gw[3]) ;
  s_config += String(s_work) ;                    //
  sprintf(s_work,"wifi_dns  : %3d.%3d.%3d.%3d\n",wifi_dns[0],wifi_dns[1],wifi_dns[2],wifi_dns[3]) ;
  s_config += String(s_work) ;                    //
  sprintf(s_work,"wifi_mode : %s\n",wifi_mode) ;  //
  s_config += String(s_work) ;                    //
 
  // 設定ファイルに書き込む ----------------------------------------------------
  fp = SPIFFS.open("/config.txt",FILE_WRITE) ;    // 設定ファイルを開く
  if (!fp) {
    Serial.println(" 設定ファイル オープンエラー !!") ;
  } else {
    // 初期設定ファイル書き込み -------------------------------------------------
    if(fp.print(s_config)) {                      // ファイルに書き込み
      Serial.println("s_config written") ;        //   終了メッセージ
    } else {                                      //
      Serial.println("s_config write error !!") ; //   失敗メッセージ
    }                                             //
    fp.close() ;                                  // ファイルクローズ
  }                                               //
                                                  //
}                                                 //
 
// *****************************************************************************
// * HTML 送信処理                                                             *
// *****************************************************************************
 
// ----------------------------------------------------------------------------
// - CONF_HTML 送信  -----------------------------------------------------------
// ----------------------------------------------------------------------------
void  send_CONF_html(WiFiClient client) {
  String htmlwk ;
 
  // 変数置換え処理 ------------------------------------------------------------
  htmlwk = html_CONF ;
  htmlwk.replace("$ssid",String(wifi_ssid)) ;
  htmlwk.replace("$pass",String(wifi_pass)) ;
  htmlwk.replace("$ip1",String(wifi_ip[0])) ;
  htmlwk.replace("$ip2",String(wifi_ip[1])) ;
  htmlwk.replace("$ip3",String(wifi_ip[2])) ;
  htmlwk.replace("$ip4",String(wifi_ip[3])) ;
  htmlwk.replace("$sm1",String(wifi_sm[0])) ;
  htmlwk.replace("$sm2",String(wifi_sm[1])) ;
  htmlwk.replace("$sm3",String(wifi_sm[2])) ;
  htmlwk.replace("$sm4",String(wifi_sm[3])) ;
  htmlwk.replace("$gw1",String(wifi_gw[0])) ;
  htmlwk.replace("$gw2",String(wifi_gw[1])) ;
  htmlwk.replace("$gw3",String(wifi_gw[2])) ;
  htmlwk.replace("$gw4",String(wifi_gw[3])) ;
  htmlwk.replace("$dns1",String(wifi_dns[0])) ;
  htmlwk.replace("$dns2",String(wifi_dns[1])) ;
  htmlwk.replace("$dns3",String(wifi_dns[2])) ;
  htmlwk.replace("$dns4",String(wifi_dns[3])) ;
  if (stamode) {                                // ステーションモード時
    htmlwk.replace("$checked_sta","checked") ;  //
    htmlwk.replace("$checked_ap","") ;          //
  } else {                                      // アクセスポイントモード時
    htmlwk.replace("$checked_sta","") ;         //
    htmlwk.replace("$checked_ap","checked") ;   //
  }
  htmlwk.replace("$footer",foot_msg ) ;
  // --------------------------------------------------------------------------
 
  send_html(client,htmlwk) ;                       // HTML 送信処理
}

WIFI処理 (主に MAIN処理(レジスタアクセス)の WEB画面処理 )
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// *****************************************************************************
// * SPIFFS ファイルを String に読み込む                                       *
// *****************************************************************************
int rd_SPIFFS(String fname, String &sname) {     //
  File fp = SPIFFS.open(fname,"r") ;             // ファイルをオープンする
  if (!fp) {                                     //  オープン失敗の場合
    Serial.print(fname) ;                        //
    Serial.println(" : file open error") ;       //
    return -1 ;                                  //    戻り値 -1
  }else {                                        //  オープン出来たら
    sname = fp.readString() ;                    //    String変数に読み込む
    fp.close() ;                                 //
  }                                              //
  return 0 ;                                     //  オープン出来た時のみ
}                                                //    戻り値 0
                                                 //
// ****************************************************************************
// * ステーションモードで サーバーを起動                                      *
// ****************************************************************************
void start_STA_server() {
  int lpcnt = 0 ;                                    // ループカウント
  int lpcnt2 = 0 ;                                   // ループカウント2
 
  WiFi.config(wifi_ip, wifi_gw, wifi_sm, wifi_dns);  // Set fixed IP address
  delay(10) ;                                        //
  WiFi.begin(wifi_ssid, wifi_pass);                  // wifi 開始
  lpcnt = 0 ;                                        //
  lpcnt2 = 0 ;                                       //
  while (WiFi.status() != WL_CONNECTED) {            // 接続確認
      lpcnt += 1 ;                                   //
      if (lpcnt > 4) {                               //
        WiFi.begin(wifi_ssid, wifi_pass);            // 4回目(2秒) で再度開始指示
        lpcnt = 0 ;                                  //
        lpcnt2 += 1 ;                                //
      }                                              //
      if (lpcnt2 > 5) {                              // 2秒x5 接続できなければ、
        stamode = false ;                            // APモードにして
        ESP.restart() ;                              // 再起動
      }                                              //
      Serial.print(".");                             //
      delay(500);                                    //   0.5秒毎にチェック
  }                                                  //
  server.begin();                                    // サーバー開始
}
 
// *****************************************************************************
// * HTML 送信処理                                                             *
// *****************************************************************************
 
// ----------------------------------------------------------------------------
// - CONF_HTML 送信                                                           -
// ----------------------------------------------------------------------------
void send_MAIN_html(WiFiClient client) {
  String htmlwk ;
 
  htmlwk = html_MAIN ;                          // htmlwk に HTML をコピー
  htmlwk.replace("$s_adr",String(sadr,HEX)) ;       // 変数を値に置き換える
  htmlwk.replace("$reg_adr",String(regadr,HEX)) ;   // 変数を値に置き換える
  htmlwk.replace("$wr_dt",String(wrdt,HEX)) ;       // 変数を値に置き換える
  htmlwk.replace("$rd_dt",String(rddt,HEX)) ;       // 変数を値に置き換える
  htmlwk.replace("$rdt00",String(dmpdt[0],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt01",String(dmpdt[1],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt02",String(dmpdt[2],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt03",String(dmpdt[3],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt04",String(dmpdt[4],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt05",String(dmpdt[5],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt06",String(dmpdt[6],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt07",String(dmpdt[7],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt08",String(dmpdt[8],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt09",String(dmpdt[9],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt0a",String(dmpdt[10],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt0b",String(dmpdt[11],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt0c",String(dmpdt[12],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt0d",String(dmpdt[13],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt0e",String(dmpdt[14],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt0f",String(dmpdt[15],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt10",String(dmpdt[16],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt11",String(dmpdt[17],HEX)) ;  // 変数を値に置き換える
  htmlwk.replace("$rdt12",String(dmpdt[18],HEX)) ; // 変数を値に置き換える
  htmlwk.replace("$rdt13",String(dmpdt[19],HEX)) ; // 変数を値に置き換える
  htmlwk.replace("$rdt14",String(dmpdt[20],HEX)) ; // 変数を値に置き換える
  htmlwk.replace("$rdt15",String(dmpdt[21],HEX)) ; // 変数を値に置き換える
  htmlwk.replace("$footer",foot_msg ) ;         // 変数を値に置き換える
 
  send_html(client,htmlwk) ;                    // HTML 送信処理
 
}
 
// ----------------------------------------------------------------------------
// - HTML 送信処理                                                            -
// ----------------------------------------------------------------------------
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                                       //
}
 
// ----------------------------------------------------------------------------
// - XHR RESPONSE_HTML 送信                                                   -
// ----------------------------------------------------------------------------
void send_resp_html(WiFiClient client) {        //
  String htmlwk ;                               // HTML 編集用 ワーク
                                                //
  htmlwk = html_resp ;                          // htmlwk に HTML をコピー
                                                //
  // 変数を値に変換-----------------------------//
  htmlwk.replace("$cnf_text",s_config) ;        // 変数に 設定文字列をセット
                                                //
  send_html(client,htmlwk) ;                    // HTML 送信処理
      Serial.print("xhr html  :"); Serial.println(htmlwk);
# ifdef DEBUG_WiFi                              //
      Serial.print("xhr value :"); Serial.println(duty);
#endif                                          //
}                                               //
                                                //
 
// *****************************************************************************
// * フォームデータ処理                                                        *
// *****************************************************************************
int  proc_form(String &line) {
  String s_work ="" ;
  int xhr = 0 ;
 
  if (line.indexOf("GET /?") != -1) {            // "form" が押下された時
    if (line.indexOf("config=") != -1) {         // wifi 設定なら
      config_mode = true ;                       //   設定モードにする
    }                                            //
    if (line.indexOf("cnfdl") != -1) {           // config.txt のダウンロード時
      config_dl = true ;                         //   設定ダウンロード要求フラグ ON
      xhr = 1 ;                                  //   XHR 応答にする。
    }                                            //
    if (line.indexOf("read") != -1) {            // "read" が押下された時
      if (line.indexOf("sadr=") != -1) {         //   sadr
        sadr   = getvalue_h(line,"sadr=") ;      //     sadr に続く数値を変数にセット
      }                                          //
      if (line.indexOf("regadr=") != -1) {       //   regadr
        regadr = getvalue_h(line,"regadr=") ;    //     sadr に続く数値を変数にセット
      }                                          //
      rd_req = true ;                            //   リード要求フラグを ON
    }                                            //
    if (line.indexOf("write") != -1) {           // "write" が押下された時
      if (line.indexOf("sadr=") != -1) {         //   sadr
        sadr   = getvalue_h(line,"sadr=") ;      //     sadr に続く数値を変数にセット
      }                                          //
      if (line.indexOf("regadr=") != -1) {       //   regadr
        regadr = getvalue_h(line,"regadr=") ;    //     sadr に続く数値を変数にセット
      }                                          //
      if (line.indexOf("wrdt=") != -1) {         //   wrdt
        wrdt   = getvalue_h(line,"wrdt=") ;      //     wrdt に続く数値を変数にセット
      }                                          //
      wr_req = true ;                            //   ライト要求フラグをON
    }                                            //
    if (line.indexOf("dump") != -1) {            // "dump" が押下された時
      dmp_req = true ;                           //    ダンプ動作要求フラグを ON
    }                                            //
  }                                              //
  return xhr ;                                   //
}                                                //
                                                 //
// 要素名に続く値(文字列)を取得する --------------------------------------------
String getvalue_s(String &line,String param) {
  String val="" ;
  int pos = 0 ;
 
  if ((pos=line.indexOf(param)) != -1) {          // 要素名の位置を取得
    pos += param.length() ;                       //
    while((line.charAt(pos) != '&') & (line.charAt(pos) != '\n')) {
      val += line.charAt(pos++) ;                 //  '&' か 行末 まで文字を取得
    }                                             //
  }                                               //
  return val ;                                    //  取得した文字列を返す
}
 
// 要素名に続く値(数値)を取得する ---------------------------------------------
int getvalue_i(String &line,String param) {
  String val="" ;
  int pos = 0 ;
 
  if ((pos=line.indexOf(param)) != -1) {          // 要素名の位置を取得
    pos += param.length() ;                       //
    while((line.charAt(pos) >= '0') & (line.charAt(pos) <= '9')) {
      val += line.charAt(pos++) ;                 //  数値でなくなるまで文字を
    }                                             //  取得
  }                                               //
  return val.toInt() ;                            //  数値に変換して返す
}
 
// 要素名に続く値(数値(HEX))を取得する ----------------------------------------
int getvalue_h(String &line,String param) {
  String val="" ;
  int pos = 0 ;
  byte c= 0 ;
  int dt = 0 ;
 
  if ((pos=line.indexOf(param)) != -1) {          // 要素名の位置を取得
    pos += param.length() ;                       //
    do {                                          //
      c = line.charAt(pos++) ;                    //
      if ((c>='0') & (c<='9')) {                  // 数値の場合
        dt = dt*16 + ( c - 0x30) ;                   //
      } else if ((c>='a') & (c<='f')) {           //
        dt = dt*16 + (c - 87) ;                      // 小文字 a~f の場合
      } else if ((c>='A') & (c<='F')) {           // 大文字 A~F の場合
        dt = dt*16 + (c - 55) ;                      //
      } else {                                    // 16進数値以外
        c = 0xff ;                                //
      }                                           //
    } while (c != 0xff) ;                         //
  }                                               //
  return dt ;                                     //  数値を返す
}
 
// -----------------------------------------------------------------------------

MAIN処理 (主に I2Cアクセス の関数)
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
/* +=======================================================================+ */
/* | MAIN 処理                                                             | */
/* +=======================================================================+ */
 
// I2C WR/READ ----------------------------------------------------------------
void I2C_BWR(byte TGT, byte REGADR, byte DATA) {
  Wire.beginTransmission(TGT);         // transmit to device #TGT
  Wire.write(REGADR);                  // send REG address (REGADR)
  Wire.write(DATA);                    // send write data (DATA)
  Wire.endTransmission();              // end transmit
  Serial.print("TGT=") ;
  Serial.print(TGT) ;
  Serial.print(" ,  REGADR=") ;
  Serial.print(REGADR) ;
  Serial.print(" , WRDT=") ;
  Serial.print(DATA) ;
  Serial.println(" ") ;
}
 
byte I2C_BRD(byte TGT,byte REGADR) {
  byte data = 0 ;
  Wire.beginTransmission(TGT);         //  transmit to device #TGT
  Wire.write(REGADR);                  //  send REG address (REGADR)
  Wire.endTransmission();              //  end transmit
  Wire.requestFrom(TGT, 1);            // request 1 byte from slave device #TGT
  data = Wire.read();                  // receive 1 byte
  Serial.print("TGT=") ;
  Serial.print(TGT) ;
  Serial.print(" ,  REGADR=") ;
  Serial.print(REGADR) ;
  Serial.print(" , RDDT=") ;
  Serial.print(data) ;
  Serial.println(" ") ;
 
   
  return data ;
}
 
void reg_dmp() {
                                                 //
  dmpdt[0]  = I2C_BRD(sadr,0) ;                  // REG0 リード
  dmpdt[1]  = I2C_BRD(sadr,1) ;                  // REG0 リード
  dmpdt[2]  = I2C_BRD(sadr,2) ;                  // REG0 リード
  dmpdt[3]  = I2C_BRD(sadr,3) ;                  // REG0 リード
  dmpdt[4]  = I2C_BRD(sadr,4) ;                  // REG0 リード
  dmpdt[5]  = I2C_BRD(sadr,5) ;                  // REG0 リード
  dmpdt[6]  = I2C_BRD(sadr,6) ;                  // REG0 リード
  dmpdt[7]  = I2C_BRD(sadr,7) ;                  // REG0 リード
  dmpdt[8]  = I2C_BRD(sadr,8) ;                  // REG0 リード
  dmpdt[9]  = I2C_BRD(sadr,9) ;                  // REG0 リード
  dmpdt[10]  = I2C_BRD(sadr,10) ;                // REG0 リード
  dmpdt[11]  = I2C_BRD(sadr,11) ;                // REG0 リード
  dmpdt[12]  = I2C_BRD(sadr,12) ;                // REG0 リード
  dmpdt[13]  = I2C_BRD(sadr,13) ;                // REG0 リード
  dmpdt[14]  = I2C_BRD(sadr,14) ;                // REG0 リード
  dmpdt[15]  = I2C_BRD(sadr,15) ;                // REG0 リード
  dmpdt[16]  = I2C_BRD(sadr,16) ;                // REG0 リード
  dmpdt[17]  = I2C_BRD(sadr,17) ;                // REG0 リード
  dmpdt[18]  = I2C_BRD(sadr,18) ;                // REG0 リード 18 : 0x12
  dmpdt[19]  = I2C_BRD(sadr,19) ;                // REG0 リード 19 : 0x13
  dmpdt[20]  = I2C_BRD(sadr,20) ;                // REG0 リード 20 : 0x14
  dmpdt[21]  = I2C_BRD(sadr,21) ;                // REG0 リード 21 : 0x15
 
}


0 件のコメント:

コメントを投稿