ESP-WROOM-02を2個使って片方がサーバ、もう片方がクライアントとして接続し、TCPソケット通信をしてみます。
UDPのサンプルは良く見るけど、TCPのソケット通信はなかなか見つからなかったので実験をかねて作成してみました。
クライアント側を電池で動かせばリモコンとして使えそうです。
概要:
・Arduinoの開発環境でプログラミングしてESP-WROOM-02に書込む
・サーバ側はSoftAPモードでWiFiアクセスポイントを開設
・クライアント側はSWを押すとコマンドをサーバに送る
・サーバ側は送られて来たコマンドを見てLEDをON/OFFする
動作イメージ
クライアント側のSWを押すとサーバ側のLEDが光ります
//サーバ側プログラム #include <ESP8266WiFi.h> static const char *SSID = "WROOM-B'MICOM"; static const char *PASSWD = "password"; const int LED1 = 12; //SW1のIOピン const int LED2 = 16; //SW2のIOピン const int LED3 = 5; //SW3のIOピン const int LED4 = 4; //SW4のIOピン IPAddress ip(192, 168, 0, 33); //IPAddress gateway(192, 168, 0, 1); //IPAddress netmask(255, 255, 255, 0); WiFiServer server(26842); //Port番号 void setup() { Serial.begin(115200); Serial.println(); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(LED4, OUTPUT); //起動時LEDを光らせてみる digitalWrite(LED1, HIGH); delay(100); digitalWrite(LED1, LOW); digitalWrite(LED2, HIGH); delay(100); digitalWrite(LED2, LOW); digitalWrite(LED3, HIGH); delay(100); digitalWrite(LED3, LOW); digitalWrite(LED4, HIGH); delay(100); digitalWrite(LED4, LOW); //WiFiアクセスポイントを開始 WiFi.mode(WIFI_AP); WiFi.softAP(SSID, PASSWD); WiFi.softAPConfig(ip, WiFi.gatewayIP(), WiFi.subnetMask()); //WiFi.softAPConfig(ip, gateway, netmask); WiFi.begin(); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP Started. myIP address: "); Serial.println(myIP); //Portのlistenを開始 server.begin(); Serial.println("Server started"); } void loop() { String cmd; cmd = rcvCommand(); //受信したコマンドに対応したLEDを点灯/消灯 if(cmd == "LED1OFF"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED1, LOW); } if(cmd == "LED1ON"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED1, HIGH); } if(cmd == "LED2OFF"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED2, LOW); } if(cmd == "LED2ON"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED2, HIGH); } if(cmd == "LED3OFF"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED3, LOW); } if(cmd == "LED3ON"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED3, HIGH); } if(cmd == "LED4OFF"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED4, LOW); } if(cmd == "LED4ON"){ Serial.print("Exec: "); Serial.println(cmd); digitalWrite(LED4, HIGH); } } //コマンドを受信してそのコマンド文字列を返す String rcvCommand(){ WiFiClient client = server.available(); String rstr; if (client.connected()) { Serial.println("Connected to client"); //コマンド文字列受信(文字列が来なければタイムアウトする) rstr = client.readStringUntil('\r'); Serial.print("["); Serial.print(rstr); Serial.println("]"); //応答送信 client.print("OK\r"); //接続をクローズ client.stop(); Serial.println("Closed"); } return rstr; }
//クライアント側プログラム #include <ESP8266WiFi.h> #include <Ticker.h> #define SW_ONDELAY 4000 //SWチャタリング防止ディレイ(ループカウント数) #define SW_OFFDELAY 4000 //SWチャタリング防止ディレイ(ループカウント数) Ticker ticker1; //タイマ割り込み (LED点滅用) const char* ssid = "WROOM-B'MICOM"; const char* password = "password"; char hostIP[] = "192.168.0.33"; int hostPort = 26842; const int SW1 = 12; //SW1のIOピン const int SW2 = 16; //SW2のIOピン const int SW3 = 5; //SW3のIOピン const int SW4 = 4; //SW4のIOピン const int LED = 13; //LEDのIOピン int ledStatus = 0; //0:消灯 1:点灯 2:点滅 int sw1Status = 0; //0:OFF 1:ON int sw2Status = 0; //0:OFF 1:ON int sw3Status = 0; //0:OFF 1:ON int sw4Status = 0; //0:OFF 1:ON WiFiClient client; void setup() { Serial.begin(115200); //タイマ割り込み間隔と 割り込み関数名 LEDの点滅に使用 ticker1.attach_ms(500, ticker1_interrupt); pinMode(SW1, INPUT); pinMode(SW2, INPUT); pinMode(SW3, INPUT); pinMode(SW4, INPUT); pinMode(LED, OUTPUT); Serial.println("Booting..."); WiFi.mode(WIFI_STA); connectToWiFi(); } void connectToWiFi(){ ledStatus = 2;//0:消灯 1:点灯 2:点滅 WiFi.begin(ssid, password); delay(500); int retrycnt = 0; while(WiFi.waitForConnectResult() != WL_CONNECTED){ Serial.print("."); delay(100); retrycnt++; if(retrycnt > 100){ ESP.restart(); } } Serial.println("Connect Success"); } void loop() { if (WiFi.status() == WL_CONNECTED) { ledStatus = 1;//0:消灯 1:点灯 2:点滅 sw1process(); sw2process(); sw3process(); sw4process(); }else{ //WiFi接続が切れた Serial.println("WiFi ERR. Restart."); ESP.restart(); } } void sendSocket(String str) { if (client.connect(hostIP, hostPort)) { Serial.print("Connected:"); Serial.println(hostIP); Serial.println("Posting: " + str); //送信 client.print(str); //応答受信 client.setTimeout(1000); do{ String line = client.readStringUntil('\r'); Serial.print(line); } while (client.available() != 0); //残りがあるときはさらに受信のためループ Serial.println(); } else { Serial.println("Connection failed."); } } //SW1の処理 int sw1onCnt = 0; int sw1offCnt = 0; void sw1process(){ if(sw1Status == 0){ if(digitalRead(SW1) == HIGH){ sw1onCnt++; if(sw1onCnt == SW_ONDELAY){ //ON送信 sendSocket("LED1ON\r");; sw1Status = 1; sw1offCnt = 0; }else if(sw1onCnt > SW_ONDELAY){ sw1onCnt = SW_ONDELAY; } }else{ sw1onCnt = 0; } }else{ if(digitalRead(SW1) == LOW){ sw1offCnt++; if(sw1offCnt == SW_OFFDELAY){ //OFF送信 sendSocket("LED1OFF\r"); sw1Status = 0; sw1onCnt = 0; }else if(sw1offCnt > SW_OFFDELAY){ sw1offCnt = SW_OFFDELAY; } }else{ sw1offCnt = 0; } } } //SW2の処理 int sw2onCnt = 0; int sw2offCnt = 0; void sw2process(){ if(sw2Status == 0){ if(digitalRead(SW2) == HIGH){ sw2onCnt++; if(sw2onCnt == SW_ONDELAY){ //ON送信 sendSocket("LED2ON\r");; sw2Status = 1; sw2offCnt = 0; }else if(sw2onCnt > SW_ONDELAY){ sw2onCnt = SW_ONDELAY; } }else{ sw2onCnt = 0; } }else{ if(digitalRead(SW2) == LOW){ sw2offCnt++; if(sw2offCnt == SW_OFFDELAY){ //OFF送信 sendSocket("LED2OFF\r"); sw2Status = 0; sw2onCnt = 0; }else if(sw2offCnt > SW_OFFDELAY){ sw2offCnt = SW_OFFDELAY; } }else{ sw2offCnt = 0; } } } //SW3の処理 int sw3onCnt = 0; int sw3offCnt = 0; void sw3process(){ if(sw3Status == 0){ if(digitalRead(SW3) == HIGH){ sw3onCnt++; if(sw3onCnt == SW_ONDELAY){ //ON送信 sendSocket("LED3ON\r");; sw3Status = 1; sw3offCnt = 0; }else if(sw3onCnt > SW_ONDELAY){ sw3onCnt = SW_ONDELAY; } }else{ sw3onCnt = 0; } }else{ if(digitalRead(SW3) == LOW){ sw3offCnt++; if(sw3offCnt == SW_OFFDELAY){ //OFF送信 sendSocket("LED3OFF\r"); sw3Status = 0; sw3onCnt = 0; }else if(sw3offCnt > SW_OFFDELAY){ sw3offCnt = SW_OFFDELAY; } }else{ sw3offCnt = 0; } } } //SW4の処理 int sw4onCnt = 0; int sw4offCnt = 0; void sw4process(){ if(sw4Status == 0){ if(digitalRead(SW4) == HIGH){ sw4onCnt++; if(sw4onCnt == SW_ONDELAY){ //ON送信 sendSocket("LED4ON\r");; sw4Status = 1; sw4offCnt = 0; }else if(sw4onCnt > SW_ONDELAY){ sw4onCnt = SW_ONDELAY; } }else{ sw4onCnt = 0; } }else{ if(digitalRead(SW4) == LOW){ sw4offCnt++; if(sw4offCnt == SW_OFFDELAY){ //OFF送信 sendSocket("LED4OFF\r"); sw4Status = 0; sw4onCnt = 0; }else if(sw4offCnt > SW_OFFDELAY){ sw4offCnt = SW_OFFDELAY; } }else{ sw4offCnt = 0; } } } //タイマ割り込み時の処理 void ticker1_interrupt(){ if(ledStatus == 0){ digitalWrite(LED, LOW); }else if(ledStatus == 1){ digitalWrite(LED, HIGH); }else if(ledStatus == 2){ digitalWrite(LED, !digitalRead(LED)); } }
突然申し訳ございません。
Wi-Fi通信初心者の 川勝 (カワカツ)と申します。
ESPWROOM2(8266)の勉強中で、貴H.P.にたどり着き、
「TCPソケット通信」スケッチを使わせていただきましたところ、何の障害もなくクライアントのスイッチ状態を、サーバ側のLEDに送ることができ感動致しております。これから詳しく勉強させていただこうと思うのですが、一点だけ教えていただけないでしょうか。
サーバを立ち上げ、クライアントの電源を投入(またはリセット)した後、
クライアントに “Connect Success” メッセージが出て、サーバとクライアントの
通信が確立するまで、4分程度かかるのですが、この程度の時間は妥当なのでしょうか。
動画を見ますと一瞬で繋がっているように見えますが、如何なのでしょうか。
お手数をお掛けしますが、お返事いただけましたら幸いに存じます。
クライアント側 ログ
12:17:18.180 -> r��nĒ 中略 `�Booting…
12:18:18.773 -> ….Connect Success
12:21:29.766 -> Connected:192.168.0.33
12:21:29.766 -> Posting: LED2ON
12:21:29.766 -> OK
サーバ側ログ
12:16:57.347 -> r l���b 中略 ���
12:16:58.758 -> AP Started. myIP address: 192.168.0.33
12:16:58.758 -> Server started
12:21:28.227 -> Connected to client
12:21:28.227 -> [LED2ON]
12:21:28.477 -> Closed
12:21:28.477 -> Exec: LED2ON
こんにちは!
結構前のことなので、うる覚えですが
当時やっていたときは待ち時間なくすぐに通信できたと記憶しています。
(動画は待ち時間を短くみせるようにカットとかしていません。)
お力になれずスミマセン(>_<;
川勝です。
ESP8266のボードマネージャをVer3.02 から Ver2.60 に変更することで解消しました。