Endless resetting

Hi everyone!

I’ve written the sketch below for Arduino Due and now just uploaded into a ATmega328p on a breadboard (16Mhz external).
In the compiler it says it is using 5488 FLASH and 182 RAM, which are less than the maximum.
However the microntroller keeps resetting when the command is sent:

esp8266.print(F("AT+RST\r\n")); // rst

Here is the sketch:

#define esp8266 Serial

const char PROGMEM Index_html[] = {
  "<!DOCTYPE html> \n"
  "<html lang=\"pt-BR\"> \n"
  "  <head> \n"
  "     <meta charset=\"UTF-8\" /> \n"
  "     <title>ESP8266</title> \n"
  //"      <link rel=\"stylesheet\" href=\"styles.css\"> \n"
  "  </head> \n"
  "  <body> \n"
  "    <h1> \n"
  "      <u> \n"
  "      Arduino - ESP8266 - Web Server \n"
  "      </u> \n"
  "    </h1> \n"
  "    <h2> \n"
  "      PortaDigital 8: %DR,8% \n"
  "    </h2> \n"
  "    <h2> \n"
  "     Porta Digital 9: %DR,9% \n"
  "    </h2> \n"
  "  </body> \n"
  "</html> \n"
};

void setup()
{
  esp8266.begin(115200);

  esp8266.print(F("AT+RST\r\n")); // rst
  wait(F("ready"), 10000);

  esp8266.print(F("AT+CWJAP=\"WORKGROUP\",\"49WNN7F3CD@22\"\r\n")); //connect to wifi
  wait(F("ERROR\r\n,OK\r\n"), 20000);

  esp8266.print(F("AT+CWMODE=3\r\n")); //client and server mode
  wait(F("ERROR\r\n,OK\r\n"), 5000);
  esp8266.print(F("AT+CIFSR\r\n")); //get local ip and MAC
  wait(F("ERROR\r\n,OK\r\n"), 5000);
  esp8266.print(F("AT+CIPMUX=1\r\n")); //enable multiple connections
  wait(F("ERROR\r\n,OK\r\n"), 5000);
  esp8266.print(F("AT+CIPSERVER=1,8080\r\n")); //create server at port
  wait(F("ERROR\r\n,OK\r\n"), 5000);
}

void loop()
{
  // Verifica se o ESP8266 esta enviando dados
  if (esp8266.available())
  {
    if (wait(F("+IPD,"),5000) == 0)
    {
      delay(300);

      int ConnectionId = esp8266.read() - 48;

      sendPage(Index_html, ConnectionId);
      wait(F("ERROR\r\n,OK\r\n"), 5000);

      char ConnectionInfo[(int)log10(ConnectionId) + 2];
      itoa(ConnectionId, ConnectionInfo, 10);

      esp8266.print(F("AT+CIPCLOSE="));
      esp8266.print(ConnectionInfo);
      esp8266.print(F("\r\n"));
      wait(F("ERROR\r\n,OK\r\n"), 5000);
    }
  }
}

void sendPage(const char* PROGMEM Page, int ConnectionID) {

  if (!Page) return;

  int len = strlen_P(Page);

  char ConnectionInfo[(int)log10(ConnectionID) + 2];
  itoa(ConnectionID, ConnectionInfo, 10);

  char LengthInfo[(int)log10(len) + 2];
  itoa(len, LengthInfo, 10);

  esp8266.print(F("AT+CIPSEND="));
  esp8266.print(ConnectionInfo);
  esp8266.print(F(","));
  esp8266.print(LengthInfo);
  esp8266.print(F("\r\n"));
  wait(F("ERROR\r\n,OK\r\n"), 5000);

  char c;

  for (int n = 0; n < len; n++) {
    c = pgm_read_byte(Page++);

    esp8266.print(c);
  }
}

int16_t wait(const __FlashStringHelper *ifsh, uint16_t TimeOut){
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  uint16_t Length = strlen_P(p);
  
  char string[Length+1];
  memset(string,0,sizeof(string));
  strcpy_P(string,p);
  
  return wait(string,TimeOut);
}

int16_t wait(char* Values, uint16_t TimeOut) {

  if(!Values)
    return -1;
  
  uint16_t Length = strlen(Values);

  char InputBuffer[Length + 1];
  strcpy(InputBuffer, Values);
  char CompareBuffer[Length + 1];
  memset(CompareBuffer, 0, sizeof(CompareBuffer));

  uint16_t TokenQuantity = 1;

  for (int16_t n = 0; n < Length; n++) {
    if (InputBuffer[n] == ',')
      TokenQuantity++;
  }

  char* InputTokens[TokenQuantity];
  memset(InputTokens, 0, sizeof(InputTokens));
  char* CompareTokens[TokenQuantity];
  memset(CompareTokens, 0, sizeof(CompareTokens));

  InputTokens[0] = InputBuffer;
  CompareTokens[0] = CompareBuffer;

  uint16_t TokenPosition = 1;
  for (int16_t n = 0; n < Length; n++) {
    if (InputBuffer[n] == ',') {
      InputBuffer[n] = 0;
      InputTokens[TokenPosition] = &InputBuffer[n + 1];
      CompareTokens[TokenPosition] = &CompareBuffer[n + 1];
      TokenPosition++;
    }
  }

  uint64_t timer = millis();
  char c;

  while (millis() - timer < TimeOut) {
    while (esp8266.available()) {
      c = esp8266.read();

      for (int16_t n = 0; n < TokenQuantity; n++) {
        Length = strlen(CompareTokens[n]);
        if (c == InputTokens[n][Length])
          CompareTokens[n][Length] = c;
        else if (Length > 0)
          memset(CompareTokens[n], 0, Length);

        if (!strcmp(InputTokens[n], CompareTokens[n]))
          return n;
      }
    }
  }
  return -1;
}

