ESP8266 accepts command but returns nothing

Hello,

This is my first post in here.
I've been struggling for a couple of days now with the module ESP8266.
I have tested it already with another arduino and I could send some test commands and receive the corresponding response. However, I am currently facing a issue where the ESP8266 receives the data but it seems that I not reading out properly the incoming data (Rx).

The code consists of 3 files:

water-monitoring.ino // master
wifi.cpp
wifi.h

(I am creating some customized wifi files to be reused in another project)

here is the code (still being developed):

water-monitoring.ino

#include<SoftwareSerial.h>
#include "wifi.h"
#define WIFI_RX PD2
#define WIFI_TX PD3

const String url = "jsonplaceholder.typicode.com";
const String endpoint = "/posts/42";
const int yellowLed = PD6;
const int redLed = PD7;
const int motorPWM = PB1;
const int lWaterLevel = PC0;
const int sWaterLevel = PC1;
unsigned long timerOne = 0;

Wifi wifi(WIFI_RX, WIFI_TX);

void setup() {
  //Setting up pin inputs and outputs
  DDRD=0x00;
  DDRB=0x00;
  DDRC=0x00;
  DDRD|=(1 << yellowLed) | (1 << redLed);
  DDRB|=(1 << motorPWM);
  DDRC&=~((1 << lWaterLevel) | (1 << sWaterLevel));

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  
  Serial.println("Serial communication started...");
  // set the data rate for the SoftwareSerial port
  wifi.init();
  wifi.getRequest(url, endpoint);
}

void loop() {
  // put your main code here, to run repeatedly:
  PORTD^=(1 << yellowLed);
  PORTD^=(1 << redLed);
}

wifi.cpp

#include <Arduino.h>
#include<SoftwareSerial.h>
#include "wifi.h"
 
void Wifi::init() {
    //ESP8266.begin(BAUD_RATE);
    Serial.println("WIFI INIT");
    
    sendCommand("AT");
    
    // AT+CWMODE (1: Station mode (client), 2 = AP mode (host), 3 : AP + Station mode)
    sendCommand("AT+CWMODE=1");
    checkFirmware();
    connect();
    connectionStatus();
};

void Wifi::setBaudRate() {
  //set baud rate
  sendCommand("AT+UART_DEF=9600,8,1,0,0");
 };
 
void Wifi::checkFirmware () {
    //AT+GMR check firmware
    sendCommand("AT+GMR");
  };

bool Wifi::connect() {
  //AT+CIPSTATUS check whether it is connected
  sendCommand("AT+CIPSTATUS");
  
  // AT+CWJAP connect to wifi
  sendCommand("AT+CWJAP=\"" + String(WIFI_SSID) + "\",\"" + String(WIFI_PASS) + "\"");

  // AT+CIFSR check ip of wifi module
  sendCommand("AT+CIFSR");
};

bool Wifi::disconnect() {
  // AT+CWQAP disconnect from current WIFI
  sendCommand("AT+CWQAP");  
};

String Wifi::connectionStatus () {
  // AT+CIPSTATUS status from the connection
  sendCommand("AT+CIPSTATUS");
};

String Wifi::getReq(String url, String endpoint) {
  
};

String Wifi::postReq(String url, String endpoint, String data) {
};

bool Wifi::sendCommand(String command){
  //printing command in the debug window
  delay(30);
  Serial.print("=> ");
  Serial.print(command);
  Serial.print(" ");
  countSendAttempts = 0;
  successfulResponse = false;
  response = "";
  
  while(countSendAttempts < SEND_ATTEMPTS) {
    countSendAttempts++;
    Serial.print(".");
    ESP8266.println(command);
    delay(100);
    if(ESP8266.find("OK")){
      Serial.print("OK");
      Serial.println(" ");
      successfulResponse = true;
      printResponse();
      break;  
    };
  }
  if(!successfulResponse) {
    Serial.print("Fail");  
  }
};

void Wifi::printResponse() {
  delay(50);
  Serial.print("RES:");
  Serial.print(getResponse());
  Serial.print("\n");
};

String Wifi::getResponse() {
  delay(50);
  if (ESP8266.available()){
     return ESP8266.readStringUntil('\n');
  }
};

