Reduce Uno RAM usage

For our school project we have to use arrays extensively, so I decided to create a pretty simple to use wrapper class. However since I created this class, the RAM usage of my arduino raised quite a bit. From a couple of bytes, to almost half a kilobyte. Maybe someone can give me a hint to make the class below use less RAM?

#ifndef Array_h
#define Array_h
template<class T>
class Array {
  public:
    Array()
      {
	//Initialize array
        values = new T[0];
      }
    ~Array()
      {
	//Garbage cleaning
        delete [] values;
      };
    //Return the size of the array
    int size()
      {
        return numItems;
      }; 
	  
    //Add item  
    void add(T item)
      {
	//Create an array of the current size + 1
        T* tmp = new T[size()+1];
	//Add items to new array
        for(int i = 0; i < size(); i++)
        {
          tmp[i] = values[i];
        }
	//Add the new item
        tmp[size()] = item;
	//Set the array back to the property, and add to our size counter
        values = tmp;
        numItems++;
      };
      
      //Remove item at index
      void remove(int idx)
        {
	  //Can't remove  if there are less then 1 items
	  if(numItems < 1)
	    return;
	  //Create a new array of current size - 1		
          T* tmp = new T[size() - 1];
          int c = 0;

	  //Add items, except for the given index to the new array
          for(int i = 0; i < size(); i++)
          {
            if(i != idx)
            {
              tmp[c] = values[i];
              c++;
            }
          }
          values = tmp;
          numItems--;
        };
        
      //Return the item at idx
      T get(int idx)
        {
	  if(numItems < 1)
            //Empty <typename> if there are less then 1 items
	    return T;
          return values[idx];
        };
        
        void inverse()
        {
          T * tmp = new T[numItems];
          int c = 0;
	  for(int i = numItems; i > -1; i--)
	  {
	    tmp[c] = values[i];
	    c++;
	  }
	  values = tmp;
	};
  private:
    T* values;
    int numItems;
};
#endif //Array_h

Do not use a wrapper class. When it comes to MCU, there is a rule of thumb: the simpler, the better. That is to be taken from the perspective of the generated code, not from the code written by the programmer.

