Strange conflict involving web server, I2C and strings

This topic could be a continuation of this one...

https://forum.arduino.cc/t/arduino-nano-web-server-ajax-not-quite-working/1342359

... but that one was resolved. I have built on on that sketch with some added functionality and have new issues, so here's a new topic.

So we have an Arduino Nano with a web server. I want my Arduino to retrieve some measurements from another ATMega controller over I2C, present those data on a webpage and send them continually over Ethernet to a PC for visualisation (Grafana). Here is the code:

#include <SPI.h>
#include <EthernetENC.h>
//#include <Wire.h>

#define pAI03 A3
#define pAI06 A6

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x47 };
IPAddress ip(192, 168, 1, 71);
EthernetServer server(6501);
EthernetUDP udp;

const byte MY_ADDRESS = 11;

String HTTP_req;

int g = 0;
int i = 0;
int i22AI03, i22AI06 = 0;
String s22AI03, s22AI06;
String vIED_22;

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.begin(9600);
  //Wire.begin(MY_ADDRESS);

  pinMode(pAI03, INPUT);
  pinMode(pAI06, INPUT);
  analogReference(DEFAULT);

  TCCR1A = B00000000;
  TCCR1B = B00001101;
  OCR1A  = 15625;
  TIMSK1 = B00000010;
}


void loop()
{
  EthernetClient client = server.available();

  if (client)
  {
    boolean currentLineIsBlank = true;
    while (client.connected())
    {
      if (client.available())
      {
        char c = client.read();
        HTTP_req += c;
        if (c == '\n' && currentLineIsBlank)
        {
          client.print(F("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n"));
          if (HTTP_req.startsWith("GET /ajax_switch"))
          {
            GetSwitchState(client);
          }
          else
          {
            client.print(F(R"~~~(
              <!DOCTYPE html>
              <html>
              <head>
              <title>Arduino Web Page</title>
              <script>

              function GetSwitchState()
              {
                var nocache = "nocache=" + Math.random() * 1000000;
                var request = new XMLHttpRequest();
                request.onreadystatechange = function()
                {
                  if (this.readyState == 4)
                  {
                    if (this.status == 200)
                    {
                      if (this.responseText != null)
                      {
                        document.getElementById("switch_txt").innerHTML = this.responseText;
                      }
                    }
                  }
                }
                request.open("GET", "ajax_switch?" + nocache, true);
                request.send(null);
                setTimeout(GetSwitchState, 1000);
              }
              </script>
              </head>
              <body onload="GetSwitchState()">
              <h1>Weather Station</h1>
              <div id="switch_txt">Starting...</div>
              </body>
              </html>
              )~~~"));
          }
          HTTP_req = "";
          break;
        }
          
        if (c == '\n')
        {
          currentLineIsBlank = true;
        } 
        else if (c != '\r')
        {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }

  if (g == 1)
  {
    g--;

    s22AI03 = String(i22AI03);
    s22AI06 = String(i22AI06);
    vIED_22 = String("IED_22 22AI03=" + s22AI03 + ",22AI06=" + s22AI06);

    Serial.println(vIED_22);
  }
}

void GetSwitchState(EthernetClient cl)
{
  i++;
  cl.print("Counter = ");
  cl.print(i);
  cl.print("<br>22AI03 = ");
  cl.print(i22AI03);
  cl.print("<br>22AI06 = ");
  cl.print(i22AI06);
}

ISR(TIMER1_COMPA_vect)
{
  g++;
  i22AI03 = analogRead(pAI03);
  i22AI06 = analogRead(pAI06);
}

For now I am not using I2C but reading two potentiometers connected to Arduino. If I don't use Wire.h and don't initiate I2C (wire.begin()) everything works fine. However, if I uncomment those two lines here is what happens: the programs works fine until I refresh the web page. After that still everything works except for this line:

vIED_22 = String("IED_22 22AI03=" + s22AI03 + ",22AI06=" + s22AI06);

What happens is that the string that is created omits everything before the comma. So if I don't include the "22AI06" part then an empty string is created. Otherwise the string looks like this:

,22AI06=517

Other than that, everything else works fine, including the I2C communication and sending data to the PC which I omitted here in order to focus on the part that doesn't work.

To summarize: everything works fine until I refresh the webpage, after which the creation of the string "vIED_22" doesn't work as it should. And all this only if Wire.h is included. Is it a conflict between libraries? Or something simpler?

OK, a quick update. I figured out that there is no need to concatenate strings. Changed to:

    a = String("IED_22 22AI03=");
    b = s22AI03;
    c = String(",22AI06=");
    d = s22AI06;

    udp.beginPacket(IPAddress(192, 168, 1 , 40),5555);
    udp.print(a);
    udp.print(b);
    udp.print(c);
    udp.print(d);
    udp.endPacket();

This works now. But now it seems that the web server shows the page correctly only if the Arduino is reset while the page is open. If I open the page while Arduino is running I get a similar situation like in my previous topic. Will come back after more testing.

You don't need to convert anything to String, you can print the text and variables directly, preferably using the F() macro for the text literals.

My suspicion is that you are using up all the available ram memory with the use of String. Do you have any idea what the maximum length of the text being stored in HTTP_req is? That may be consuming a large amount of ram, and if you know the maximum length you can use a char array instead of String.

On any processor with limited memory, avoid Strings. They will eventually bite you. And the more you use them, the quicker they will bite you.

The completely String free technique you used in GetSwitchedState can be reused:

    udp.beginPacket(IPAddress(192, 168, 1 , 40),5555);
    udp.print(F("IED_22 22AI03="));
    udp.print(i22AI03);
    udp.print(F(",22AI06="));
    udp.print(i22AI06);
    udp.endPacket();

Removing the strings seems to have helped.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.