void Wifi::htmlRequest(String url, String endpoint, String reqType, String data = "") {

  // AT+CIPMUX (0: single connection, 1: multiple connection)
  sendCommand("AT+CIPMUX=1");

  // AT+CWMODE (1: Station mode (client), 2 = AP mode (host), 3 : AP + Station mode)
  sendCommand("AT+CWMODE=1");

  // AT+CIPSTART establishes TCP connection
  sendCommand("AT+CIPSTART=4,\"TCP\",\"" + url + "\",80");

  String cmd = "";
  if(reqType == "GET") {
    cmd = "GET " + endpoint +  " HTTP/1.1 \r\nHost: " + url + "\r\n\r\n";     
  } else if (reqType == "POST") {
    //TODO
    cmd = "POST " + endpoint +  " HTTP/1.1 \r\nHost: " + url + "\r\n\r\n";        
    }
  // AT+CIPSTART set the command size
  sendCommand("AT+CIPSEND=4," + String(cmd.length() + 4));

  // Send the command
  sendCommand(cmd);
 };

 String Wifi::getRequest(String url, String endpoint){
    Serial.println("ENDPOINT:" + endpoint);
    htmlRequest(url, endpoint, "GET");
 };

 String Wifi::postRequest(String url, String endpoint, String data) {
  
 };

wifi.h

#ifndef Wifi_h
#define Wifi_h
#include <Arduino.h>
#include<SoftwareSerial.h>
 
#define WIFI_SSID "XXXXXX"
#define WIFI_PASS "XXXXXX"
#define BAUD_RATE 9600
#define SEND_ATTEMPTS 5
#define DEBUG true
 
class Wifi
{  private:
    uint8_t rx;
    uint8_t tx;
    uint8_t countSendAttempts;
    bool successfulResponse;
    String response;
  public:
   void init();
   bool sendCommand(String command);
   String getResponse();
   void setBaudRate();
   void checkFirmware();
   bool connect();
   bool disconnect();
   void printResponse();
   String connectionStatus();
   void htmlRequest(String url, String endpoint, String reqType, String data = "");
   String getRequest(String url, String endpoint);
   String postRequest(String url, String endpoint, String data);
   String getReq(String url, String endpoint);
   String postReq(String url, String endpoint, String data);

   SoftwareSerial ESP8266;
   Wifi(uint8_t rx, uint8_t tx) : ESP8266 (rx, tx) {
     ESP8266.begin(BAUD_RATE);
   }
};
 
#endif

and here is the serial response:

Serial communication started...
WIFI INIT
=> AT .OK 
RES:
=> AT+CWMODE=1 .OK 
RES:
=> AT+GMR .OK 
RES:
=> AT+CIPSTATUS .OK 
RES:
=> AT+CWJAP="FlixRouter","12345678!" .....OK 
RES:
=> AT+CIFSR .....Fail=> AT+CIPSTATUS .OK 
RES:
ENDPOINT:jsonplace
=> AT+CIPMUX=1 .OK 
RES:
=> AT+CWMODE=1 .OK 
RES:
=> AT+CIPSTART=4,"TCP","jsonplaceholder.typicode.com",80 .OK 
RES:
=> AT+CIPSEND=4,67 .OK 
RES:
=> GET jsonplace HTTP/1.1 
Host: jsonplaceholder.typicode.com

 ..OK 
RES:

Another problem I noticed is that the variable "endpoint" is mutating and changing its value for some unknown reason.

If anyone could shed some light on my problem, it would be really appreciated.

Thanks!
Victor

OK ends the response. you skip it all with find("OK")

Thanks for the quick reply.
I modified the while loop in wifi.cpp to

while(countSendAttempts < SEND_ATTEMPTS) {
    countSendAttempts++;
    Serial.print(".");
    ESP8266.println(command);
    delay(1000);
    response = getResponse();
    if(response.indexOf("OK") > 0){
      Serial.print("OK");
      Serial.print(response);
      Serial.println(" ");
      successfulResponse = true;
      break;  
    };
  }

and now the wifi module does not seem to acknowledge any data transmission:

Serial communication started...
WIFI INIT
 
=> AT.....Fail 
=> AT+CWMODE=1.....Fail 
=> AT+GMR.....Fail 
=> AT+CIPSTATUS.....Fail 
=> AT+CWJAP="FlixRouter","12345678!".....Fail 
=> AT+CIFSR.....Fail 
=> AT+CIPSTATUS.....FailENDPOINT:typicode.
 
=> AT+CIPMUX=1.....Fail 
=> AT+CWMODE=1.....Fail 
=> AT+CIPSTART=4,"TCP","jsonplaceholder.typicode.com",80....

