PROGMEM v. F()

Reading the docs, I see a detailed discussion of PROGMEM for keeping strings in memory.

http://playground.arduino.cc/Learning/Memory

At the bottom of that page, there's a short reference to F(), but there's no description, nor is there any explanation if the F() syntax takes place of PROGMEM, or how the two are related.

I have a fair number of strings I need to manipulate, mostly sprintf format strings for display on an LCD.

Which format should I be using?

If they're in PROGMEM, some forms of manipulation may be impossible.
Yes, the F macro puts strings in PROGMEM.

I have a fair number of strings I need to manipulate, mostly sprintf format strings for display on an LCD.

Which format should I be using?

Neither one. PROGMEM, and the magic behind F() uses PROGMEM, is read-only. You can't write to strings in PROGMEM at run time.

To clarify:

I'm doing a lot of sprintf like this

sprintf(buffer, "some %format or other",var, var, ....);

I'm interested in keeping the "some %format or other" out of RAM. I can reuse the buffer, it's the format strings that take a lot of bytes.

So

sprintf(buffer, F("some %format or other"), var, var, ....);

should do the trick?

I can reuse the buffer, it's the format strings that take a lot of bytes.

Perhaps you need to reconsider what you are doing, then, to reduce the size of the format strings.

Well, I have 6 screens of 4 lines, each line is about 16 characters. I don't have much way to reduce that; I need those screens to get the functionality I must have.

So that's 6416 = 384 bytes, of my 2K ram. Worse, some of those strings repeat in different parts of the code. I could do fancy stuff with pointers, but if I can leave them in flash and use them from there, that gives me that much more room for stuff I actually need to manipulate.

The use of the F() macro requires that the function support it. Serial.print() has an overloaded method that accepts a value of the type generated by the F() macro. The sprintf() function does not.

The sprintf() function requires a pointer to a format string. It does NOT require a format string. You could put the format strings in PROGMEM (not using F()), and fetch them into SRAM just before use, so only one was in SRAM at a time.

Of course, without seeing your code, this is all just theoretical.

Thanks for the clarification. It looks like PROGMEM and pointers is it.

Right now my code is supremely ugly. I wrote it without taking into consideration the limited RAM, so I'm in the midst of a huge re-write, off-loading a bunch of processing to slave arduinos and such.

Maybe when I get it all cleaned up I'll post back with some specific snippets.

I'm in the midst of a huge re-write, off-loading a bunch of processing to slave arduinos and such

Sounds complex - would using an arduino with more RAM help instead?

Not really. It's a master-slave network that communicates via an RS485 bus. Each slave has some sensors attached. My original thought was to have the slaves just report the raw readings and have the master process all the information. But that would require the master keep up to 16 copies of all the data collected by the slaves.

Rather than that, I will have the slaves process all the data and then report the processed data to the master. This will free the master to just send data requests to the slaves and display the result. It's an interesting project.

cptdondo:
Not really. It's a master-slave network that communicates via an RS485 bus. Each slave has some sensors attached. My original thought was to have the slaves just report the raw readings and have the master process all the information. But that would require the master keep up to 16 copies of all the data collected by the slaves.

Rather than that, I will have the slaves process all the data and then report the processed data to the master. This will free the master to just send data requests to the slaves and display the result. It's an interesting project.

That actually sounds very similar to how most of our rack DAQ (Data AcQuisition) systems work here at Bartol. But because it is all within the same 19" rack, we can get away with simple UART communication and address each board similar to how SPI addresses multiple devices. Each slave board processes their own sensors and/or commands (some boards just take sensor data, others control mechanical things, and others do both). The "Readout board" (yeah, that's what we call it) collects all the data and then massages it for what ever communications we need with the outside world. That can be an attached computer for some of our ground-based systems, or radio/satellite communications for our balloon based systems. The modular approach makes us able to customize a DAQ system for an experiment with mostly standard boards (possibly with custom firmware) with only a couple custom boards.

PaulS:
Serial.print() has an overloaded method that accepts a value of the type generated by the F() macro. The sprintf() function does not.

Thus sprintf_P(). Something like:

char buf[20];
sprintf_P(buf, PSTR("%d %02x"), a, b);

No problemo. sprintf_P() is in stdio.h, if your building outside your main sketch.