Help on my code

I’m just looking for a Guru which can solve my problem…
I’m working on a project to controll my heating house, its an arduino uno 2011version with WiFi Shield
The idea is to be able to configure via Wifi all parameters from over the world, to do that i created a home page. (I attached an image of the control, sorry but is in spanish…)

Now I can control: Temperature of the room(house), know the state of the heater(if it is on or off), Switch on/off, current time(which is get from the wifi shield), Put on automatic mode or manual, state of the mode(if it is on manual or automatic), set start time when the automatic mode is on will be switch on the heater, set end time when the automatic mode is on will be switch off the heater, get start time configured, and get the end time configured

My problem start when i program my arduino to do all that things… i mean, if i compile all code doesnt work well… if i comments pieces of code it works… WTF? :fearful:
To do this things it just “if’s” conditions so, if i comment 2 of this “ifs” works, if i uncoment this 2 “ifs” and comment another “ifs” still works, can someone help me?
this is how my arduino is reciving the information from the net throw wifly shield
G
GE
GET
GET
GET /
GET /?
GET /?o
GET /?ou
GET /?out
GET /?out=
GET /?out=2
GET /?out=2&
GET /?out=2&s
GET /?out=2&st
GET /?out=2&sta
GET /?out=2&stat
GET /?out=2&statu
GET /?out=2&status
GET /?out=2&status=
GET /?out=2&status=0
GET /?out=2&status=0
GET /?out=2&status=0 H
GET /?out=2&status=0 HT
GET /?out=2&status=0 HTT
GET /?out=2&status=0 HTTP
GET /?out=2&status=0 HTTP/
GET /?out=2&status=0 HTTP/1
GET /?out=2&status=0 HTTP/1.
GET /?out=2&status=0 HTTP/1.0
GET /?out=2&status=0 HTTP/1.0

GET /?out=2&status=0 HTTP/1.0

And this is what i get when it doesnt work:
G
GE
GET
GET
GET /
GET /?
GET /?o
GET /?ou
GET /?out
GET /?out=
GET /?out=2
GET /?out=2&
GET /?out=2&s
GET /?out=2&st
GET /?out=2&sta
GET /?out=2&stat
GET /?out=2&statu
GET /?out=2&status
GET /?out=2&status=
GET /?out=2&status=1
GET /?out=2&status=1
GET /?out=2&status=1 H
GET /?out=2&status=1 HT
GET /?out=2&status=1 HTT
GET /?out=2&status=1 HTTP

1
1.
1.0
1.0

1.0

1.0

I attach my code on a txt file because message exceeds the maximum allowed length (9500 characters).

Any ideas?

Thanks in advance!

code.txt (15.7 KB)

you have many 'if's, which ones do you comment out?.

        c = client.read();

if(readString.length() < 100)
        {
              readString=readString+c;
        }
        Serial.println(readString);

I would pretty-much expect what you are seeing because you are printing each character as you receive it, on a new line, concatenated with what you have before.

I would also expect you to run out of memory pretty soon, because the String class has to allocate memory for each new string (1 byte, 2 bytes, 3 bytes and so on). You only have 2K bytes, which might sound like a lot, but at this rate you’ll use them up quickly.

pYro_65:
you have many 'if’s, which ones do you comment out?.

I play with all, just comment one of them, and then other, i thought about it could be possible a limit of a memory code but it sounds that i wasn´t wrong at all and the problem could be on sram limit memory as Nick Gammon suggest

I think you are right
When i was programming my code I feel like I was declaring lot of variables… can be that my problem!
So… Any idea to solve? How can I change my code to avoid this problem?

PD: Thanks both for your support! :slight_smile:

Any idea to solve? How can I change my code to avoid this problem?

People wrote pretty complex string handling code for decades before the String class was (poorly) developed.

Since you are actually already limiting the size of the String object, just dump the whole String class. Use a char array, instead. You'll need an index into the array, and a way to know when the array contains a whole packet, so that the packet can be processed and the array and index reset. Fortunately, every packet received ends in a carriage return/line feed.

Each time you read a character, see if it is a carriage return or line feed, If it is, it's time to use the data received so far, and reset the array and index.

If not, add the character to the array, increment the index, and add a NULL to the array.

Global stuff:

char buffer[120];
byte index;

