Storing Constants in Arduino Programs
/Welcome to another of my "I put this into my blog because otherwise I forget how to do it and have to go onto the net and find out again" posts.....
I really like writing programs for the Arduino platform. The good news is that the devices can do a lot, but the programs themselves are actually very tiny. The bad news is that you are working in an environment where there is hardly enough of every kind of resource. Particularly memory.
In an Arduino there are two kinds of memory. There is RAM (random access memory) which is where your program stores the variables it is working on at any given time and there is EEPROM (Electrically Erasable Programmable Read Only Memory) which is where the program code lives. When you put your program into the Arduino it is stored in the EEPROM part and runs from there. If your program creates any variables, these are stored in the much smaller RAM.
If you want things like large look up tables (which would usually be stored in the memory of your computer) then you are heading for trouble, as you only have a strictly limited space to store data values. Fortunately you can move constant data into the program memory of the device, so that it doesn't need to be stored in the precious data space.
const byte big_lookup_table [] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
The statement above creates a big (actually not that big, but you get the picture) array of bytes that I've called big_lookup_table. I've added the modifier PROGMEM to tell the compiler I want the table to be located in program memory, not RAM. The table could be quite big (an Arduino UNO has around 28K of program memory available as I recall), you could save things like sound samples or images here if you wanted to.
The only slight complication is that when you want to get hold of the elements in the array you can't just directly access them. Instead you have to use a macro which will do the fetching for you.
x = pgm_read_byte(&big_lookup_table[i]);
The statement above takes the element at location i and fetches it into byte variable x. This also means that fetching data from program memory is a tiny bit slower than "normal" variables, but in practice you don't notice the difference.