Weather station on UNO - memory overload

Hi

I am making weather station based on Arduino UNO on atmega328. As I have decided at the beggining the station would measure: humidity, temperature, pressure, wind speed, rain intensivity. Additionally, it would be equipped with SD card to track data, bluetooth module to communicate with smartphone and and LCD with some buttons to look up weather without using phone. So far it was not so hard but now I have stumbled upon memory problems (dynamic memory) - Low memory available, stability problems may occur. This results in SD card not registering data which is unacceptable.

The fact that I have not finished the code yet and UNO is already using 82% storage space and 84% of dynamic memory is quite depressing...

I can not use EEPROM as I am updating data quite often, way too often to use EEPROM. I am not using Serial at all. I do not see any way I could optimize my code by macros etc.

What can I do in such situation? I do not feel like buying Arduino Mega nor using atmega1284p as I can not stick in into Arduino. Am I really left with buying Mega?

There is this:-
https://www.pjrc.com/teensy/

Hello, this happens when you use lots of strings. Check out this link, it helped me a ton with reducing my memory usage.

whoru:
What can I do in such situation? I do not feel like buying Arduino Mega nor using atmega1284p as I can not stick in into Arduino. Am I really left with buying Mega?

Very likely. You can come to that conclusion now, or you can come to it later, after you have spent some time bashing your head against the wall. What nutcrapper said is true and it would be a good idea to post the code, but I wouldn't be surprised if Strings are not the problem, as you are being warned as you compile rather than getting grief as you run.

I believe the real problem is that you are simply doing too many things for a Uno. They are not really up to the job of datalogging and, be assured, the situation is only going to get worse as you want to do something you haven't thought of yet.

Nick_Pyner:
Very likely. You can come to that conclusion now, or you can come to it later, after you have spent some time bashing your head against the wall. What nutcrapper said is true and it would be a good idea to post the code, but I wouldn’t be surprised if Strings are not the problem, as you are being warned as you compile rather than getting grief as you run.

I believe the real problem is that you are simply doing too many things for a Uno. They are not really up to the job of datalogging and, be assured, the situation is only going to get worse as you want to do something you haven’t thought of yet.

I hope the OP took a look at the link, my sketch went from 94% memory to ~60%. There are many tips on there that help a ton, not just about strings.

Grumpy_Mike:
There is this:-
Teensy USB Development Board

It is better for me to buy Arduino Mega clone in my country than buy Teensy. Dollars too expensive.

nutcrapper:
I hope the OP took a look at the link, my sketch went from 94% memory to ~60%. There are many tips on there that help a ton, not just about strings.

I have seen this link but I can not apply this to my code. There is simply nothing I can use it on tho I will take a deep look into it once again.

Nick_Pyner:
I believe the real problem is that you are simply doing too many things for a Uno. They are not really up to the job of datalogging and, be assured, the situation is only going to get worse as you want to do something you haven't thought of yet.

Well, I must say that there is a lot going on for Uno. Even if I tweaked my code a bit down to lets say 65% SRAM usage, I would still go over 80% at the end as I have not programmed wind speed meter, bluetooth and batttery levels yet. In the future I would like to introduce RTC into it aswell.

I guess it's a fine time to finally switch to Mega...

whoru:
I guess it's a fine time to finally switch to Mega...

Right on.......

And I don't recall seeing the word "internet" anywhere.....

Note though, that bluetooth may not require any more code than you already have, at most a couple of lines or so for two-way traffic.

whoru:
The fact that I have not finished the code yet and UNO is already using 82% storage space and 84% of dynamic memory is quite depressing...

When using an Arduino UNO with SD card, more than half of the 2 KB RAM is already used for SD.

But if your sketch just uses 84% of dynamic memory, this would mean that 16% of 2048 bytes = 327 bytes are still free. Under normal circumstances, 327 bytes of free memory, even 250 bytes, should always be enough to keep a sketch running without any RAM memory problems.

So I'd first inspect what causes the fact your program is not running errorfree any longer.

The first suspect when looking at beginners code in this forum would be:

  1. Not using the F-macro when printing constant strings.

Bad example for println wasting RAM:

  Serial.println("This is wasting RAM");

Good example for saving RAM by using F-macro:

  Serial.println(F("This is saving RAM"));

The second suspect when looking at beginners code in this forum would be:
2. Use of "String" objects.

As soon as you start declaring "String" in your sketch, you start wasting RAM.
Instead: Better use char arrays (C-Strings, nullterminated strings) only to save RAM, and use flash-strings in PROGMEM memory section wherever possible! Strictly avoid declaring "String" anywhere in your sketch if you don't want to waste RAM!

Hi,
Can you post your code or if its too big, attach it to a posting.
We may be able to suggest some solutions.

Please use code tags.. See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom..... :slight_smile:
Use REPLY rather than QUICK REPLY to see the attachment function.

There are two ways. You can buy a processor with more memory or you can work to reduce the memory usage of your code. The first costs money and the second costs time.

For my first Arduino Uno project I discovered after buying the hardware that the existing libraries added up to over 3K RAM. It seemed impossible. I looked everywhere for ways to save RAM and when I was done the sketch used about 1000 bytes. Half the RAM is empty (the sketch uses an SD card).

