{"id":1472,"date":"2021-02-21T13:45:31","date_gmt":"2021-02-21T12:45:31","guid":{"rendered":"http:\/\/hobbykeller.spdns.de\/?p=1472"},"modified":"2021-06-12T14:40:14","modified_gmt":"2021-06-12T12:40:14","slug":"f-function-with-strings-in-arduino-programming","status":"publish","type":"post","link":"https:\/\/hobbykeller.spdns.de\/?p=1472","title":{"rendered":"F() Macro with Strings in Arduino Programming"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">When working with ESP8266 or with Arduino boards I sometimes come across expressions like <code>client.println(F(\"Server started.\"));<\/code> &#8211; That is the moment when I wonder what difference there is compared to <code>client.println(\"Server started.\");<\/code>. After all, both versions will usually work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In looking for an answer, I found a good <a href=\"https:\/\/forum.arduino.cc\/index.php?topic=91314.0\" data-type=\"URL\" data-id=\"https:\/\/forum.arduino.cc\/index.php?topic=91314.0\" target=\"_blank\" rel=\"noreferrer noopener\">discussion on the Arduino forum<\/a> that explains the background of the <code>F()<\/code> function. Here are the key takeaways:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Arduinos and Arduino-like devices such as the ESP8266 or the ESP-32 feature a so called <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Harvard_architecture\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Harvard_architecture\" target=\"_blank\">Harvard architecture<\/a>.<\/li><li>This means that there are <strong>separate memories<\/strong> for <strong>instructions<\/strong> and <strong>data<\/strong>.<\/li><li><strong>Instructions<\/strong> are stored in the <strong>FLASH<\/strong> memory.<\/li><li><strong>Data<\/strong> is stored in the <strong>RAM<\/strong>.<\/li><li>In the Arduino world, code memory is sometimes referred to as PROGMEM and data memory is referred to as SRAM.<\/li><li>String constants are data and would normally be stored in the (S)RAM.<\/li><li>Methods such as <code>Serial.println()<\/code> expect the <code>String<\/code> argument to be a pointer to a <code>char[]<\/code> array that resides in SRAM, not in the FLASH\/PROGMEM section.<\/li><li>To <strong>preserve RAM<\/strong>, we could also try to put <code>String<\/code> constants into the PROGMEM\/FLASH part of the device, but there is a problem: objects stored in PROGMEM\/FLASH are <strong>different<\/strong> from the traditional <code>char[]<\/code> arrays stored in SRAM.<\/li><li>The <code>F()<\/code> function forces <code>String<\/code> data to be stored in PROGMEM\/FLASH and ensures that these objects behave like ordinary <code>char[]<\/code> arrays in later parts of the code.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-warning\" role=\"alert\">Note that the memory that is advertised (1 \/ 4 \/ 16 MB depending on whether it&#8217;s the D1 Mini Lite \/ Standard \/ Pro) refers to the FLASH memory. <br><br>The RAM memory in all cases is no more than 160 kB (depends on what exactly you count as RAM see <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/ESP8266\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/ESP8266\" target=\"_blank\">here<\/a>). Therefore it might make sense to move string data to the FLASH section.<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">There is a very good explanation on PROGMEM and the <code>F()<\/code> macro on the <a rel=\"noreferrer noopener\" href=\"https:\/\/www.arduino.cc\/reference\/en\/language\/variables\/utilities\/progmem\/\" type=\"URL\" id=\"https:\/\/www.arduino.cc\/reference\/en\/language\/variables\/utilities\/progmem\/\" target=\"_blank\" class=\"broken_link\">Arduino reference pages<\/a>. The key takeaway is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>When an instruction like<\/p><p><code>Serial.print(\"Write something to the Serial Monitor\");<\/code><\/p><p>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:<\/p><p><code>Serial.print(F(\"Write something to the Serial Monitor\"));<\/code><\/p><p><\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Note in particular, that the &#8220;generous&#8221; 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 <code>F()<\/code> macro is useful to redirect storage towards the PROGMEM\/FLASH memory part.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When working with ESP8266 or with Arduino boards I sometimes come across expressions like client.println(F(&#8220;Server started.&#8221;)); &#8211; That is the moment when I wonder what difference there is compared to<span class=\"more-button\"><a href=\"https:\/\/hobbykeller.spdns.de\/?p=1472\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\">F() Macro with Strings in Arduino Programming<\/span><\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[312,318,310,64],"tags":[305,309,314,317,315,327,316,326],"class_list":["post-1472","post","type-post","status-publish","format-standard","hentry","category-arduino","category-d1-mini-pro","category-iot","category-linux","tag-arduino","tag-esp8266","tag-f","tag-flash","tag-harvard-architecture","tag-progmem","tag-ram","tag-sram"],"_links":{"self":[{"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=\/wp\/v2\/posts\/1472","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1472"}],"version-history":[{"count":9,"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=\/wp\/v2\/posts\/1472\/revisions"}],"predecessor-version":[{"id":1508,"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=\/wp\/v2\/posts\/1472\/revisions\/1508"}],"wp:attachment":[{"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1472"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1472"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hobbykeller.spdns.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1472"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}