0

I'm using a Nucleo F429ZI board and I wrote a sketch that enables a simple web-server:

#include <LwIP.h>
#include <STM32Ethernet.h>

const int WEB_PORT = 80;
EthernetServer server(WEB_PORT);
char buffer[1024];

void setup() 
{
    Serial.begin(115200);
    // define variables
    Ethernet.begin(localIP, netmask, dns, gateway);
    server.begin();
}

void loop() 
{
    processServer();
}

void processServer()
{
  String readString; 
  EthernetClient client = server.available();
  if (client) 
  {
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        readString += c; 

        if (c == '\n')
        {
          if (readString.startsWith("GET"))
          {
            readString.remove(0, 4);
            int pos = readString.indexOf(' ');
            String path = readString.substring(0, pos);

            if (path == "/status") pageStatus(client);
            break;
          }
        }
      }
    }
    delay(1);
    client.stop();
  }
}

void pageStatus(EthernetClient client)
{
    sectionHeader(client, 2);
    client.println("<html>");
    client.println("<style>table{font-family: verdana, sans-serif;border-collapse: collapse;width: 30%;}");
    client.println("td, th{border: 1px solid #dddddd;text-align: left;padding: 8px;}tr:nth-child(even)");
    client.println("{background-color: #dddddd;}</style>");
    client.println("<table>");
    client.println("<tr><th>Servo</th><th>Position</th><th>Running</th><th>Initialized</th></tr>");

    for (int i = 0; i < getParamUInt8(P_SERVO_SIZE); i++) 
    {
        sprintf(buffer, "<tr><td>%u</td><td>%d</td><td>%s</td><td>%s</td></tr>", i + 1, (int16_t) _servo[i].current, _servo[i].ended ? "NO" : "YES", _servo[i].initialized ? "YES" : "NO" );
        client.println(buffer);
    }
    client.println("</table>");

    client.println("<br><hr><br>");

    client.println("<table>");
    client.println("<tr><th>Led</th><th>PWM</th><th>Running</th></tr>");

    for (int i = 0; i < getParamUInt8(P_LED_SIZE); i++) 
    {
        sprintf(buffer, "<tr><td>%u</td><td>%d</td><td>%s</td></tr>", i + 1, (int16_t) _led[i].pwm, _led[i].ended ? "NO" : "YES");
        client.println(buffer);
    }
    client.println("</table>");

    client.println("<br><hr><br>");

    client.println("<table>");
    client.println("<tr><th>Stepper</th><th>Position</th><th>Running</th></tr>");

    for (int i = 0; i < getParamUInt8(P_STEPPER_SIZE); i++) 
    {
        sprintf(buffer, "<tr><td>%u</td><td>%d</td><td>%s</td></tr>", i + 1, (int16_t) _stepper[i].stepper.getCurrentPositionInMillimeters(), _stepper[i].stepper.motionComplete() ? "NO" : "YES");
        client.println(buffer);
    }
    client.println("</table>");
    client.println("</html>");
}

void sectionHeader(EthernetClient client, int refresh)
{
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Connection: close");
    if (refresh) client.println("Refresh: 2"); 
    client.println();
    client.println("<!DOCTYPE HTML>");
}

As you can see in the sectionHeader() I want to refresh the page every 2 seconds. It works, but after 3 or 4 refreshes it hangs and I have to reset the whole board.

Of course with an embedded system I would use Ajax... here I thought reloading the page should be enough.

What might cause such a hang?

  • I recommend stm32duino.com – Juraj Jan 14 at 10:14
  • 1
    Welcome to the shockingly bad world of the String object. Ditch it as a first priority. – Majenko Jan 14 at 10:16
  • @Majenko, I used the String object only to parse the incoming GET request. Do you think it's worth to remove it, about my problem? – Mark Jan 14 at 15:01
  • 1. You may want to look at the HTTP conversation with Wireshark. 2. What does your server do when the client requests "GET /favicon.ico"? 3. What if it instead requests "HEAD /favicon.ico"? – Edgar Bonet Jan 23 at 8:39
  • @EdgarBonet, it just doesn't answer. Is this a bad behavior? Should I provide an answer anyway? – Mark Jan 24 at 12:43
1

The code you have that says readString += c has to allocate a whole new string whenever it runs out of space for more characters. All those allocations are filling up memory.

Instead of the String class, use a single C character array, e.g.

char s[128];

that is big enough for whatever you put in it.

If it helps, I wrote a simple arduino web server for my own project, and if you look at the code here that may give you ideas for how to implement this.

|improve this answer|||||
  • Or just set readString = "" after processing the request, I guess. – Mark Jan 23 at 8:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.