What are some of the best programming practices that can be adopted while coding sketches for Arduino, so that it uses the least memory and performance should not suffer from memory outage, and still the code be robust?
From the link: https://www.arduino.cc/en/Products/Compare
I have learned that the Uno has 32 KB of Flash memory. The maximum available is in the MEGA with 256 KB. I think Uno and Mega are the most widely used by people.
-
First off, I'd consider NOT using Arduino library and directly use AVR C library, as Arduino adds a lot of code to simplify programming, but not necessary once you know AVR MCU. This is what I'm trying to achieve in github.com/jfpoilpret/fast-arduino-lib optimized libraryjfpoilpret– jfpoilpret2016年11月30日 09:42:32 +00:00Commented Nov 30, 2016 at 9:42
2 Answers 2
Paul covered the most important points. This answer is intended to be a complement to his.
First, you should keep in mind the general rules, which are more important than the more specific ones. The general rule for saving RAM is: be aware of what you are storing, and do not store anything you do not really need. The general rule for saving flash is: be aware of what you are doing, and do not do anything you do not really need.
Now, a few specific tips:
Use the const
qualifier for declaring constants (e.g.
const int ledPin = 13;
). The compiler will optimize-out the storage of
the constant and use immediate addressing instead.
Use PROGMEM
for arrays of constants.
Whenever possible, use static memory (globals and static
locals)
rather than heap allocation (malloc()
and new
). This will prevent
memory fragmentation and make the memory usage more predictable (only
the stack holds dynamic memory): you know at compile time, rather than
run time, whether you are low in RAM.
For the same reason, prefer C strings (char *
) over String
objects.
Use the C99 types int8_t
and uint8_t
whenever 8 bits are enough for
your integer variables.
Use the static
qualifier for functions that will be used only in the
same source file, especially for functions that are called only from one
place. This gives the compiler more optimization opportunities.
If you need to optimize,
use avr-nm
to know what is
consuming your precious RAM.
-
just out of curiosity @Edgar , is 'const int ledPin = 13' use the same memory size as const char ledPin = 13' ?duck– duck2016年12月01日 06:19:40 +00:00Commented Dec 1, 2016 at 6:19
-
@dhimaspw: In my tests, yes, the size and the generated assembly are the same. In both cases,
digitalWrite(ledPin, HIGH);
compiles toldi r22, 1 $ ldi r24, 13 $ call digitalWrite
. Here,ldi
means "load an immediate value into a register", i.e. the value given as the second argument (1 forHIGH
or 13 forledPin
) is part of the instruction itself.Edgar Bonet– Edgar Bonet2016年12月01日 08:46:36 +00:00Commented Dec 1, 2016 at 8:46
Keep in mind that RAM is even less. 32KB is a fair lot of code, since C/C++ is highly efficient. "Don't save **** in RAM."
If you need to load images into a display, save the images on an SD card. And "stream" it to the display. You can read and transmit the bytes one by one, or 10 by 10 or something.
Also, if you need long strings, you can use the "flashStringHelper" to store the string in flash memory. For example: println(F("Error message: Couldn't connect to server));
. By using F()
around the string, you save valuable bytes.
Not using Arduino code, but pure AVR-C/C++, can save you a little also. (Will also save the bootloader piece of memory, if you program directly with a programmer.)
If you use Arduino, know how it works. The Arduino serial library uses ~256 or 500 bytes (I believe) as a buffer. You can change this if you need it for other applications.
Keep in mind that your saving technique depends on what resources are low. If you need to do a lot simultaneously, it's better to write non-blocking code.
But also remember: Don't optimize unless it's actually needed! Or, actually set measurable and realistic requirements, optimizing something to be "as fast as possible" can take infinite amounts of time... Run a google search on "premature optimization" as the old folks in the field like to call it.
-
1I agree with part premature optimisation is mother of all evils , I have read it before however the point of start looking into optimisation comes when you start seeing low memory warning while uploading to ArduinoCiasto piekarz– Ciasto piekarz2016年11月30日 07:30:43 +00:00Commented Nov 30, 2016 at 7:30
-
1@Ciastopiekarz That's complete nonsense, I am afraid. A mis-quote of a partial excerpt from a perfectly good quote. Good software design includes a certain level of optimization right from the start. What is "evil" is spending many man hours doing pointless micro-optimization of small bits of code. When that statement was first quoted "optimization" meant something completely different to what it does today, yet it is still erroneously spouted as a reason to not bother doing any optimization at all, and you end up with Windows applications.Majenko– Majenko2016年11月30日 10:07:10 +00:00Commented Nov 30, 2016 at 10:07
-
Windows application 😳Ciasto piekarz– Ciasto piekarz2016年11月30日 10:12:25 +00:00Commented Nov 30, 2016 at 10:12
-
@Ciastopiekarz Have you ever noticed how things like Office run at about the same speed with a modern version on a 3GHz i7 as old versions ran on a 33MHz 486? They spread to fill the available space, but there hasn't been much change in functionality... Bloat is a blight. Interesting article: ubiquity.acm.org/article.cfm?id=1513451Majenko– Majenko2016年11月30日 10:27:59 +00:00Commented Nov 30, 2016 at 10:27
-
@Ciastopiekarz If you share and explain your sketch (and the debug output, which states how many bytes have been used from what memory) we could try and point out where it could be optimized. Often, it's just the whole approach that is ineffective/inefficient.aaa– aaa2016年11月30日 12:23:15 +00:00Commented Nov 30, 2016 at 12:23
Explore related questions
See similar questions with these tags.