ESP32[13] Wi-Fi 通信 (softAP)

ES32はWi-Fiモジュールが標準でついているので簡単にWi-Fi通信が行えます。ここでは、ESP32をルーターとして機能させてみます。

ルーターとは複数のクライアントが接続できるサーバーです。具体的には1つのESP32をルーターにしてWi-Fiで複数のクライアントを接続させてクライアントとルーター間でデータのやり取りをします。通信にはUDPを用いています。TCP/IPでもできるとは思いますが、小さいデータのやり取りならUDPのほうが楽だからです。

// AP側(サーバー側)

#include <WiFi.h>
#include <WiFiUdp.h>

const char pass[] = "password";  // password
const char ssid[] = "SSID"; // SSID

const IPAddress ip(192, 168, 4, 1);       // IPアドレス
const IPAddress subnet(255, 255, 255, 0); // サブネットマスク
static const char *kRemoteIpadr = "192.168.4.255";  //送信先のIPアドレス (BC)
char data[256];

static WiFiUDP wifiUdp;
static WiFiUDP udp;

const int localPort = 10000;      // ポート番号
IPAddress myIP;

static void Serial_setup()
{
  Serial.begin(115200);
  Serial.println(""); // to separate line
}

void ip_port_set() {
  WiFi.softAPConfig(ip, ip, subnet); // IPアドレス、ゲートウェイ、サブネットマスクの設定
  wifiUdp.begin(localPort);
}

void setup() {
  ip_port_set();
  Serial_setup();
  ssid0_set();
  sprintf(data, "123456789\0");
  Serial.printf("Router Starts\n");
}

void ssid0_set() {
  WiFi.softAP(ssid, pass);           // SSIDとパスの設定
  delay(200);                        // 追記:このdelayを入れないと失敗する場合がある
  WiFi.softAPConfig(ip, ip, subnet); // IPアドレス、ゲートウェイ、サブネットマスクの設定
  delay(100);
  myIP = WiFi.softAPIP();
  udp.begin(localPort);  // UDP通信の開始(引数はポート番号)
}

void loop()
{
  char rv_data[255];
  int i;
  int rec_size;

  // データ送信
  wifiUdp.beginPacket(kRemoteIpadr, localPort);
  for (i = 0; i < 10; i++) {
    wifiUdp.write(data[i]);
  }

  wifiUdp.endPacket();

  //データ受信
  if (rec_size = wifiUdp.parsePacket()) {
    wifiUdp.read(rv_data, 255);
    Serial.printf("%s\n", rv_data);
  }

  delay(500);
}
// クライアント側

#include <WiFi.h>
#include <WiFiUdp.h>
#define TRUE 1
#define FALSE 0
const char pass[] = "password";  // password
const char ssid[] = "SSID"; // SSID

const IPAddress ip(192, 168, 4, 3);       // IPアドレス(ゲートウェイも兼ねる)
const IPAddress subnet(255, 255, 255, 0); // サブネットマスク

static WiFiUDP udp;
static const char *kRemoteIpadr = "192.168.4.255";  //送信先のIPアドレス ブロードキャスト
static const int localPort = 10000; //送信先のポート

hw_timer_t * timer = NULL; //timer 初期化
int msec; //msec カウンター用グローバル変数
int msec_100; // 100msec カウンター
int counter_100msec;
int rec_size;
int reconnect;
char data[256];

void IRAM_ATTR msecond_100() {
  msec_100++;
  if (msec_100 < 0) msec_100 = 0;
  counter_100msec = counter_100msec - 1;
  if (counter_100msec < 0) counter_100msec = 0;
}


#define RE_CONNECT 50 // 5 sec //切断したときに、再接続を開始するまでの時間

void setup() {
  Serial.begin(115200);
  Serial.println(""); // to separate line
  // msec timer start
  timer = timerBegin(0, 80, true); //timer=1us
  timerAttachInterrupt(timer, &msecond_100, true);
  timerAlarmWrite(timer, 100000, true); // 100ms
  timerAlarmEnable(timer);
  sprintf(data, "0123456789");

  Serial.printf("Client Starts\n");

  WiFi.begin(ssid, pass);
  delay(100);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println("connected");
  udp.begin(localPort);  // UDP通信の開始(引数はポート番号)
  counter_100msec = RE_CONNECT;
}

void loop() {
  char rv_data[255];
  int i;

  if (counter_100msec == 0) {
    reconnect = TRUE;
  }

  // データ受信

  if (rec_size = udp.parsePacket()) {

    counter_100msec = RE_CONNECT; // re connect counter resets.

    udp.read(rv_data, 255);

    Serial.printf("%s\n", rv_data);

    //データ送信

    Serial.printf("%s\n", data);
    udp.beginPacket(kRemoteIpadr, localPort);
    for (i = 0; i < sizeof(data); i++) {
      udp.write(data[i]);
    }
    udp.write('\0');
    udp.endPacket();

    delay(100);

    //再接続が必用なら再接続する。
    if (reconnect == TRUE) {

      WiFi.disconnect();
      delay(100);
      WiFi.begin(ssid, pass);
      while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
      }
      Serial.println(" connected");
      //   udp.begin(localPort);   UDP通信の開始(引数はポート番号)
      counter_100msec = RE_CONNECT;
      reconnect = FALSE;
    }
  }
}