Creating a class simplifies the coding process quite a bit, and increases reusability, but adds complexity to the generated code, which sometimes the Arduino cannot afford (like you've already found out).

Hmm, that seems to make sense. The thing I don't understand is, how can such an tiny class take up so much space, without even any variable being inserted into the array.

Not all students have the same programming abilities (it really differs quite a bit), which is the reason for creating the class. So if possible I would still like to reduce the RAM usage, if possible. This would also be a learning curve for me, as in how to write optimal codes.

Dynamic arrays are a bad idea in small RAM environments. It's better to define permanent buffer space and swap in and out as necessary. Even for strings, make a char array and use it even if for general use. Yes, avoid C++ String objects on Arduino. Sure, you need to do more design work but you'll have more RAM to use better if you do the design work up front.

I've programmed in other languages (PHP, Java, C# etc) where the memory use doesn't matter (that much), and dynamic arrays are pretty simple to use.
Guess that I've gotta get used to the fact that this is just a very tiny computer, with very little RAM, and there is no easy fix for that. Had hoped for it, but so be it.

But on the other hand, it's the little things like this through which you learn, so now I know for a next time to keep everything as small and simple as possible.

Thanks for clearing this up :slight_smile:

I've programmed in other languages (PHP, Java, C# etc) where the memory use doesn't matter (that much), and dynamic arrays are pretty simple to use.

It's not a language issue. It's the hardware that matters. A PC, where the other stuff you've written runs, has a lot more real memory, and virtual memory to back that up. You can afford to waste memory when there is plenty. You can't afford to waste a byte when there is so little.

That's kinda what I meant. Just put differently :stuck_out_tongue:

For my next project (Can't change the entire project now, I do want a good grade ^^), I'm focussing mainly on keeping it as small and optimized possible. It'll be a nice test for me, as usally I don't care for memory that much. It's like you said, You can afford to waste memory when there is plenty. This topic really got me thinking about memory usage.

Well for your next project, to reduce SRAM usage, you can look into using PROGMEM and the techniques around fetching values from Flash for your character arrays (character strings are really character arrays under the hood) or any other array that doesn't change value like look-up tables.

The simplest way to do it for a character array that you only use once in your code is to wrap it in F(...) when you output the character array. For example, instead of:

Serial.print("The value of my all important variable is: ");
Serial.println(variable);

Which will store the character array "The value of my all important variable is: " in the valuable SRAM, use this:

Serial.print(F("The value of my all important variable is: "));
Serial.println(variable);

Which will store the character array "The value of my all important variable is: " in the Flash area (where the actual executing code is, much more space than SRAM, on my UNO 32k Flash vs 2k SRAM). On execution it will fetch the character array from Flash and hand it off to Serial.print. There is an array buffer in SRAM used by the F(...) method, but it gets reused (or destroyed and then recreated, I'm not sure which) for the next character array.

For character arrays that are used multiple times or other constant arrays that are used programmatically (like look-up tables), you will then have to learn how to use the PROGMEM argument, and how to to fetch values. Here are a couple links to get you started:
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
http://playground.arduino.cc/Main/PROGMEM

A technique that I've been playing with based on the two links above for dumping a PROGMEM stored character array byte by byte (looking for a null as the termination character) to the serial port. Kinda reverse of proper reading of the serial port. My experiments seem to show that it is just as fast as copying the character array in PROGMEM to a character array in SRAM and dumping the SRAM character array to the serial port. But it saves SRAM by only using a 1 byte buffer instead of an array buffer that is as large (or larger) than the longest string stored in PROGMEM.

If anyone is interested I can post my code, but it would probably be more instructive to learn how to do it from my description. (And, really, is starting to escape the scope of this particular thread.)

Well the last bit is pretty much what I’m doing for my project as well.
The arduino only acts event based. The computer (through a Java application) waits for an order to be placed, then sends the arduino a command, on which it should pick up the order from a “warehouse”. To prevent hijacking I first do a handshake between the arduino and the Java app, and when that succeeds, then the Java application can send predefined commands to the arduino, and vice versa.

That’s one of the implementations of the array, to store the commands. So what I’m going to try next is to save the commands in the Flash memory, and see if this might help clear up some memory.

And I totally agree on your point of figuring this out by myself, it is and always will be the best way to learn (in my opinion at least)

Guess I kinda figured it out. Storing 5 strings, totalling 25 characters (each String of a different length), takes up 34 bytes of storage in SRAM when I use progmem. However when I use a regular string array, the usage is 69 bytes (35 additional bytes) in SRAM. I did those calculations using the estimation the Arduino Enhanced Release gave me. Which seems pretty accurate to me.

So according to my calculations for every String stored using progmem, that saves up to 3 bytes in comparison to a String. I assume that is 1 byte overhead for the char array of each String, and another 2 bytes for what I assume is the String object.

However, there still is one thing that bothers me... And that is that the amount of Flash memory used, when storing strings using progmem, is less then it was when I was using a regular array. 204 bytes less to be exact. Whilst my assumption would be that more Flash memory would be used when storing using progmem. Or is just because of the string object, that takes up that much space?

Here's a snippet of what I used for my tests:

//For progmem
const char* const Commands::commands[] PROGMEM = {
    "LED",
    "COMMAND",
    "START_CONVEYER",
    "START",
    "A"
  };

//For regular string array
const String[] Commands::commands[] PROGMEM = {
    "LED",
    "COMMAND",
    "START_CONVEYER",
    "START",
    "A"
  };

I know I'm asking quite a lot, but I just want to learn as much as possible about the Arduino :smiley:

When you use the regular version, it is still stored in flash. When the MCU starts the global data section is initialised by copying the flash contents into ram.
The progmem features have a little overhead, but when used multiple times to replace ram data, it can produce smaller code like you see.

I know when you are low on memory, you are low. I'm no expert by any means, but I'm not sure it's a good idea using flash memory. If I remember right, I think the spec sheet on the 328p said it's only good for 10,000 flashes - stupidly, by accident, put it in a loop 10,000 times and your chip may not work or cause problems - see what even one else has to says about it

If I remember right, I think the spec sheet on the 328p said it's only good for 10,000 flashes - stupidly, by accident, put it in a loop 10,000 times and your chip may not work or cause problems - see what even one else has to says about it

If "it" refers to avrdude uploading the sketch to the Arduino, then, yes, that could be a mistake.

If "it" refers to some code on the Arduino executing a loop 10,000 times, reading from read-only memory won't cause the chip to wear out.

I'm no expert by any means, but I'm not sure it's a good idea using flash memory.

The flash memory is only changed when you upload a sketch, you may be thinking of the EEPROM, which has 10x more writes than the flash, but still has a limit.

You can write a program that 'exercises' flash, but not if it sits on top of any bootloaders I've seen listed.
There are AVR systems that use that. AVR Forth and another Forth that runs on AVR's writes to flash as normal operation, generally in a write-once manner. But they don't use bootloaders and they are interpreters.

Thank you Sembazuru and pYro_65 for your comments. I learned
something useful from you both.

Sembazuru's comment: Serial.print(F("xyz"));

pYro_65's comment: flash memory is only changed when you upload a sketch