you still print the line only if it contains OK. with the delay(1000) the serial buffer can overflow (not for simple commands)
remove if (ESP8266.available()){ in getResponse to let the readUntil function apply the timeout

Still failing to get the message after removing if (ESP8266.available())

still the same output with "Fail"?

Exactly ...

Serial communication started...
WIFI INIT
 
=> AT.....Fail 
=> AT+CWMODE=1.....Fail 
=> AT+GMR.....Fail 
=> AT+CIPSTATUS.....Fail 
=> AT+CWJAP="FlixRouter","12345678!".....Fail 
=> AT+CIFSR.....Fail 
=> AT+CIPSTATUS.....FailENDPOINT:typicode.
 
=> AT+CIPMUX=1.....Fail 
=> AT+CWMODE=1.....Fail 
=> AT+CIPSTART=4,"TCP","jsonplaceholder.typicode.com",80.....Fail 
=> AT+CIPSEND=4,67.....Fail 
=> GET typicode. HTTP/1.1 
Host: jsonplaceholder.typicode.com

.....Fail

print the response before searching OK in it

That is the response

Serial communication started...
WIFI INIT
 
=> AT. RES1:AT


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CWMODE=1. RES1:AT


. RES1:

. RES1:OK

OKOK
 
 
=> AT+GMR. RES1:AT


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CIPSTATUS. RES1:AT+CWMODE=1


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CWJAP="FlixRouter","12345678!". RES1:AT+CWMODE=1


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CIFSR. RES1:AT+CWMODAT+GAT+GMATAT+CAT+CIPSTATUS

ATAT+CAT+CWJAP="FlixATAT+C
. RES1:AT+CIFSR


. RES1:busy p...

. RES1:AT+CIFSR


. RES1:busy p...

Fail 
=> AT+CIPSTATUS. RES1:AT+CIFSR


. RES1:busy p...

. RES1:AT+CIFSR


. RES1:busy p...

. RES1:AT+CIPSTATUS


FailENDPOINT:typicode.
 
=> AT+CIPMUX=1. RES1:busyAT+CIPSTATUAT+CIPSTATUAT+CIPSTATUAT+CIPSTATUAT+CIPMUX=1


. RES1:
AT+CIPMUX=1


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CWMODE=1. RES1:AT+CIPMUX=1


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CIPSTART=4,"TCP","jsonplaceholder.typicode.com",80. RES1:AT+CIPMUX=1


. RES1:

. RES1:OK

OKOK
 
 
=> AT+CIPSEND=4,67. RES1:AT+CWMODE=1


. RES1:

. RES1:OK

OKOK
 
 
=> GET typicode. HTTP/1.1 
Host: jsonplaceholder.typicode.com

. RES1:AT+CWMODE=1


. RES1:

. RES1:OATAT+CAT+CIPSTART=4,ATAT+CAT+CIPSEND=4,6ATGET GET typicode. GE
. RES1:GET typicode. HTTP/1.1 


. RES1:ERROR

Fail

I fixed a small typo if(response.indexOf("OK") >= 0){ (it was > 0 before) and the getResponse() method is the following

String Wifi::getResponse() {
  delay(50);
  //if (ESP8266.available()){
     return ESP8266.readStringUntil('\n');
  //}
};

but I am still unable to see the responses from the wifi module.

don't send commands again. you only get "busy p...".

don't send commands again. you only get "busy p...".

you have echo on so you can see the responses are to previous command. you are out of sync

Any clues, what is the reason for the out of sync behavior?

send the command and wait for end 'token'
something like

bool sendCommand(const char* cmd) {
  Serial.println(cmd);
  Serial1.println(cmd);
  while (true) {
    buff = Serial1.readStringUntil('\n');
    buff.trim();
    if (buff.length() > 0) {
      Serial.println(buff);
      if (buff == "OK" || buff == "SEND OK" || buff == "ALREADY CONNECTED")
        return true;
      if (buff == "ERROR" || buff == "FAIL" || buff == "SEND FAIL")
        return false;
    }
  }
}

Thank you very much :slight_smile: Things are looking up.

Now, at least the incoming messages seem to be in sync with the commands.

One thing though still missing is the url and the endpoint of my GET requests, which seem to be changing for non apparent reason.
I define them as follows

const String url = "jsonplaceholde.typicode.com";
const String endpoint = "/posts/42";

and call the function

wifi.getRequest(url , endpoint);

which is defined as follows

String Wifi::getRequest(String url, String endpoint){
    Serial.println("URL:" + url);
    Serial.println("ENDPOINT:" + endpoint);
    htmlRequest(url, endpoint, "GET");
 };

in the serial the following is printed

URL:jsonplaceholde.typicode.com
ENDPOINT:typicode.

I am trying to figure out why the endpoint is taking another value.

if I overwrite the the url and endpoint as follows:

cmd = "GET /v2/5cdc13222d00005211f5a574 HTTP/1.1\r\nHost: mocky.io\r\n\r\n";     
sendCommand("AT+CIPSEND=4," + String(cmd.length() + 4));
sendCommand(cmd);

I get the following:

RES:AT+CIPSTART=4,"TCP","mocky.io",80
RES:4,CONNECT
RES:OK
SEND:AT+CIPSEND=4,65
RES:AT+CIPSEND=4,65
RES:OK
SEND:GET /v2/5cdc13222d00005211f5a574 HTTP/1.1
Host: mocky.io



RES:>
RES:4,CLOSED

after AT+CIPSEND, you should wait for prompt from the AT firmware. it sends '>'. then you can write the data.

if you use String, at least don't copy it as parameter. use String& (a reference to String) as function's parameter type. and if you want to put const String as parameter, then the parameter should be const String&

Juraj:
if you use String, at least don't copy it as parameter. use String& (a reference to String) as function's parameter type. and if you want to put const String as parameter, then the parameter should be const String&

This as long as you are using the Arduino to create AT-commands. (actually avoid using 'String' as much as possible) Once you start to program the ESP directly using the IDE, then you can feel more free to use the 'String' class.

I created a class to overcome the async problems I am having with the ESP8266 module. I would like to sync all commands by piping them into a String buffer[]. Whenever the buffer has data, the first String (FIFO) is sent to the ESP8266 and upon receiving a response from the ESP8266 module, the corresponding String is removed from the pipe and the next one is shifted to the first position and so on.

It was working partially until I decided to move every to Strings, and now I facing some weird things with the Serial terminal. There must be something very wrong with my code. I've been debugging it for hours now...
e.g.
At some point in the code I have the following:

  cmdHtmlToSend = "GET ";
  if(reqType == "GET") {
    //cmdHtmlToSend = "GET " + endpoint +  " HTTP/1.1\r\nHost: " + url + "\r\n\r\n";
    cmdHtmlToSend.concat(endpoint);
    cmdHtmlToSend.concat(" HTTP/1.1\r\nHost: ");
    cmdHtmlToSend.concat(url);
    cmdHtmlToSend.concat("\r\n\r\n");
    Serial.println(cmdHtmlToSend);
  } else if (reqType == "POST") {
    //TODO
       
    }

 Serial.println(cmdHtmlToSend);
   // Send the command
  addToPipe(cmdHtmlToSend);

(cmdToSend is a member of ESP8266 class)

where addToPipe(cmdHtmlToSend) is the following:

void ESP8266::addToPipe(String  cmd) {
  Serial.print("Trying to add:");
  Serial.println(cmd);
  if(cmd.length() < 1)
    return;
  for(pipeSlot = 0; pipeSlot < PIPEMAXSIZE; pipeSlot++) {
    Serial.println("IMHERE - 1");
    if(pipe[pipeSlot].indexOf(cmd) > -1) {
        Serial.println("IMHERE - 2");
       Serial.println("$DATA already exists in slot " + String(pipeSlot));
       pipeSlot = PIPEMAXSIZE;
      } else {
        Serial.println("IMHERE - 3");
        if(pipe[pipeSlot].length()>0){
          Serial.print("Slot " + String(pipeSlot) + " occupied with:");
          Serial.println(pipe[pipeSlot]);
        } else {
          Serial.print("Slot " + String(pipeSlot) + " is Empty. New data:");
          Serial.println(cmd);
          pipe[pipeSlot] = cmd;
          printPipe();
          }
        }
  }
}

and I get in the serial port

GET /posts/42 HTTP/1.1
Host: jsonplaceholder.typicode.com


Trying to add:

As you can see the String is not showing up inside the other function.
Any ideas why this String is not showing in the serial monitor?
If anyone could have a peak at my code, I would really appreciate. I could send all the files if necessary.

you should try the WiFiEsp library

Juraj:
you should try the WiFiEsp library

Where can I find this library?

Do you know whether it works with the following device:

I am driving it with an Arduino nano and an external 3V LDO.

I found the library. Thanks for the heads up :slight_smile: