Arduino and ESP8266, CIPSTA_DEF command

After spending quite a bit of time trying to programmatically communicate between the Arduino and an ESP8266 module, I finally have something that seems to work reasonably reliably. I first determine the baud rate by switching baud rate, sending an AT command and checking for an OK response. Once I get an OK response, I send the following sequence:

AT+CWJAP?   // Are we joined to an AP?
AT+CIFSR    // What's my IP address

If the AP name and IP address are correct then a valid connection is assumed. If either of the above are not correct then the configuration is assumed to be invalid and the following sent to configure it:

AT+CWDHCP_DEF=1,0               // Disable DHCP (need to use a static IP)
AT+CWQAP                        // Quit the current AP
AT+CWJAP="ESSID","password"     // AP name and password specified
AT+CIPSTA_DEF="10.210.210.117","10.210.210.125","255.255.255.192"  // Set an IP address

This does actually work up to the second command, but the final command seems to fail. If I do not disable DHCP, then I do get an IP address assigned by the DHCP server so I know that I am connecting to the WiFi network.

The last command that sets a static IP address echoes backas follows:

AT+CIPSTA_DEF="10.210.210.117","10.210.210.125","255.255.255.19

The ‘2"’ is truncated and the command does not seem to get executed as the IP address is not changed. If I paste the command into the serial monitor and send it manually, the it works as expected. I am currently programming using a UNO with the ESP8266 connected to pins 5 and 6, and I am using softwareserial to communicate with it.

Anyone know why this fails when sent programmatically but works manually?

BTW, I also tried this:

AT+CIPSTA="10.210.210.117","10.210.210.125","255.255.255.192"

The deprecated variant of the command without “_DEF” seems to get echoed back complete but I do not get the OK reply and the IP address is not getting set.

This is the sequence of code that sends the config commands:

bool wifiCfg(){

  // Set operating mode and disable DHCP
  Serial1.println(F("AT+CWDHCP_DEF=1,0"));
  if (!replyContains("OK",400,200)) return false;
  
  // If already connected to some AP then disconnect
  Serial1.println(F("AT+CWQAP"));
  if (replyContains("OK",400,200)){
    // Connect to defined AP
    Serial1.println(F("AT+CWJAP=\"" AR_WL_NAME "\",\"" AR_WL_PASS "\""));
    if (!replyContains("CONNECTED", 10000, 800)) return false;
    // Apply IP address
    Serial1.println(F("AT+CIPSTA_DEF=\"" AR_WL_ADDR "\",\"" AR_WL_GATE "\",\"" AR_WL_MASK "\""));
    if (!replyContains("OK", 400, 300)) return false;
  }

  // Success!
  return true;
}

This is the function replyContains() that waits for the response:

bool replyContains(const char* reply, unsigned int waitA, unsigned int waitB) {

  // Clear buffer
  uint8_t rl = strlen(reply);
  uint8_t idx = 0;
  uint8_t c = 0;

  int i = 0;
  int j = 0;

  // Default timeouts
  if (!waitA) waitA = 1000;
  if (!waitB) waitB = 100;

  // Set timeout threshold
  unsigned long timeout = millis() + waitA;

  i = 0;
  j = 0;
  while (millis() < timeout) {

    while (esp8266.available()) {
      
      // Read a character
      c = esp8266.read();
      i++;
    
//      Serial.print(c, HEX);
//      Serial.print("[");
      Serial.print((char)c);
//      Serial.print("] ");

      // Break on LF
/*
      if (c == 10) {
        if (idx < rl) idx = 0;
        break;
      }
*/
      // Match the character
      if ((c == reply[idx]) && (idx < rl)) {
        idx++;  // Matched, now look for the next one
      }else{
        if (idx != rl) idx = 0; // Not matched - reset matching process
      }
    }

    if (j>0) {
      if (i>0) {
        // Received some chars - update count, wait for more and go around loop again
        j = j + i;
        i = 0;
      }else{
        // If nothing further received then exit loop
        break;
      }
    }
    delay(waitB);
  }

  Serial.println();

Serial.print(F("RL:"));Serial.println(rl);
Serial.print(F("IDX:"));Serial.println(idx);

  if (idx == rl) {Serial.print(F("Found: "));Serial.println(reply);};

  // Reply was matched
  if (idx == rl) return true;

  // Reply was not matched
  return false;
}

is 255.255.255.0 a valid subnet mask of class A network (10.)?

Sorry, I messed that up. Have corrected it in the posted text. The mask should end in .192. Apparently the ESP does not officially support subnets, but it works just fine - at least when the command is entered manually.

I dug out my Mega board, amended my sketch to use Serial1 instead of the esp8266 softwareserial device and am got the same result there. That would seem to rule out a problem with softwareserial and would appear to points to the ESP8266.

The only observation here is that in contrast to the other commands being sent, this sequence is more than 64 characters in length, but I'm not sure why that would make a difference? To test this, I split the command into two print lines like this:

Serial1.print(F("AT+CIPSTA_DEF=\"" AR_WL_ADDR "\","));
delay(200);
Serial1.println(F("\"" AR_WL_GATE "\",\"" AR_WL_MASK "\""));
if (!replyContains("OK", 400, 200)) return false;

This does seem to have fixed it and the delay was necessary. Without it, the result was the same.

This still does not explain why the command works OK when pasted into the serial monitor and sent manually?