Flash

A Library to Ease Accessing Flash-based (PROGMEM) Data

Storing static program data in flash/PROGMEM is a tricky part of Arduino programming. To save precious RAM, a novice user already at odds with unfamiliar C++ syntax must digest such daunting concepts as prog_char, PSTR(), PROGMEM, pgm_read_word(), etc. Even seasoned users get tripped up by the indirection and typecasting that are required to retrieve valid PROGMEM data. Add to that a couple of apparent bugs in the implementation, and it’s clear that PROGMEM is a complicated mess.

I have written a new library, Flash, which abstracts away most of this complexity. It provides new String, Array, Table, and String Array types that make ROM-based data collections as easy to use as “normal” types. Each overrides the C++ [] operator, so to extract individual elements one uses familiar array access syntax:

// float array example
float t = temperatures[950];

// (2D) font table example
digitalWrite(pin[i], font_table['a'][i]);
// string example
for (int i=0; i<str.length(); ++i)
  if (str[i] == ';') break;

Download and Installation

To install this library, download here, unzip the archive into the Arduino “libraries” folder, and restart Arduino. You should rename the folder “Flash”, because the IDE doesn’t like dashes in the name.
Download

Creating named Flash objects

To create a Flash object, you use a library-provided macro. Each of the four basic types provides its own creation macro:

Strings: FLASH_STRING(name, value)
Arrays: FLASH_ARRAY(type, name, list of values…)
Tables: FLASH_TABLE(type, name, columns, values…)
String Arrays: FLASH_STRING_ARRAY(name, values…)

Examples:

FLASH_STRING(big_string, "Moreover, as you might appreciate, "
    "their implications were such as to provoke a certain "
    "degree of sorrow within me. Indeed - why should I not "
    "admit it? - at that moment, my heart was breaking.");
FLASH_ARRAY(float, temperatures, 23.1, 23.1, 23.2, 23.2, 23.4,
    23.7, 25.0, 26.0, 26.8, 28.8, 30.2, 31.9, 33.1, 33.1, 33.2,
    33.2, 33.4, 33.7, 35.0, 36.0, 36.8, 38.8, 40.2, 41.9);
FLASH_TABLE(boolean, font_table, 7, {0,0,0,0,0,0,0},
    {0,0,0,1,0,1,1}, {1,0,1,1,1,0,1}, {1,1,0,0,0,0,0},
    {0,1,0,1,0,1,0}, {1,0,1,1,1,0,1}, {1,0,0,1,0,0,1},
    {0,0,1,1,0,1,1}, {1,0,1,1,1,1,1});
FLASH_STRING_ARRAY(digits, PSTR("Zero"), PSTR("One"),
    PSTR("Two"), PSTR("Three"), PSTR("Four"), PSTR("Five"),
    PSTR("Six"), PSTR("Seven"), PSTR("Eight"), PSTR("Nine"));

[Note that you can make Arrays and Tables out of any native type.]

[Note also that the String Array is a slightly special case. For technical reasons, as you can see in the example, each member of the array initializer must be wrapped with the PSTR() operator. For this reason, String Arrays cannot be declared at global scope, but must be non-statically defined within in the body of a function. Note also that while the individual strings in a String Array are contained in PROGMEM space, the array itself (again, for technical reasons) is RAM-based, consuming 2 bytes per array element. This limitation does not apply to the other Flash types.]

Using named Flash objects