Change your code to:

        c = client.read();
        if(c == 10 || c == 13) // carriage return or line feed
        {
           // Do something with the data, if strlen(buffer) is greater than 0

           index = 0;
           buffer[index] = '\0';
        }
        else
        {
           buffer[index] = c;
           index++;
           buffer[index] = '\0';
        }

Hello Guys,
I applied your recomendation,
I changed the read loop to PaulS’s way
Now my code is faster! and works OK! :slight_smile:
But still having and strange bug

When i uncomment this last “if”

/*
          if(strncmp(cReadBuffer, "GET /?out=all", strlen("GET /?out=all")) == 0)
          {
              //Serial.print("\n OUT ALL\n");
              
              client.print("{\"nombre\" : \"Calefaccion\", ");
              client.print("\"tipo\" : \"WiFi\", ");
              client.print("\"ubicacion\" : \"Bodega\", ");
              client.print("\"ip\" : \"192.168.0.110\", ");
              client.print("\"devices\" : ");
              client.print("[{ \"type\" : \"time\", \"name\" : \"Hora\", \"out\" : \"");
              client.print("15");
              client.print("\"}");
              client.print(",{ \"type\" : \"text\", \"name\" : \"Auto/Manual\", \"out\" : \"");
              client.print("16");
              client.print("\"}");
              client.print(",{ \"type\" : \"text\", \"name\" : \"Auto/Manual\", \"out\" : \"");
              client.print("17");
              client.print("\"}");
              client.print(",{ \"type\" : \"set\", \"name\" : \"Hora Inicio\", \"out\" : \"");
              client.print("18");
              client.print("\"}");
              client.print(",{ \"type\" : \"set\", \"name\" : \"Hora Fin\", \"out\" : \"");
              client.print("19");
              client.print("\"}");
              client.print(",{ \"type\" : \"time\", \"name\" : \"Hora Inicio\", \"out\" : \"");
              client.print("20");
              client.print("\"}");
              client.print(",{ \"type\" : \"time\", \"name\" : \"Hora Fin\", \"out\" : \"");
              client.print("21");
              client.print("\"}");
              //client.print(",{ \"type\" : \"text\", \"name\" : \"Estado\", \"out\" : \"");
              client.print("1");
              client.print("\"}");         
              //client.print(",{ \"type\" : \"plug\", \"name\" : \"ON/OFF\", \"out\" : \"");
              client.print("2");
              client.print("\"}");
              client.print("]}");
          }
          */

And also if I uncomment the 2 lines with // my arduino get reboot always I send a command! WTF?
Also works bad if i add a new library,
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

FYI hole code get my a Binary sketch size: 12882 bytes (of a 32256 byte maximum)

What can be happening? It’s just a simply code… :fearful:

PD: I uploaded my new code as it’s working perfectly; Also now it’s “cleaner”

WiflyCalefaccion.pde (15.3 KB)

Looking at that code fragment, I suspect your issue is that you are out of RAM - don't be fooled by the reported size of your sketch - your Uno only has 2K and all those strings have to be stored there. Take a look at progmem in the reference section of the main site.

wildbill: Looking at that code fragment, I suspect your issue is that you are out of RAM - don't be fooled by the reported size of your sketch - your Uno only has 2K and all those strings have to be stored there. Take a look at progmem in the reference section of the main site.

I Thought this type of code it just a code, I thought it should be in the fash memory... Why this type of code has to be store in the sram? What can i do to reduce my sram memory usage? I'm always running out of memory... :S

All strings are stored in SRAM, copied there from the boot image before "main" runs.

I Thought this type of code it just a code, I thought it should be in the fash memory...

I think anything that is in the sketch code that gets loaded goes into the flash memory, which is read only when the the code is running. Any data (string varaibles and such) that is generated when the code is running is placed in th SRAM memory. Not sure how the SRAM can be cleared, but possibly setting the variables to "" when done with them might help keep SRAM memory available. Just speculation.

setting the variables to "" when done with them might help keep SRAM memory available.

