Arduino + W5100 strange behaviour

Hello guys!

I have noticed a strange behaviour in my web server using the function below.

  char *Username  = "Username";
  char Auth1[50];
  float tempC;
  float tempH;
  float tempA;
  float PHA;
  float PHR;
  int ORP;
  int DEN;
  byte status_parametros;
  byte temporizador_status;
  byte Status;
  boolean nivel_status;
  byte tpa_status;
prog_char string0[] PROGMEM = "POST /api/temp HTTP/1.1";
prog_char string1[] PROGMEM = "Host: www.mysite.com";
prog_char string2[] PROGMEM = "Authorization: Basic ";
prog_char string3[] PROGMEM = "Cache-Control: no-cache";
prog_char string4[] PROGMEM = "Content-Type: application/x-www-form-urlencoded";
prog_char string5[] PROGMEM = "Connection: Keep-Alive";
prog_char string6[] PROGMEM = "Content-Length: ";

char* tabela_strings[] PROGMEM = 
{
  string0, string1, string2, string3,
  string4, string5, string6
};
void enviar_dados()
{
  char dados[6];
  EthernetClient client;

  Serial.println("Connecting...");

  String PostData =
    "{\"userName\":\""+
    String(Username)+
    "\",\"minute\":\""+
    rtc.getTimeStamp()+
    "\",\"A\":"+ // Temp. da água
  dtostrf(tempC,5,2,dados)+
    ",\"B\":"+ // Temp. dissipador
  dtostrf(tempH,5,2,dados)+
    ",\"C\":"+ // Temp. ambiente
  dtostrf(tempA,5,2,dados)+
    ",\"D\":"+ // PH do aquário
  dtostrf(PHA,4,2,dados)+
    ",\"E\":"+ // PH do reator de cálcio
  dtostrf(PHR,4,2,dados)+
    ",\"F\":"+ // Densidade
  String(DEN)+
    ",\"G\":"+ // ORP
  String(ORP)+
    ",\"H\":"+ // Status chiller, 0 = desligado e 1 = ligado
  String(bitRead(status_parametros,0))+
    ",\"I\":"+ // Status aquecedor, 0 = desligado e 1 = ligado
  String(bitRead(status_parametros,1))+
    ",\"J\":"+ // Status reator de cálcio, 0 = desligado e 1 = ligado
  String(bitRead(status_parametros,5))+
    ",\"K\":"+ // Status ozonizador, 0 = desligado e 1 = ligado
  String(bitRead(status_parametros,7))+
    ",\"L\":"+ // Status reposição de água doce, 0 = desligado e 1 = ligado
  String(bitRead(Status,1))+
    ",\"M\":"+ // Status niveis, 0 = baixo e 1 = normal
  String(nivel_status)+
    ",\"N\":"+ // Status TPA, 0 = desligado e 1 = ligado
  String(bitRead(tpa_status,0))+
    ",\"O\":"+ 
    String(bitRead(temporizador_status,1))+ // Status timer 1, 0 = desligado e 1 = ligado
  ",\"P\":"+ 
    String(bitRead(temporizador_status,2))+ // Status timer 2, 0 = desligado e 1 = ligado
  ",\"Q\":"+
    String(bitRead(temporizador_status,3))+ // Status timer 3, 0 = desligado e 1 = ligado
  ",\"R\":"+ 
    String(bitRead(temporizador_status,4))+ // Status timer 4, 0 = desligado e 1 = ligado
  ",\"S\":"+ 
    String(bitRead(temporizador_status,5))+ // Status timer 5, 0 = desligado e 1 = ligado
  ",\"T\":"+ // Sinaliza falha na TPA
  String(bitRead(tpa_status,2))+ 
    "}";

  if (client.connect("www.mysite.com", 80)) 
  {
    Serial.println(">> Connected <<");
    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[0]))); // "POST /api/temp HTTP/1.1"
    client.println(buffer);

    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[1]))); // "Host: www.mysite.com"
    client.println(buffer);

    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[2]))); // "Authorization: Basic "
    client.print(buffer);

    client.println(Auth1);

    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[3]))); // "Cache-Control: no-cache"
    client.println(buffer);

    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[4]))); // "Content-Type: application/x-www-form-urlencoded"
    client.println(buffer);

    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[5]))); // "Connection: close"
    client.println(buffer);

    strcpy_P(buffer, (char*)pgm_read_word_near(&(tabela_strings[6]))); // "Content-Length: "
    client.print(buffer);

    client.println(PostData.length());
    client.println();
    client.println(PostData); 

    Serial.println(PostData);

    delay(5);
    client.stop();

  }
  else
  {
    Serial.println("Can't connect!");
  }
}

For now I can’t show my full code because it have more than 10,000 lines.

The sketch size is 212.066 Kbytes.

A previous version can be found here.

I’ll add this new function to this code.

Let me try explain the problem.

The function above send a HTTP POST to a server.

This code works fine during 1 or 2 days.

After this time the server doesn’t receive more data but all others functions keep working.

The serial monitor print “Clnnecting…” instead “Connecting…” even after send the code to the board.

if remove “Serial.println(“Connecting…”);”, the function (enviar_dados()) doesn’t works anymore.

Looking the traffic on wireshark the function try connect to “wtw.mysite.com” instead “www.mysite.com”.

The board have 2456 bytes of free memory.

Also I would like to know a best way to build the string “PostData”.

I can’t use a “client.print()” to each value because I’ll have problem to know the content length.

Someone can give some suggestion to this problems?

Thanks in advance.

