16

Most Arduinos (like the Uno or Nano) have very few RAM, thus you first need to make sure, that you never allocate too much memory. Also dynamically allocating memory can lead to heap fragmentation (heap being the part of memory, where dynamic allocation happens). In most cases you would want to allocate memory of different sizes (for example arrays of ...


14

What are the generally practiced methods for the optimization program memory usage? First, note you are searching for ways to lower SRAM memory. This contains global (variable) memory and heap space (dynamic memory + stack memory). Avoid memory gaps, by not using dynamic memory (with free/malloc/new). Avoid using the String class. Avoid global memory in ...


12

As you have noticed yourself, this can be somewhat platform-dependent. Since you are working on a Nano, my answer will be for the AVR architecture, when compiled with gcc, the avr-libc, and the Arduino core library. First, let me reassure you: this weird behavior you saw of the Wixel doesn't happen on this platform. Local variables get allocated mostly in ...


10

AVR is a modified Harvard architecture family, so code is stored in flash only, whereas data exists primarily in RAM when being manipulated. With that in mind, let's address your questions. Why on earth do I have to copy the damn content to RAM before accessing it? You don't need to per se, but by default code assumes that data is in RAM unless the code ...


10

Say you have a string of 1000 characters in Flash, and you want to print it to Serial. Yes, you need to load it into RAM in order to pass that data around the place for printing. But, do you need to put all of it in RAM at once? No. You only need one character at a time. So instead of taking 1000 characters and allocating 1000 bytes of RAM and copying ...


9

The short answer is no: PROGMEM data is read-only. Flash memory limitations The first thing to understand is that Flash memory (where program space lives) is designed for long-term fixed storage. Reading from it is very fast and precise. However, generally speaking, you can't modify it on a byte-by-byte basis (e.g. changing a specific variable). You usually ...


9

The Arduino EEPROM library is compatible with the ATTiny range of AVR microcontrollers as the library itself is built on the standard Atmel AVR avr/eeprom.h 'library' so it is compatible with all the AVR microcontrollers. The EEPROM also doesn't take to being written or read to often as EEPROM can wear very quickly. Reading though does not cause much damage ...


9

There is a lot you are missing. Such as: SoftwareSerial is using RAM. The system stack is using RAM. The Arduino core software is using RAM. There's plenty more going on than just your sketch. For instance, where do you think it stores the current millis() and micros() counts? Where do you think incoming serial data gets buffered? Where do you think your ...


9

Since you seem interested about RAM, rather than flash usage, I suggest you look at the symbol table of your compiled program, which will be more telling than the disassembly. On my Linux system, I usually do the following: avr-nm -Crtd --size-sort the_program.elf | grep -i ' [dbv] ' avr-nm is the utility for displaying the symbol table. It is normally ...


8

This is how Print::print prints from program memory in the Arduino library: size_t Print::print(const __FlashStringHelper *ifsh) { const char PROGMEM *p = (const char PROGMEM *)ifsh; size_t n = 0; while (1) { unsigned char c = pgm_read_byte(p++); if (c == 0) break; n += write(c); } return n; } __FlashStringHelper* is an empty class ...


8

The Arduino core macro F() takes a string literal and forces the compiler to put it in program memory. This reduces the amount of SRAM needed as the string is not copied to a data memory buffer. Special functions are required to access the data stored in program memory. The Arduino core hides a lot of the typical usages such as: Serial.println(F("Hello ...


8

That is an incredibly hard question to give a definitive answer to. In general using OO consumes more memory, but that is the price you pay for greater flexibility and ease of use. The difference is usually minor though. Variables within an object take the same amount of space as variables outside an object. It's just the overhead of instantiating the ...


8

If I dare suggest an unorthodox solution... I suggest you store the times as “float11” floating point numbers. Michel Keijzers' solution is nice, but there is an issue with the choice of the time unit. If you use 0.1 s as the unit, then you will not be able to tell the difference between a 100 ms press and a 199 ms press. I am sure these ...


8

You'll find no noticeable difference memory-wise between the two. The only real difference is that the const method also imposes a type to the value, which can be useful for function overloading or mathematical operations.


7

If you add a debugging print you will see what is happening: void setup() { Serial.begin (115200); Serial.println (); pinMode(13, OUTPUT); int len = 5000; byte *data = (byte *)malloc(len * sizeof(*data)); Serial.print ("data = "); Serial.println ((int) data); } Output: data = 0 The malloc failed, it returned NULL, the rest of the program ...


7

You can decipher most of them yourself. A u prefix means unsigned. The number is the number of bits used. There's 8 bits to the byte. The _t means it's a typedef. So a uint8_t is an unsigned 8 bit value, so it takes 1 byte. A uint16_t is an unsigned 16 bit value, so it takes 2 bytes (16/8 = 2) The only fuzzy one is int. That is "a signed integer value at ...


7

I just want to add a single bullet to Michel Keijzers’ excellent answer: think about every single item you are storing in memory and ask yourself the question: do I really need to keep this in RAM? It may sound silly to state what many would consider obvious, but we have seen here many instances of novices who do not take this into consideration. As a ...


7

Dynamic allocation is generally discouraged in embedded applications because you cannot guarantee that you do not exceed (attempt to allocate more than) the available memory. Static allocation will generally have this guarantee although out-of-memory bugs may still be possible. Additionally, far fewer services or tools are available to automatically manage ...


6

Expanding on my previous comment... The RAM memory map of an AVR-based Arduino looks like this: ┌──────┬─────┬──────┬──────────┬───────┐ │ data │ bss │ heap │→ free ←│ stack │ └──────┴─────┴──────┴──────────┴───────┘ The data and bss sections are fixed, and their size can be known at compile time. However, the stack and the heap grow and shrink ...


6

One approach is to look at the assembly listing of the program. After compiling the program (via the Verify or Download button) locate the directory where the .cpp, .hex, and .elf files for the program have been stored. (If you have trouble finding them, briefly turn on verbose compile options in the arduino IDE and look at the directory names in the ...


6

This is not a direct answer to your question, as I have no such answer, and I believe the answer you are seeking would be of no use to you. The problem with your question is that your method of testing memory usage is heavily flawed. By removing the switch statement, you most likely have allowed the linker to remove lots of methods referenced by it, leading ...


6

This all gets very much trickier than just an array of function pointers. Your functions are methods in unknown objects. As such you can't have one single type that stores pointers to the functions in different objects. The simple reason is that C++ changes the function prototype for you. For instance, it changes: class MyClass { public: int ...


6

There are SRAM ICs / boards, however, don't expect 100 MB, more like 1 MB (with the pin numbers and connectivity / protocols that an Arduino offers). With Flash you can get much further, but it can only be written a number of times; not sure if that suits your requirements. Beyond that, I'm afraid the real problem is in the processing speed. Mixing 100 ...


6

I am afraid there is no good solution to this problem. One option I do like is to use the __flash qualifier instead of PROGMEM: const uint8_t ram_array[] = { 1, 2, 3, 4 }; __flash const uint8_t flash_array[] = { 5, 6, 7, 8 }; void function_reading_ram(const uint8_t *array) { uint8_t secondElement = array[1]; // ... } void function_reading_flash(...


5

It's stored in both the FLASH and SRAM because it's initialized array. To store in FLASH only you need use PROGMEM attribute. const unsigned PROGMEM char g1[]= ... You cannot access directly but using memcpy_P() function.


5

The AVR (the microcontroller family traditionally used on Arduino boards) is a Harvard Architecture, meaning that executable code and variables are in two separate memories - in this case flash and SRAM. The executable code never leaves flash memory. When you call a function the return address is usually pushed to the stack - the exception is when the ...


5

Local variables and function parameters are stored on the stack. However, that is not a reason not to use them. Computers are designed to work that way. Stack memory is only in use while a function is active. As soon as the function returns, the memory is freed. Stack memory is a GOOD Thing. You don't want to use recursive functions with lots of levels of ...


5

You can try (explict unsigned long values): unsigned long fromValues = (0x00UL << 16) | (0x01 << 8) | 0xF3; Serial.println(fromValues); or: value = (((unsigned long) c1) << 16) | (c2 << 8) | c3; The issue is that the expression is implicit int and not long (as you are assuming). You need to tell the compiler about this. An ...


5

What would be the best-practice in this kind of situation? To not use String. I also want to allow the end user to use the String functions (like indexOf) to search for particular content in emails. There's nothing wrong with providing an indexOf function in your API. But you don't have to use String to implement that function when called. You can just ...


5

A simple SPI SRAM chip. Available up to 128KB, such as the 23LC1024: http://www.microchip.com/wwwproducts/en/23LC1024


Only top voted, non community-wiki answers of a minimum length are eligible