ESP8266をWifiモデムとして使う

ライブラリを使わないSocket通信(クライアント編)


ESP8266用のライブラリはいくつかありますが、所詮シリアル通信でATコマンドを投げているだけなので、
ライブラリを使わずに通信してみることにしました。
一連のATコマンドについてはこ ちらを参考にさせていただきました。

最初に、Raspberryがサーバー、Arduino+ESP-01がクライアントの動作を紹介します。
Raspberry側のプログラムはこちらと同じものを使いま す。

Arduino側のスケッチは以下の通りです。
SSIDにはアクセスポイントのSSID、PASSWORDにはそのパスワード、SERVERには相手側のIPアドレスを指定してください。
sendCommand() waitForString() errorDisplay() clearBuffer() はセットなので
1つにまとめてしまってもいいかもしれません。

/*
 * ESP8266 TCP Client with AT Command
 *  
 * ESP8266----------ATmega
 * ESP8266_TX    -> RX(D3)
 * ESP8266_RX    -> TX(D2)
 *
 */

#include <SoftwareSerial.h>

#define rxPin 2    // PD2
#define txPin 3    // PD3

#define SSID        "APのSSID"
#define PASSWORD    "APのパスワード"
#define SERVER      "192.168.10.10"
#define PORT        "9876"
#define INTERVAL    1000

//answer strings from ESP
//char str_buffer[64];
//command strings to ESP
char cmd[64];
unsigned long lastmillis;

SoftwareSerial myESP8266(rxPin, txPin); // RX, TX

//Wait for specific input string until timeout runs out
bool waitForString(char* input, int length, unsigned int timeout) {

  unsigned long end_time = millis() + timeout;
  char current_byte = 0;
  int index = 0;

   while (end_time >= millis()) {
   
      if(myESP8266.available()) {
       
        //Read one byte from serial port
        current_byte = myESP8266.read();
        Serial.print(current_byte);
        if (current_byte != -1) {
          //Search one character at a time
          if (current_byte == input[index]) {
            index++;
           
            //Found the string
            if (index == length) {             
              return true;
            }
          //Restart position of character to look for
          } else {
            index = 0;
          }
        }
      }
  } 
  //Timed out
  return false;
}

//Remove all bytes from the receive buffer
void clearBuffer() {
  while (myESP8266.available())
    myESP8266.read();
  Serial.println("");
}

//Send AT command
void sendCommand(char* buff) {
  Serial.print(buff);
  Serial.println("-->");
  myESP8266.println(buff);
  myESP8266.flush();
}

//Print error
void errorDisplay(char* buff) {
  Serial.print("Error:");
  Serial.println(buff);
  while(1) {}
}

//Receive Message
int readResponse(int id, char * buf,int sz_buf, int timeout) {
  int len=0;
  int flag=0;
  int datalen;
  long int time = millis();

  // id < 0  +IPD,nn:ReceiveData
  // id = 0  +IPD,0,nn:ReceiveData
  // id > 0  +IPD,id,nn:ReceiveData
  while( (time+timeout) > millis()) {
    while(myESP8266.available())  {
      char current_byte = myESP8266.read(); // read the next character.
      Serial.print(current_byte);
      if (flag == 0) {
        if (current_byte != 0x2c) continue;
        flag++;
        if (id < 0) flag++;
      } else if (flag == 1) {
        if (current_byte != 0x2c) continue;
        flag++;
      } else if (flag == 2) {
        if (current_byte == 0x3a) { // :
          datalen=atoi(buf);
          flag++;
          len=0;
        } else {
          buf[len++]=current_byte;
          buf[len]=0;
        }
      } else {
        buf[len++]=current_byte;
        if (len == sz_buf) return -len;
        buf[len]=0;
        if (len == datalen) return len;
      }
    } // end while
  } // end while
  return -len;
}

void setup(void)
{
  Serial.begin(9600);

  //Make sure ESP8266 is set to 4800
  myESP8266.begin(4800);
  delay(100);

  //Local echo off
  sendCommand("ATE0");
  if (!waitForString("OK", 2, 1000)) {
    errorDisplay("ATE0 Fail");
  }
  clearBuffer();

  //Disconnect from AP
  sendCommand("AT+CWQAP");
  if (!waitForString("OK", 2, 1000)) {
    errorDisplay("AT+CWQAP Fail");
  }
  clearBuffer();

  //Set Wifi Station mode
  sendCommand("AT+CWMODE=1");
  if (!waitForString("OK", 2, 1000)) {
    errorDisplay("AT+CWMODE fail");
  }
  clearBuffer();

  //Connect to AP
  sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", SSID, PASSWORD);
  sendCommand(cmd);
  if (!waitForString("OK", 2, 10000)) {
    errorDisplay("AT+CWJAP Fail");
  }
  clearBuffer();

  //Get local IP address
  sendCommand("AT+CIPSTA?");
  if (!waitForString("OK", 2, 1000)) {
    errorDisplay("AT+CIPSTA? Fail");
  }
  clearBuffer();

  lastmillis = millis();
}

void loop(void) {
  static int num = 0;
  char smsg[64];
  char rmsg[64];
  short sz_smsg;

  if (Serial.available() > 0) {
    char inChar = Serial.read();
    Serial.print("KeyIn");
    sendCommand("AT+CWQAP");
    if (!waitForString("OK", 2, 1000)) {
      errorDisplay("AT+CWQAP Fail");
    }
    clearBuffer();
    Serial.println("client end");
    while(1) { }
  }

  if (((signed long)(millis() - lastmillis)) > 0) {
    lastmillis = millis() + INTERVAL;
    //Start connection
    //Send AT+CIPSTART="TCP","192.168.XXX.XXX",PORT
    sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s", SERVER,PORT);
    sendCommand(cmd);
    if (!waitForString("OK", 2, 10000)) {
      errorDisplay("AT+CIPSTART Fail");
    }
    clearBuffer();
    sprintf(smsg,"data from arduino %05d",num);
    num++;
    sz_smsg=strlen(smsg);
    //Send AT+CIPSEND=nn
    sprintf(cmd,"AT+CIPSEND=%d",sz_smsg);
    sendCommand(cmd);
    if (!waitForString(">", 1, 1000)) {
      errorDisplay("AT+CIPSEND Fail");
    }
    clearBuffer();
    //Send data
    sendCommand(smsg);
    if (!waitForString("SEND OK", 7, 1000)) {
       errorDisplay("AT+CIPSEND Fail");
    }
    clearBuffer();
    //Read data
    int readLen = readResponse(-1, rmsg, sizeof(rmsg), 5000);
    Serial.println();
    Serial.print("readLen=");
    Serial.println(readLen);
    if (readLen < 0) {
       errorDisplay("Server not response");
    }
    clearBuffer();
    //Close TCP connection
    sendCommand("AT+CIPCLOSE");
    if (!waitForString("OK", 2, 1000)) {
      errorDisplay("AT+CIPCLOSE Fail");
    }
    clearBuffer();
  }
}

実行結果はこちらと全く同じとなります。
なぁんだ...ライブラリいらないじゃん...
次回はサーバー側の動作をライブラリ無しでやってみます。