Your ram is being overwritten. Perhaps you use too many String objects, or use too many memory buffers, or you Postdata doesn’t fit in the buffer.

This string is in ram : Serial.println("Connecting...");
Also this string is in ram : if (client.connect("www.mysite.com", 80))
Keep the string for “client.connect” in ram, but use the “F()” macro for all the Serial.println().

Add a function to show the available memory. Use the one at the bottom of this page : http://playground.arduino.cc/Code/AvailableMemory
Show the memory to the Serial port or on a webpage, and write down the value to see if it changes.

Hi Peter!

Thank you for your reply.

I already had an functions to show free RAM on loop.

Now I added after “PostData” see the result:

Free memory: 2531
Free memory: 2531
Clnnecting...
Free memory after PostData: 1794
>> Connected <<
{"userName":"fernandogarcia","minute":"1417773098","A":21.50,"B":24.75,"C":22.75,"D":8.40,"E":6.94,"F":0,"G":211,"H":0,"I":1,"J":0,"K":1,"L":0,"M":0,"N":0,"O":0,"P":0,"Q":0,"R":0,"S":0,"T":1}
Free memory: 2531
Free memory: 2531

The free RAM decrease to 1794 bytes.

In fact I would like to remove all debug messages but, now the code doesn’t work without. Seems that exists a space corrupted in the memory.

Any suggestion is welcome.

Best regards.

FernandoGarcia:
Any suggestion is welcome.

Look very carefully at every place where you use an array or a pointer. Make sure you aren't indexing off the end of an array or using an uninitialized pointer.

Where is defined the variable buffer? Do you have enough space in it?

In the link to the previous version, the buffer is size 50.

Hi!

The bigger string is “Content-Type: application/x-www-form-urlencoded” and have 47 characters.

The buffer have a size of 50 as Peter told.

Best regards.

That very long String concatenation might crash the memory. Every time you add something with ‘+’ I think a new memory block is created (I’m not sure, didn’t look at the library code). And perhaps with a few hundred bytes on the stack here and there, and some more that was not reported by the function, and perhaps bad use of stack variables, and bingo, you hit the normal variables in ram.

You can test it, by sending smaller pieces of text with client.println.

Why do you use such a pointer-to-table-to-text-in-progmem ? Why not the simple client.println(F(“Host: www.mysite.com”)); ?

Do you use the newest Arduino IDE version 1.0.6 ?
You could try the Arduino IDE 1.5.8 BETA, you have to replace the prog_char with “const char” someday anyway.

Every time you add something with '+' I think a new memory block is created (I'm not sure, didn't look at the library code).

I have; it is.

Why I need to know the content length.

Now I'm using "PostData.length()". I don't know other function to this case.

I'm using string table just because I was using this method to print texts on TFT.

I'm using IDE 1.0.5, I tried to use 1.5.x but had some problems so, I gave up.

Edit:
I'll try use client.println(F()) to others strings.

The new version is available here.

Thanks for all replies.

I don't know an other solution for the many '+' of the large String Postdata, but you need a lot of memory for that.

PostData needs of 696 bytes.

I did the changes according to your suggestion and the consume of RAM is 500 bytes smaller.

Thanks.

That is 696 byte plus a lot of copies during building that String object and maybe memory fragmentation.
The String object allocated memory in the heap, see the picture with "kaboom" : Optimizing SRAM | Memories of an Arduino | Adafruit Learning System

The "String.reserve()" as mentioned in the Adafruit page might be a good idea.

That will work since you are only adding to the end of the String.

Using PostData.reserve(200) the amount of memory free on loop is smaller but seems more advantageous.

During the creation of the new string are used 171 bytes, adding 200 bytes reserved the total is 371 bytes.

Too less than 696 bytes used previously and with advantage of reduce the fragmentation.

But the "Clnnecting..." remains. :smiley:

You could make two passes structuring the data. On the first pass, count the characters. Then, write that count, and then make another pass to write the data, NOT using the String class.

Hi!

Yesterday I changed all "Serial.print()" in my code to "Serial.print(F())".

The free RAM increased in 94 bytes and now the "Connecting..." is printed correctly, however the HTTP POST doesn't work anymore.

PaulS, can you give some example?

Best regards.

Use the ‘F()’ only for the …print(), …println(), …write() functions. Not for the other Ethernet functions.
But the feeling that you are using a pointer to no data or data beyond an array gets only stronger.

Hi Peter!

I haven't any problem using F() in others functions.

It works fine:

      client.print(F("{\"hStart\":"));
      client.print(on_hora[temporizador]);
      client.print(F(",\"mStart\":"));  
      client.print(on_minuto[temporizador]);
      client.print(F(",\"hEnd\":"));  
      client.print(off_hora[temporizador]);
      client.print(F(",\"mEnd\":"));  
      client.print(off_minuto[temporizador]);
      client.print(F(",\"activated\":"));  
      client.print(temporizador_ativado[temporizador]);
      client.println(F("}"));

The problem is always the "void enviar_dados" and I'm not using F() for it.

I don't understand what you mean about pointers.

Best regards.

      client.print(F("{\"hStart\":"));

How many bytes does that send to the client? Why can't you count them BEFORE you print to the client?

Because is impossible to know the quantity of characters to this variables.

  float tempC;
  float tempH;
  float tempA;
  float PHA;
  float PHR;
  int ORP;
  int DEN;

By example, if the user have a pH sensor the PHA or PHR can be 8.50 otherwise will be 0 (zero).

On this case have a difference is of 3 chars.

The variable DEN can be 1025 or 0 the difference can be of 3 chars too.