I can’t see any problem. Any help?

And a comment:
The wait() function just wait for strings in the serial input, that I declare in the argument and this function is working well (I replaced every call with delay() but the problem hasn’t been solved).

In the compiler it says it is using 5488 FLASH and 182 RAM

With all those char arrays and char pointer arrays, using only 182 bytes of SRAM is completely unrealistic.

PaulS: With all those char arrays and char pointer arrays, using only 182 bytes of SRAM is completely unrealistic.

Did you not notice most of them are in FLASH???

Regards, Ray L.

PaulS: With all those char arrays and char pointer arrays, using only 182 bytes of SRAM is completely unrealistic.

All the strings are insided PROGMEM, so only the pointer are being used.

Is this related to dynamic allocation inside the functions? Or I'm not using PROGMEM in the right way?

Did you not notice most of them are in FLASH???

Like these?

  char ConnectionInfo[(int)log10(ConnectionID) + 2];
  itoa(ConnectionID, ConnectionInfo, 10);

  char LengthInfo[(int)log10(len) + 2];
  itoa(len, LengthInfo, 10);

  char InputBuffer[Length + 1];
  strcpy(InputBuffer, Values);
  char CompareBuffer[Length + 1];

  char* InputTokens[TokenQuantity];
  memset(InputTokens, 0, sizeof(InputTokens));
  char* CompareTokens[TokenQuantity];

Yeah, I did.

Thanks Paul!

I can't see why those arrays are the problem.

They aren't that big to cause a memory problem.

Max Elements in each array of my sketch:

char ConnectionInfo = 3 char LengthInfo = 5 char InputBuffer = 13 char CompareBuffer = 13 char* InputTokens = 2 char* CompareTokens = 2

Do they exceed the memory size?

Max Elements in each array of my sketch:

char ConnectionInfo = 3

int ConnectionId = esp8266.read() - 48;
...
char ConnectionInfo[(int)log10(ConnectionID) + 2];

ConnectionID is derived from a value that the program reads from elsewhere, so how can you have any confidence in its maximum size?

Perhaps this is not the problem, but the approach is rather dangerous.

ConnectionID is derived from a value that the program reads from elsewhere, so how can you have any confidence in its maximum size?

Assuming (yes, I know...) that there actually was a digit in the range '0' to '9', ConnectionID will be in the range 0 to 9.

Why the character needs to be converted to an int, and the int converted to a string is a mystery.

There is no useful purpose served from converting len to a string, when print() is perfectly capable of doing that, either.

PaulS: Like these?

  char ConnectionInfo[(int)log10(ConnectionID) + 2];
  itoa(ConnectionID, ConnectionInfo, 10);

 char LengthInfo[(int)log10(len) + 2];  itoa(len, LengthInfo, 10);

 char InputBuffer[Length + 1];  strcpy(InputBuffer, Values);  char CompareBuffer[Length + 1];

 char* InputTokens[TokenQuantity];  memset(InputTokens, 0, sizeof(InputTokens));  char* CompareTokens[TokenQuantity];



Yeah, I did.

All of which are automatic variables, none of which are particularly large, so none will have much impact. The only large non-FLASH, global char array is Index_html[], which is still not all that large.

Regards, Ray L.

I've written the sketch below for Arduino Due and now just uploaded into a ATmega328p on a breadboard (16Mhz external).

Sounds more like hardware than software. Can you run any sketch at all?

Mark

Thanks for the replies!

PaulS: Assuming (yes, I know...) that there actually was a digit in the range '0' to '9', ConnectionID will be in the range 0 to 9.

Why the character needs to be converted to an int, and the int converted to a string is a mystery.

There is no useful purpose served from converting len to a string, when print() is perfectly capable of doing that, either.

Oh that's true, I've figured it now that print() handles all type of info and send as ASCII, I will make the changes.

RayLivingston: All of which are automatic variables, none of which are particularly large, so none will have much impact. The only large non-FLASH, global char array is Index_html[], which is still not all that large.

Regards, Ray L.

Index_html[] is also in PROGMEM, so it also saves memory.

holmes4: Sounds more like hardware than software. Can you run any sketch at all?

Mark

Yes, this breadboard is also connected to a Nokia 5110 display and works pretty well. The display is disconnected of the board when I test this problematic sketch, as I'm trying to make one thing work at a time, so after the tests I can make them work together.

Using Serial.print() to debug the arrays sizes, there weren't any problem.

I will try programming other microncontroller after changing the prints.