But it took a lot of work. I rewrote libraries, tailoring them to my specific needs. If it were for a job I would have just bought hardware. The Uno is kind of a toy, after all. But since this is a hobby for me spending all of that time was actually more rewarding than achieving the finished project was. I learned much more that way. The means was the end, for me at least.

I found it easier to use a Raspberry Pi to put my weather station online here

Russell.

I do not feel like posting the code in here but I can give the link to it. Reason: I am obligated to by 3rd parties. Don't ask...

Evernote link

Please note that, once I am done with the whole project I will gladly post DIY step by step tutorial somewhere on web which will happen in July.

Any help greatly appreciated

I'm really a mind reader.

Remember reply #7?

  1. Wasting RAM by not using the F-macro when printing string constants.
    You use (example for wasting RAM):
Serial.println("error opening log.csv");

instead of (example for saving RAM):

Serial.println(F("error opening log.csv"));

And of course wasting RAM with "String" objects:
2. Using "String" as a RAM wasting helper in your sketch

The two most powerful kinds of wasting RAM for beginners:

  • not using F-macro with print/println and constant strings.
  • using "String" objects

jurs:
2. Using "String" as a RAM wasting helper in your sketch

The two most powerful kinds of wasting RAM for beginners:

  • not using F-macro with print/println and constant strings.
  • using "String" objects

F macro saved me 1%. I used it twice so not much of a progress.

How else can I pass data to SD if not with String? I am confused.

EDIT: If I comment Strings out, I save another 1%. I am then at 81%. That does not help much.

whoru:
F macro saved me 1%. I used it twice so not much of a progress.

Twice?

These alone are four possibilities to use the F-macro with:

 lcd.print("Humidity: ");
...
 lcd.print("Temp: ");
...
 lcd.print("Pressure: ");
...
 lcd.print("Lux: ");

Looks like you left out many occurances of print/println if you only found two of them.

whoru:
How else can I pass data to SD if not with String? I am confused.

The SD-library works with C-strings (nullterminated strings) or arrays, and NOT with "String" objects in the first place. Though "print" is supported and "print" also can deal with String objects.

The main type and native type for strings in C is "array of char" or "char pointer", which is the type supported by all libraries, and NOT "String object"!

Learn the basics of C programming!

Instead of:

String dataString = String(id) + ", " + String(lux) + ", " + String(tDHT) + ", " + String(h) + ", " + String(P);

  • myFile.println(dataString);*

you could write:

myFile.print(id);

  • myFile.print(F(","));*
  • myFile.print(lux);*
  • myFile.print(F(","));*
  • myFile.print(tDHT);*
  • myFile.print(F(","));*
  • etc.*
  • myFile.println();*

Another relatively easy way to save a little RAM is to use SdFat instead of SD. When I tested this I found that SdFat used about 65 bytes less RAM up front and also required about 65 bytes less of stack usage.

jboyton:
Instead of:

String dataString = String(id) + ", " + String(lux) + ", " + String(tDHT) + ", " + String(h) + ", " + String(P);

  • myFile.println(dataString);*

you could write:

myFile.print(id);

  • myFile.print(F(","));*
  • myFile.print(lux);*
  • myFile.print(F(","));*
  • myFile.print(tDHT);*
  • myFile.print(F(","));*
  • etc.*
  • myFile.println();*

Another relatively easy way to save a little RAM is to use SdFat instead of SD. When I tested this I found that SdFat used about 65 bytes less RAM up front and also required about 65 bytes less of stack usage.

Interestingly, that does not matter. Either way, program takes 1,632 bytes (79%) of dynamic memory.

Furthermore, commenting out whole save() function does not have an impact either.

Anyways, thanks for your input everyone. Concluding: using macros helps but not as much as I would like to. Resigning from Strings does not help either. Obviously, use percentage drops but once again not as much as it is needed to.

How are you determining the amount of memory used?

whoru:
Interestingly, that does not matter. Either way, program takes 1,632 bytes (79%) of dynamic memory.

I’m not surprised. As I said, using String is not much of a problem when compiling, but you get the grief when running. I understand it screws up the stack and eventually it goes kaboom.

. Resigning from Strings does not help either.

You can be sure it will, and probably sooner rather than later. You don’t have to trawl very far through this forum to see that using String is about the most stupid thing you can do with Arduino. As I understand, being admonished to “learn the basics of C programming” is no help either, as this is an Arduino “problem”.

More to the point, there is never any need to use strings, except when a receiver demands it. The only instances of that that I am aware of are a couple of Android apps, and you do that using dtostrf conversion, not String. Otherwise, all you ever need to do is simply get the data from the sensor, and pass it along to the various places it needs to go.

You are right to go for the Mega, rewriting libraries etc., is just academic nitpicking trying to put off the inevitable. My final programme is certainly over 60k and, while comprehensive, is probably rather ordinary.

Nick_Pyner:
You are right to go for the Mega, rewriting libraries etc., is just academic nitpicking trying to put off the inevitable.

This is certainly true if the goal is to complete your project as efficiently as possible. The cost of a Mega is small and it will solve your memory problem instantly.

For that matter, you could avoid this Arduino silliness entirely by purchasing a complete weather station. But you may be doing it this way for reasons other than economy. I think a large fraction of Arduino projects are bordering on ridiculous. But they're fun. So if that's the goal -- fun -- then it affects the decision you make. The funnest path between two points isn't a straight line.