Question about the "Flash" library, PROGMEM and how to do something.

Hi all,

I can send a string to the serial port from PROGMEM very easily by doing this:

    FLASH_STRING(menu,
        "\r\n"
        "  Four Valve Independent Controller - Main Menu\r\n"
        "\r\n"
        "  Please select an option\r\n"
        "\r\n"
        "    (1) Run controller\r\n\r\n"
        "    (2) Configure valve timing\r\n\r\n"
        "    (3) Review all valve timings\r\n\r\n"
        "    (4) Change serial baud rate\r\n\r\n"
        "    (5) Display free memory (debug)\r\n\r\n"
        "    (6) View license information\r\n\r\n"
        "    Option: "
    );
    menu.print(Serial);

But, if I want to place a TEMPLATE to use with "sprintf" in PROGMEM (like this):

    char buffer[32];
    FLASH_STRING(template, "You used %d moves to complete the puzzle\r\n");
    sprintf(buffer, template, moves);
    Serial.write(buffer);

...it doesn't work. The "template" object has no generic member with which to access it (that I know of).

Can anyone show me how to do what I want to do (i.e. use a string in PROGMEM as an SPRINTF template)?

Thanks!

-- Roger

A quick Google search for "AVR sprintf progmem" came up with a reference to sprintf_P() which expect the formatting string to be in PROGMEM. You can even format strings from PROGMEM using the %S format specifier instead of %s.

johnwasser: A quick Google search for "AVR sprintf progmem" came up with a reference to sprintf_P() which expect the formatting string to be in PROGMEM. You can even format strings from PROGMEM using the %S format specifier instead of %s.

Neat! Thanks.

I would have Googled it if I knew what to Google! :)

Thanks again!

-- Roger

johnwasser: A quick Google search for "AVR sprintf progmem" came up with a reference to sprintf_P() which expect the formatting string to be in PROGMEM. You can even format strings from PROGMEM using the %S format specifier instead of %s.

OK I've been looking and I still don't get it.

If I do this:

        const char *menu2 PROGMEM =
                "    (3) %s this channel\r\n\r\n"
                "    Option:  ";

is that string in flash memory? If so, then I'm confused as to what the "sprintf_P()" thing is for, since plain old "sprintf" works with "menu2" as a format string.

What I am hoping to do is move all my sprintf formatting strings into flash (PROGMEM) so that as little as possible of SRAM is used.

Can you provide me a little bit more guidance please?

Thanks.

-- Roger

s that string in flash memory? I

Initially it is because that is the only place for code, but it is copied to RAM because you didn't specify that it should stay in program memory.

Krupski:
If I do this:

        const char *menu2 PROGMEM =

"    (3) %s this channel\r\n\r\n"
                "    Option:  ";



is that string in flash memory?

No. The pointer is in FLASH but the string is copied to SRAM. See the reference: http://www.arduino.cc/en/Reference/PROGMEM

Setting up a table (array) of strings in program memory is slightly complicated, but
here is a good template to follow.

Setting up the strings is a two-step process. First define the strings.

#include <avr/pgmspace.h>
prog_char string_0 PROGMEM = “String 0”; // “String 0” etc are strings to store - change to suit.
prog_char string_1 PROGMEM = “String 1”;
prog_char string_2 PROGMEM = “String 2”;
prog_char string_3 PROGMEM = “String 3”;
prog_char string_4 PROGMEM = “String 4”;
prog_char string_5 PROGMEM = “String 5”;

// Then set up a table to refer to your strings.

PROGMEM const char *string_table = // change “string_table” name to suit
{
string_0,
string_1,
string_2,
string_3,
string_4,
string_5 };

Of course if you don’t need a table of your strings you can skip the second part and reference the strings individually.

johnwasser:
Of course if you don’t need a table of your strings you can skip the second part and reference the strings individually.

OK forgive me for being so dense, but is THIS right (i.e. the string is in PROGMEM and stays there)?

// buffer is defined already FYI

        prog_char menu2[] PROGMEM = {
                "    (3) %s this channel\r\n\r\n"
                "    Option:  " 
        };

        sprintf(buffer, menu2, P_enabled[v-1] ? "Disable" : "Enable ");

        Serial.write(buffer);

Is this right?

Krupski: ``` // buffer is defined already FYI

        prog_char menu2[] PROGMEM = {                 "    (3) %s this channel\r\n\r\n"                 "    Option:  "         };

        sprintf(buffer, menu2, P_enabled[v-1] ? "Disable" : "Enable ");

        Serial.write(buffer);



Is this right?

Close. Remember that if the format string is in PROGMEM you have to use sprintf_P(). Other than that it looks correct to me (depending on the declarations of buffer, P_enabled[], v, etc).

johnwasser:
Close. Remember that if the format string is in PROGMEM you have to use sprintf_P(). Other than that it looks correct to me (depending on the declarations of buffer, P_enabled, v, etc).

I know that I’m “supposed” to use sprintf_P() - but the strange thing is that it works WITHOUT it (i.e. using plain old sprintf()).

That’s why I asked if I was doing it correctly. I assumed that it should fail if I use plain sprintf().

– Roger