ESP-WROOM-02 TCPソケット通信

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));
  }
}

「ESP-WROOM-02 TCPソケット通信」への3件のフィードバック

  1. 突然申し訳ございません。
    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

  2. こんにちは!
    結構前のことなので、うる覚えですが
    当時やっていたときは待ち時間なくすぐに通信できたと記憶しています。
    (動画は待ち時間を短くみせるようにカットとかしていません。)
    お力になれずスミマセン(>_<;

  3. 川勝です。
    ESP8266のボードマネージャをVer3.02 から Ver2.60 に変更することで解消しました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です