Post topics, source code that relate to the Arduino Platform

User avatar
By BlitzSSS
#31579 Hi All

When using an ESP as a WiFi module issuing AT commands over serial, what is the best way to read the ESP response back with an Arduino?

I’ve seen various ways of reading from serial such as this which simply echo's the response out to the serial monitor.

Code: Select all  if (Serial1.available()) {
    int inByte = Serial1.read();
    Serial.write(inByte);
    }


I also need to be able to interpret the response and create conditions. They way I've been doing this so far is with Serial.find i.e:

Code: Select all  Serial.print(F("\nPing Router......."));
  Serial1.println(F("AT+PING=\"192.168.0.1\""));
  delay(500);
  if (Serial1.find("OK")) {
    Serial.print(F("OK"));
  } else {
    Serial.print(F("Error"));
  }


The issues I’m coming across are:
1) Sometimes delays are needed between issuing the command and waiting for a response.
.a) These delays sometimes need to be different lengths per command i.e AT+CIPMODE is instant but AT+CWJAP_DEF might take a few seconds.
.b) These delays sometimes vary for the same command i.e during very busy network traffic AT+CIPSTART or AT+CIPSEND might take longer than usual.
.c) Can’t make them too short or you miss the response, but they can't be too long either.

2) Longer responses that have multiple lines are much more difficult to read for a simple print let alone use with Serial.find. The following is an example I’ve been using with the delay needed within the loop, this delay is problematic and causes random characters to be missed if it's not exact. i.e
Code: Select all  Serial1.println(F("AT+CIFSR"));
  while (Serial1.available()) {
    delayMicroseconds(460);
    char inByte = Serial1.read();
    Serial.write(inByte);
  }


Can anyone offer any suggestions on better ways I can achieve this? I need to be able to read the response for error checking and other conditions.

Thanks
User avatar
By gapdev
#32393 I use functions similar to these in a Library I'm developing.

Note that you will need to use the Streaming and Delay Libraries.

Kenny

Code: Select all#include <Arduino.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <Delay.h>
#include <Streaming.h>

   char buf[256];                                // buffer to gather ESP responses

// Get a response from ESP
// return when string received or timeout
// returns 1 if expected response received, 0 if not

GetResponse(long wait_time, char const *send_str, char const *match)
{
   int ret = 0;

   espSerial << send_str << endl;

   ret = espWait(wait_time, match);              // Wait for match to arrive

   return(ret);
}

// Get a response from ESP
// return when string received or timeout
// returns 1 if expected response received, 0 if not
// Similar to GetResponse, but doesn't send a command

espWait(long wait_time, char const *match)
{
   char c;
   int n        = 0;
   int ret      = 0;
   int gotfirst = 0;                             // true if 1st character of string received

   NonBlockDelay wt;                             // Allows us to do something while waiting

   memset(buf, 0, sizeof(buf));

   wt.Delay(wait_time);                          // seconds to wait for response

   while(!wt.Timeout())
      {
      if (espSerial.available() > 0)             // if something there
         {
         c = espSerial.read();                   // read  character

         if (c >= 32 && c <= 127)                // Store ASCII only
            {
            if (!gotfirst && c == match[0])      // does this char match 1st character of match?
               ++gotfirst;                       //   yes. start storing

            if (gotfirst)                        // don't start storing data until character
               {                                 //   matches 1st byte of string
               buf[n++] = c;                     // store character
               buf[n]   = 0;                     // give string a NULL

               if (strcasestr(buf,match))        // do we have a match ?
                  {
                  ret = 1;                       // yes
                  break;
                  }

               if (n == sizeof(buf)-1)           // don't overflow string
                  {
                  n = 0;                         // restart at beginning of string
                  }
               }
            }
         }
      }

   return(ret);
}
User avatar
By BlitzSSS
#32591 Thank you gapdev, I admit that I haven't tried your code yet but I will.

I've also played more and discovered the following which has improved things (but still not perfect) with doing it the way I have been, could anyone offer any comments?

1) Serial.flush after issueing each command to ensure the command has been sent in full before continuing
2) Turning off command echo has helped (ATE0)
3) Delays of atleast 500ms are required between sending commands to avoid busy s and busy p errors from the ESP
4) Delays after issuing commands and reading the response may not be nessesary with Serial.flush and Serial.find (blocking).
5) The serial buffer may still contain responses from previous commands so Serial.find may reporting on results from previous commands and not the latest?