Once the variable has had space allocated, what you put in it won't affect it's size. As there is a lot of string data, the best option is to move it into PROGMEM (http://www.arduino.cc/en/Reference/PROGMEM), and only read parts of it into SRAM when you need it.

As there is a lot of string data, the best option is to move it into PROGMEM (http://www.arduino.cc/en/Reference/PROGMEM), and only read parts of it into SRAM when you need it.

So show how you take data generated while the code is running on the arduino and place it in PROGMEM. It appears that the general thought is that PROGMEM is read only while code is running on the arduino.

              client.print("{\"nombre\" : \"Calefaccion\", ");
              client.print("\"tipo\" : \"WiFi\", ");
              client.print("\"ubicacion\" : \"Bodega\", ");
              client.print("\"ip\" : \"192.168.0.110\", ");
              client.print("\"devices\" : ");
              client.print("[{ \"type\" : \"time\", \"name\" : \"Hora\", \"out\" : \"");
              client.print("15");
              client.print("\"}");
              client.print(",{ \"type\" : \"text\", \"name\" : \"Auto/Manual\", \"out\" : \"");
              client.print("16");
              client.print("\"}");
              client.print(",{ \"type\" : \"text\", \"name\" : \"Auto/Manual\", \"out\" : \"");
              client.print("17");
              client.print("\"}");
              client.print(",{ \"type\" : \"set\", \"name\" : \"Hora Inicio\", \"out\" : \"");
              client.print("18");
              client.print("\"}");
              client.print(",{ \"type\" : \"set\", \"name\" : \"Hora Fin\", \"out\" : \"");
              client.print("19");/*
              client.print("\"}");
              client.print(",{ \"type\" : \"time\", \"name\" : \"Hora Inicio\", \"out\" : \"");
              client.print("20");
              client.print("\"}");
              client.print(",{ \"type\" : \"time\", \"name\" : \"Hora Fin\", \"out\" : \"");
              client.print("21");
              client.print("\"}");
              client.print(",{ \"type\" : \"text\", \"name\" : \"Estado\", \"out\" : \"");
              client.print("1");
              client.print("\"}");*/
              client.print(",{ \"type\" : \"plug\", \"name\" : \"ON/OFF\", \"out\" : \"");
              client.print("2");
              client.print("\"}");
              client.print("]}");

All of this is constant data, as are the strings in most of your client.print()'s. It could all be moved to PROGMEM.

All of this is constant data, as are the strings in most of your client.print()'s. It could all be moved to PROGMEM.

I think you are mixing apples and oranges here. All the data you show in your posted code already goes in PROGMEM when the code is compiled and loaded into the arduino flash memory. The strings and data that are generated when the program is running is put in SRAM, and PROGMEM is not available for storage of the generated strings and data.

I'm pretty sure that all static strings are moved into sram.

http://scott.dd.com.au/wiki/Arduino_Static_Strings

They are.

zoomkat:

All of this is constant data, as are the strings in most of your client.print()'s. It could all be moved to PROGMEM.

I think you are mixing apples and oranges here. All the data you show in your posted code already goes in PROGMEM when the code is compiled and loaded into the arduino flash memory. The strings and data that are generated when the program is running is put in SRAM, and PROGMEM is not available for storage of the generated strings and data.

I think what he said is ok, I read the article http://www.arduino.cc/en/Reference/PROGMEM and if i understand, what happen is that the compiler force arduino to not be load this variables on sram, and then when you need it take it from the flash memory loading into sram to be used.... so you can have a buffer on sram and loading from flash in this buffer all strings you want only spend in sram the buffer size :)

Thank you for this link: http://scott.dd.com.au/wiki/Arduino_Static_Strings it explain my problem and how to solve so good! I think it will be usefull to people who are having the same problem as me to understand the problem! :)

@AWOL - Thanks for the confirmation.

@SICOPOLY - Always happy to help where I can.

If you are using the 1.0 ide, you could try this (from the release notes)

  • Support has been added for printing strings stored in flash (program memory) rather than RAM. Wrap double-quoted strings in F() to indicate that they should be stored in flash, e.g. Serial.print(F("hello world")).

dxw00d: If you are using the 1.0 ide, you could try this (from the release notes)

  • Support has been added for printing strings stored in flash (program memory) rather than RAM. Wrap double-quoted strings in F() to indicate that they should be stored in flash, e.g. Serial.print(F("hello world")).

WoW, i will try this, sounds so good, if i have to be honest the PROGMEM is so dirty programming... :S dont you think so? I hope this new way will work! :)