I am following along with this tutorial here .
The following works for me (copied and pasted from tutorial):
const char string_0[] PROGMEM = "String 0";
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";
const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
char buffer[30];
void setup() {
Serial.begin(9600);
}
void loop() {
for (int i = 0; i < 6; i++) {
strcpy_P(buffer, (char *)pgm_read_word(&(string_table[i])));
Serial.println(buffer);
delay(500);
}
}
However, I would like to put the strcpy_P function into it's own function if possible. So something like:
void loop(){
for(int i = 0; i < 6; i++){
printStoredString(string_table[i]);
delay(500);
}
}
void printStoredString(const char* prettySureThisIsWhereIScrewUp){
char buffer[30];
strcpy_P(buffer, (char *)pgm_read_word(&(prettySureThisIsWhereIScrewUp)));
Serial.println(buffer);
}
How can I pass the PROGMEM string into a function for printing?
void printStoredString(const __FlashStringHelper *myProgmemString)
{
// blah
}
Got the following error:
cannot convert 'const char*' to 'const __FlashStringHelper*' for argument '1' to 'void printlnStoredString(const __FlashStringHelper*)
Edit: Changed gears a little bit and followed this tutorial by Nick Gammon .
Code now looks like this:
const char stringTable[6][10] PROGMEM {
{"String 1"},
{"String 2"},
{"String 3"},
{"String 4"},
{"String 5"},
{"String 6"}
};
void printStoredString(const char* str, bool newLine = false){
char c;
if(!str){ return; }
while((c = pgm_read_byte(str++))){ Serial.print(c); }
if(newLine){ Serial.println(); }
}
void loop(){
for(int i = 0; i < 6; i++){
printStoredString(stringTable[i], true);
}
}
Seems to be working just fine, and uses fewer lines of code, but would have less memory savings if my string sizes varied greatly.
Your array of string pointers is in PROGMEM but you are passing garbage fetched from RAM. You can pass the string pointer but only if you fetch it from PROGMEM:
printStoredString((char *)pgm_read_word(&(string_table[i])));
Or pass the PROGMEM address of the string pointer:
printStoredString(&(string_table[i]));
and fetch the pointer from PROGMEM in the function:
void printStoredString(const char * progmem_ptr) {
char buffer[30];
strcpy_P(buffer, (char *)pgm_read_word(progmem_ptr));
Serial.println(buffer);
}
Or, since Serial knows how to fetch the text directly from PROGMEM:
void printStoredString(const char * progmem_ptr) {
const char * string_ptr = (char *) pgm_read_word(progmem_ptr);
Serial.println((__FlashStringHelper *) string_ptr);
}
Or you could move the array indexing into your printStoredString() function:
void printStoredString(const int index) {
char buffer[30];
strcpy_P(buffer, (char *)pgm_read_word(&(string_table[index])));
Serial.println(buffer);
}
Or the equivalent without the strcpy_P:
void printStoredString(const int index) {
const char * string_ptr = (char *)pgm_read_word(&(string_table[index])));
Serial.println((__FlashStringHelper *) string_ptr);
}
If the strings are global, why do you need to pass them to a function?
Because they are in PROGMEM (FLASH) they have to be treated specially. You can't pass a PROGMEM address to a function that is not specifically written to expect a PROGMEM address. Adding a layer to copy the PROGMEM string into a RAM buffer allows you to pass PROGMEM strings to functions that expect RAM strings.
Having a pointer to a PROGMEM string in a table that is also in PROGMEM adds yet another layer of complexity.
Very clear answer, thank you
For some reason I only had user defined functions in mind.
system
Closed
October 3, 2022, 3:55pm
9
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.