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
234 Responses → “Flash”

  1. Mikal

    10 months ago

    @Karl,

    Thanks. Next rev will definitely have this.


  2. Mikal

    10 months 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 months 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 months 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 months ago

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


  6. dimitryous

    10 months 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 months 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

    9 months 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

    9 months 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

    9 months ago

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

    Will


  11. charles

    9 months ago

    is the library working with arduino due ?

    thanks charles


  12. Mikal

    9 months 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

    8 months 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

    8 months ago

    @Haulier,

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


  15. The Raven

    7 months 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

    6 months 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

    5 months 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

    5 months 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

    4 months 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

    4 months 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

    3 months 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

    3 months 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

    2 weeks 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

    1 week ago

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

10 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 [...]

Leave a Reply