When working with ESP8266 or with Arduino boards I sometimes come across expressions like client.println(F("Server started."));
– That is the moment when I wonder what difference there is compared to client.println("Server started.");
. After all, both versions will usually work.
In looking for an answer, I found a good discussion on the Arduino forum that explains the background of the F()
function. Here are the key takeaways:
- Arduinos and Arduino-like devices such as the ESP8266 or the ESP-32 feature a so called Harvard architecture.
- This means that there are separate memories for instructions and data.
- Instructions are stored in the FLASH memory.
- Data is stored in the RAM.
- In the Arduino world, code memory is sometimes referred to as PROGMEM and data memory is referred to as SRAM.
- String constants are data and would normally be stored in the (S)RAM.
- Methods such as
Serial.println()
expect theString
argument to be a pointer to achar[]
array that resides in SRAM, not in the FLASH/PROGMEM section. - To preserve RAM, we could also try to put
String
constants into the PROGMEM/FLASH part of the device, but there is a problem: objects stored in PROGMEM/FLASH are different from the traditionalchar[]
arrays stored in SRAM. - The
F()
function forcesString
data to be stored in PROGMEM/FLASH and ensures that these objects behave like ordinarychar[]
arrays in later parts of the code.
The RAM memory in all cases is no more than 160 kB (depends on what exactly you count as RAM see here). Therefore it might make sense to move string data to the FLASH section.
There is a very good explanation on PROGMEM and the F()
macro on the Arduino reference pages. The key takeaway is:
When an instruction like
Serial.print("Write something to the Serial Monitor");
is used, the string to be printed is normally saved in RAM. If your sketch prints a lot of stuff on the Serial Monitor, you can easily fill the RAM. If you have free FLASH memory space, you can easily indicate that the string must be saved in FLASH using the syntax:
Serial.print(F("Write something to the Serial Monitor"));
Note in particular, that the “generous” amount of memory is in the FLASH and not in the RAM (RAM will always be limited to around a meagre 160 kB). Especially with the Pro devices, there is an abundant amount of PROGMEM/FLASH. So flong strings or a series of strings that e.g. hold HTML code to define a web page, it makes sense, the F()
macro is useful to redirect storage towards the PROGMEM/FLASH memory part.