Use of PROGMEM to store strings in 1.6.5

I had put off upgrading because I had a large project which compiled and was afraid of having to go through the debugging again. Normally, this wouldn’t be a problem, but it is embedded in an animatronic and hence would be difficult to remove to run tests.

However, I am working on another project which required me to upgrade. As I feared, I cannot get the original program even to compile.

I am stuck on the error message

variable ‘MoveCommands’ must be const in order to be put into read-only section by means of ‘attribute((progmem))’

I’ve attached the original file which worked under v 1.5.x, as well as the new version which produces the above error message.

Thanks

pMoveCommands - New.h.txt (4.92 KB)

pMoveCommands.h (4.81 KB)

variable 'MoveCommands' must be const

Is this message so hard to understand? You have a variable called MoveCommands that is not const. It MUST be.

Put the keyword 'const' at the front of the declaration. That tells the compiler that you promise not to try to write into that variable.

I apologize for being so dense, but here is the line where “MoveCommands” is defined:

const char *MoveCommands PROGMEM =

Why is MoveCommands NOT “const” And I believe the keyword “Const” is there…

djsfantasi: I apologize for being so dense, but here is the line where "MoveCommands" is defined:

const char *MoveCommands[] PROGMEM =

Why is MoveCommands NOT "const" And I believe the keyword "Const" is there...

Ah, that means your array contains pointers to const characters. Try making everything const:

const char const * const MoveCommands[] PROGMEM =

Now you have a const array containing const pointers to const characters.

Ahhh! Great...

...although a little too aggressive with the "const" declarations. As you quoted,

const char const * const MoveCommands[] PROGMEM =

That code failed with the error "duplicate 'const'". I kept deleting the added declarations one by one, and the following code compiled:

const char * const MoveCommands[] PROGMEM =

When initially using PROGMEM, I found the syntax a little confusing. But I was able to work through it and was concerned when it didn't compile with 1.6.5.

Thanks John!

johnwasser: Ah, that means your array contains pointers to const characters. Try making everything const:

const char const * const MoveCommands[] PROGMEM =

Now you have a const array containing const pointers to const characters.

That's over-egging the pudding, John.

You have two things there:

  • An array of pointers
  • What they are pointing to

So you only need 2 x const.

This is a bit of an old thread, but I had the same goal: storing strings in PROGMEM, without headache and sore fingers. And yes, I had both.

With a few macros you can simply use literal strings in your source text; they automatically end up in PROGMEM, without bothering you with nasty declarations or having to insert F("") everywhere. Like:

_fprint( “string” ); instead of Serial.print( F(“string”) );
_fprintln( “string” ); instead of Serial.println( F(“string”) );

Pass strings to C-subs, like “This”:

char *p=strstr(my_string,FS(“This”) ); instead of char *p=strstr(my_string,“This”);

“This” is done with this macro:

#define FS(x) PMS( PSTR( x ) )

Where PMS() is a sub copying the PROGMEM string to a (global var) buffer of 100 chars.
NB: each use of FS() causes a string to be copied from progmem to dynamic memory. Better not use that inside a (long) loop.

The complete set of macros is:
_print()
_println()
_fprint()
_fprintln()
_debug_print()
_debug_println()
_debug_fprint()
_debug_fprintln()

Attached sketch is a small demo. It has a define:

#define USE_PROGMEM 1

to use PROGMEM, or not.

Result is memory usage:

#define USE_PROGMEM 0
4096 bytes program, 1532 bytes dynamic, 404 bytes free

#define USE_PROGMEM 1
4580 bytes program, 440 bytes dynamic, 1496 bytes free

(IDE 1.6.9 and an Adafruit Trinket PRO)

Comments are of course welcome!

Progmem_Debug_Print_Demo.ino (8.72 KB)