Array-like access. Each Flash type provides an [] operator to get access to the underlying data, for example:

    // extract an element from an Array
    float t = temperatures[5];
    // examine characters in a String
    for (int i=0; i      if (big_string[i] == 'O') ++big_O_counter;
    // Use a font table to configure a 7-segment display
    for (int i=0; i      digitalWrite(pins[i], font_table[1][i]);
    // Examine the sizes of strings in a String Array
    for (int i=0; i      Serial.println(digits[i].length());

Since Tables are really just two-dimensional arrays, the Table object’s implementation of [] returns a one-dimensional Array object.

Size. Each Flash type provides a mechanism for determining its size:

String and String Array: size_t length();
Array: size_t count();
Table: size_t rows(); size_t cols();

Access. If you need it, each Flash object provides an access() method that returns the underlying PROGMEM pointer

Print compatibility. Each Flash object has a print() method that can be used to serialize the object to any stream derived from core class Print (HardwareSerial, NewSoftSerial, LiquidCrystal, Ethernet, PString, etc.) See “Printing Flash objects” below.

String copy. Flash String objects may be copied in whole or part to RAM using the String object’s copy method:

    // copies the first 10 characters of the big_string
    char temp[11];
    big_string.copy(temp, 10);

Printing Flash objects

Each Flash object can “print” itself, using either its print method directly:

    temperatures.print(Serial);
    big_string.print(lcd);
    font_table.print(softserial);

or, equivalently, by using the << streaming operator:

    Serial << temperatures;
    lcd << big_string;
    softserial << font_table;

Library Version

You can retrieve the version of the Flash library by inspecting FLASH_LIBRARY_VERSION.

int ver = FLASH_LIBRARY_VERSION;

Download

The latest version of Flash is available here: Flash5.zip

Change Log

  1. initial version
  2. moved some code to a new .cpp file to avoid inlining every member function
  3. fixed a bug in the copy() method

Acknowledgements

Thanks to forum user Bill W. (“westfw”) for testing Flash and observing that Strings take up a surprising amount of extra PROGMEM space (20 bytes per string). I used his data to modify the library so that some of the commonly used functions, notably the _FLASH_STRING constructor are not inlined. This change reduces the footprint of the example programs noticeably. Thanks, Bill!

I appreciate any suggestions or input.

Mikal Hart

Page last updated on January 30, 2014 at 9:41 pm
252 Responses → “Flash”

  1. Mikal

    10 years ago

    @Karl,

    Thanks. Next rev will definitely have this.


  2. Mikal

    10 years ago

    @Olx,

    Yep, but this isn’t a problem with Flash. You can’t Serial.println() a type that Serial.println() doesn’t know. You’d get the same error with

    Serial.println(t);
    

  3. Mikal

    10 years ago

    You could create a global or class variable of type _FLASH_STRING_ARRAY * and set it like this:

    _FLASH_STRING_ARRAY *parray;
    parray = &pips;
    

  4. Mikal

    10 years ago

    @Hans,

    I would use the onboard EEPROM to store incoming telephone numbers. You can’t really use Flash for that kind of thing. Read up on Arduino+EEPROM.


  5. Mikal

    10 years ago

    @Passcal, I’m afraid I don’t know of any F() bugs.


  6. dimitryous

    10 years ago

    On install “Flash” I got the following message: ‘Warning: class ch.randelshofer.quaqua.osx.OSXFile can’t use library quaqua64. It has version 4 instead of 5′.

    Running Arduino 1.0.5 on MacOS 10.9.1 3.7GHz Intel QuadCore i16

    Hope this will help…


  7. Mikal

    10 years ago

    @dimitryous, I don’t think that message has anything to do with Flash. In any case, it doesn’t mean anything to me. Sorry.


  8. C W Rose

    10 years ago

    On compiling the Flash-5 library I get:

    /usr/share/arduino-1.0.5/libraries/Flash/Flash.h:60:0: warning: “F” redefined
    /usr/share/arduino-1.0.5/hardware/arduino/cores/arduino/WString.h:38:0: note: this is the location of the previous definition

    The obvious answer is to rename the F() macro to FL(), but I’m not sure of the further effects. Do you have any suggestions?

    (It might also be useful to warn people of the avr-libc 1.8 problems with prog_char, and the need for “-Wno-deprecated-declarations -D__PROG_TYPES_COMPAT__” when compiling older code.

    Will


  9. Mikal

    10 years ago

    @C W Rose,

    Hmm.. That definition is guarded with an #if ARDUINO < 100. It shouldn’t compile on Arduino 1.0.5. Is there something peculiar about your configuration?


  10. C W Rose

    10 years ago

    Right, I hadn’t noticed that. ARDUINO must be undefined,
    for some reason. I’ll check it out.

    Will


  11. charles

    10 years ago

    is the library working with arduino due ?

    thanks charles


  12. Mikal

    10 years ago

    Hi Charles–

    No, it doesn’t work on Due. I hadn’t thought to port it because the Due has so much RAM already, but I ought to make it at least compile correctly… :)


  13. Haulier

    9 years ago

    I cant run this programm when i put FLASH into my librarie i have a erreur when compilation for using flash :

    In file included from flash_streaming.pde:21:0:
    /root/sketchbook/libraries/Flash/Flash.h:70:23: error: ‘prog_char’ does not name a type
    _FLASH_STRING(const prog_char *arr);
    ^


  14. Mikal

    9 years ago

    @Haulier,

    What Arduino board have you selected? Flash only works on AVR (Atmel) boards.


  15. The Raven

    9 years ago

    Why does this sketch not work?

    It will only recall one variable.

    #include

    FLASH_ARRAY(int, analog_values, 1022, 1024, 836, 844, 926, 934, 558, 566, 692, 700);

    void setup()
    {
    Serial.begin(9600);

    int x = analog_values[0];
    int y = analog_values[1];

    Serial.println(x);
    Serial.println(y);
    }

    void loop()
    {
    }


  16. gr1ff1n

    9 years ago

    Hi,

    I am using your Flash and Streaming library for a project and have encountered a problem with Flash. I am using it to store a large look-up table. But when I search it for a certain value and try to read two positions into local variables, the second reading is wrong. Instead I get two times the same value (first reading). Only workaround is to add delay(..) or delayMicroseconds(..) in between the readings. The exact delay doesn’t matter (delayMicroseconds(1) will do just fine. The thing is, that I search the table in a loop and the compare function does always find the correct position. The problem only occurs when I read values within a row :/

    Is there any new information about this bug?


  17. Liss

    9 years ago

    Great library, however when compiling I get some warnings: http://www.pasteall.org/52721/text

    I fixed most of them, here is the patch: http://www.pasteall.org/52722/text

    With above patch, only one warning left, about “size == -1″ comparison in Flash.h. I’m not sure how to fix it because I do not understand how it was supposed to work in the first place if “size” declared as “size_t” (which is unsigned)?


  18. Brad

    9 years ago

    Hmm, I’m using TinyWebServer, which is in turn using Flash. You mentioned above that Flash won’t work on Due – I’m using Teensy3.1, which is also ARM rather than AVR based and Flash throws compile errors like:

    In file included from WebServerSD.ino:10:0:
    C:\Users\X\Arduino\libraries\Flash/Flash.h: In member function ‘char* _FLASH_STRING::copy(char*, size_t, size_t) const’:
    C:\Users\X\Arduino\libraries\Flash/Flash.h:78:37: error: operands to ?: have different types ‘char*’ and ‘int’

    Just in case you decided to look into it, here’s the lines pointed to from the error:

    /* _FLASH_STRING class. Use the FLASH_STRING() macro to create these, or use inline F() macro. */
    class _FLASH_STRING : public _Printable
    {
    public:
    _FLASH_STRING(const prog_char *arr);

    size_t length() const
    { return strlen_P(_arr); }

    char *copy(char *to, size_t size = -1, size_t offset = 0) const
    {
    return size == -1 ?
    Error Line–>> strcpy_P(to, _arr + offset) : strncpy_P(to, _arr + offset, size);
    }

    const prog_char *access() const
    { return _arr; }

    const _Printable &Printable() const
    { return *this; }

    char operator[](int index) const
    { return static_cast(pgm_read_byte(_arr + index)); }

    void print(Print &stream) const;

    private:
    const prog_char *_arr;
    };


  19. Mikal

    9 years ago

    @Liss,

    Thanks. The comparison to -1 is me basically comparing with the largest possible size_t. It should probably be “size = (size_t)-1″.


  20. Mikal

    9 years ago

    Try replacing the body of copy:

    char *copy(char *to, size_t size = -1, size_t offset = 0) const
    {
    if (size == -1)
    strcpy_P(to, _arr + offset);
    else
    strncpy_P(to, _arr + offset, size);
    return to;
    }


  21. Eule

    9 years ago

    Hi Mikal
    Great library, I have been using it a lot.
    I just got a Arduino YUN which means I have to use Arduino IDE 1.5.7 and get following compile error:
    error: ‘prog_char’ does not name a type _FLASH_STRING(const prog_char *arr);
    The YUN has ATmega32U4 which I would have thought should work with the Flash library.
    Any suggestions?
    Regards


  22. Darren Lind

    9 years ago

    Hi,

    I noticed that your library comes up with a few warnings when compiled, I think Ive fixed them.

    The ‘prog_char’ data type has been depreciated, I believe it can be replaced with ‘char’ in your .h and .c files

    You have this in your .h file
    char *copy(char *to, size_t size = -1, size_t offset = 0)
    ‘size_t’ is an unsigned data type, so when you test it in the return statement it spits out a warning
    I changed the default to 0 as you wouldnt copy something of 0 size, this code seems to work but not sure if will always work.

    char *copy(char *to, size_t size = 0, size_t offset = 0) const
    {
    return size == 0 ?
    strcpy_P(to, _arr + offset) : strncpy_P(to, _arr + offset, size);
    }


  23. Elftek

    9 years ago

    Hi, I love this library and we use it extensively and today after we upgraded to arduino ide 1.0.6 we are getting this error.

    /…/libraries/Flash/Flash.h: In member function ‘char* _FLASH_STRING::copy(char*, size_t, size_t) const’:
    /…/libraries/Flash/Flash.h:78:37: error: operands to ?: have different types ‘char*’ and ‘int’

    Can you help fix this error so it would work with 1.0.6? thanks in advance Mikal


  24. Mikal

    9 years ago

    @Elftek, I’ll take a look and get back to you…


  25. KiSwiSje

    9 years ago

    I don’t understand exactly what the availableMemory function is trying to prove …

    I use this to check available ram:
    on an uno – sketch returns
    1023
    1842

    // source http://www.gammon.com.au/forum/?id=12615
    int freeRam ()
    {
    return (RAMEND – size_t (__malloc_heap_start));
    }

    void setup ()
    {
    Serial.begin (57600);
    Serial.println (availableMemory());
    Serial.println (freeRam ());
    }

    void loop ()
    {
    }

    int availableMemory()
    {
    int size = 1024;
    byte *buf;
    while ((buf = (byte *) malloc(–size)) == NULL);
    free(buf);
    return size;
    }


  26. Mikal

    9 years ago

    @KiSwiSje,

    I believe you have a bug in your availableMemory() routine. Remove the semicolon at the end of

    while ((buf = (byte *) malloc(–size)) == NULL)
    

  27. Ty Tower

    9 years ago

    Example does not compile on 1.5.8 with this message –how do I fix that?

    In file included from flash_example.pde:21:0:
    /opt/arduino-1.5.8/libraries/Flash/Flash.h:70:23: error: ‘prog_char’ does not name a type
    _FLASH_STRING(const prog_char *arr);
    ^
    /opt/arduino-1.5.8/libraries/Flash/Flash.h:70:34: error: ISO C++ forbids declaration of ‘arr’ with no type [-fpermissive]
    _FLASH_STRING(const prog_char *arr);


  28. Mikal

    9 years ago

    @Ty,

    Later versions of the compiler don’t support the “prog_char” keyword. I think you can just change it to “char” and it will work. I’ll eventually do this myself.


  29. Rob

    9 years ago

    hi…
    I’m Trying to use Flash Library with Arduino 1.5.8 and i’m getting this Error…

    C:\Users\LabTab\Documents\Arduino\libraries\Flash-5/Flash.h: In member function ‘char* _FLASH_STRING::copy(char*, size_t, size_t) const’:
    C:\Users\LabTab\Documents\Arduino\libraries\Flash-5/Flash.h:86:34: error: c in this scope
    strncpy_P(to, _arr + offset, size);

    I would be glad to know the solution for this one.,
    I really need it ASAP., the library seems to work just fine with the older versions of arduino IDE’s but with 1.5.8, I can’t make it work.,
    thanks in advance…


  30. Philipp Masmeier

    9 years ago

    Dear Mikal,

    thanks for this Lib, which I use extensivly in programs, where I use many tables. They’re usually filled with uint8_t-Values, so only one Byte per Entry.

    I defined one FLASH_TABLE with uint16_t but this doesn’t work. Is this a general issue or did I something other wrong. Below I have copied the declaration.

    Thanks and best regards,
    Philipp

    FLASH_TABLE(uint16_t, Signaladressen, 7,
    {200, 105, 0, 105, 1, 104, 1},
    {201, 109, 0, 109, 1, 9999, 9},
    {202, 107, 0, 9999, 9, 107, 1},
    {203, 155, 0, 155, 1, 156, 0},
    {204, 146, 0, 146, 1, 9999, 9},
    {205, 147, 0, 9999, 9, 147, 1},
    {206, 145, 0, 9999, 9, 145, 1},
    {207, 207, 0, 207, 1, 9999, 9},
    {208, 208, 0, 208, 1, 9999, 9});


  31. Mikal

    9 years ago

    @Philipp Masmeier:

    What problem are you having? I copied your code and added

    Serial.println(Signaladressen[3][3]);
    

    … and it printed 155 as expected.


  32. Ovidiu Predescu

    9 years ago

    Mikal, I was able to compile version 5 of your library using the following lines added after the avr/pgmspace.h is included:

    #if ARDUINO >= 150
    typedef char prog_char __attribute__((__progmem__));
    #endif

    Hope this helps.


  33. Mikal

    9 years ago

    @Ovidiu– very helpful, thank you much.


  34. mike

    8 years ago

    hi,

    i am using ide 1.6.4 and nothing happened. it just said “compiling”, but the bar didnt move…

    i changed #if ARDUINO >= 150
    typedef char prog_char __attribute__((__progmem__));
    #endif like Ovidiu suggested, not its working.

    yours, mike.


  35. Ovidiu Predescu

    8 years ago

    Mikal, here’s another fix for version 5 of your library to make it work on the new Cortex M0-based boards. Again, this needs to be added after the avr/pgmspace.h is included. Tested on the official 1.6.7.

    #if ARDUINO_ARCH_SAMD
    extern char* strncpy_P(char* dest, const char* src, int size);
    #endif


  36. Bruce Vernham

    8 years ago

    Is it possible to pass a”FLASH_ARRAY” to a function?


  37. charles

    7 years ago

    @Ovidiu Is it possible to compile for due also?


  38. Ivan

    7 years ago

    is there any way to use the this library to pass values to a function?

    this is my string:
    FLASH_STRING(gfm_atcgatt,”AcfCGATT?\”,\”OK\”,\”yy\”,20000,2″);

    this is my function thay using a lot of memory
    myfunction(“heremyfirstparameterverylong”,”heremysecondparameterverylong)”

    how to transform it?
    myfunction(gfm_atcgatt,…)”

    help please…


  39. Mikal

    7 years ago

    @Ivan, yep, the underlying type is _FLASH_STRING, so you if want to pass that to your function use:

    void myfunction(_FLASH_STRING &str)
    {
    }
    
  40. Conseguirás unas rosas que conservaran su color y aroma.

12 Trackbacks For This Post
  1. New Flash library « Arduiniana

    [...] Interested to learn more? Read all about it here! [...]

  2. vkick Blog Site » Blog Archive » How to do Timer and Save Settings?

    [...] http://arduiniana.org/libraries/Flash/ Categories: Arduino Posted By: Mon Last Edit: 18 Jun 2009 @ 04 01 PM Email • Permalink Previous  Responses to this post » (None)  Post a Comment Click here to cancel reply. [...]

  3. Arduino net connected clock tells weather not time

    [...] third party libraries were used; PString to handle parsing the incoming website, Flash for memory management, and Streaming for easier coding. [...]

  4. Blog What I Made » YAHMS: Base Station

    [...] interface, see the links below for that too. You’ll also need NewSoftSerial of course and the Flash library which I’ve used to decrease memory usage. Follow the instructions in [...]

  5. Arduino – Steuern per Internet | bastianmueller - blog

    [...] Steckdose (An/Aus) hängt sich der Ardu komplett auf. Ihr benötigt zusätzlich die Bibliothek Flash (für das Speichern im Flash statt SRAM) und FreeMemory (für die Anzeige des freien [...]

  6. Single Machine Sun Tracking / Heliostat Electronics Set Up – CerebralMeltdown.com

    [...] Also, make sure you download and install the flash.h library before trying to upload this program. Here is the link. http://arduiniana.org/libraries/flash/ [...]

  7. Arduino – Steuern per Internet | 3bm. blog.

    [...] Steckdose (An/Aus) hängt sich der Ardu komplett auf. Ihr benötigt zusätzlich die Bibliothek Flash (für das Speichern im Flash statt SRAM) und FreeMemory (für die Anzeige des freien [...]

  8. Blog J.Schweiss | Design Patterns with Arduino

    [...] http://arduiniana.org/libraries/flash/ Tags: Categories: Actions: E-mail | Kick it! | Permalink | Kommentare (0) | Comment RSS Ähnliche BeiträgeAVR Studio and the Arduino core libraryHowTo  Forum and there Arduino-Addin Project Announcing – Arduino Tutorial Refe…Arduino Libs Interactive Arduino BASIC interpreter: – An Interactive Arduino BASIC interpreter that runs on th…Arduino Tipps               http://www.kriwane... Über den Author.Net, Silverlight, Tools & more Search Tagscmdlet-list Filesystem Key NGEN PWM SnapShot SQL SQLServer SP2 Temperature-Measurement Tipps & Tricks USB Thermometer Windows Firewall Archiv2014Februar (13)Januar (30)2013Dezember (44)November (24)Oktober (19)September (36)August (26)Juli (14)Juni (35)Mai (40)April (26)März (19)Februar (29)Januar (27)2012Dezember (35)November (36)Oktober (44)September (45)August (50)Juli (28)Juni (22)Mai (32)April (28)März (18)Februar (11)Januar (39)2011Dezember (41)November (37)Oktober (39)September (74)August (22)Juli (42)Juni (34)Mai (35)April (89)März (92)Februar (42)Januar (34)2010Dezember (13) Weitere SeitenTool ÜbersichtUtilities Blogroll Al NyveldtRazorAnt Software acqui…RazorPDF SamplesTalking MonoTouch at Ph… Download OPML file RecentPostsDesign Patterns with ArduinoC# XML SerializerCOMArduino C++ optional arguments in functionsArduino with TPLink RouterIIS app pools, worker processes, app domainsOpenWRT ForumOpenWRT on Linksys RouterLinioRepRap [...]

  9. Haskins Arduino Fans | Flash | Arduiniana

    [...] Flash | Arduiniana. [...]

  10. Ipfone2 » RELÓGIO ROLANTE COM MATRIZ 5X7 E RTC DS1307

    [...] é que o comando PROGMEM é bem complicado e após pesquisar um pouco encontrei o seguinte link: Library to Ease Accessing Flash-based (PROGMEM) Data com uma biblioteca que facilita muito o uso do [...]

  11. Accessing Arduino Program Memory | WoodUino.ca

    [...] there are libraries of functions (Mikal Hart’s FLASH library, for one) to simplify the use of storing and reading data in the program memory, I like to [...]

  12. Memoria Arduino | Aprendiendo Arduino

    [...] Ver librería Flash que facilita el uso de PROGMEM: http://arduiniana.org/libraries/flash/ [...]

Leave a Reply