Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Arduino F() Macro with string arrays

I'm working on an Arduino project that prints a random quote to an LCD screen. There are about a hundred different quotes but including more than about 10 of them overloads the SRAM.

I've looked into it and it seems I need to use either PROGMEM or F() to store the strings in flash memory rather than SRAM but I can't figure out the syntax to store, and then retrieve them. The current program looks something like this (pseudocode to remove irrelevant parts):

String quotes[] = {"quote 1", "quote2", "quote3", ... "quoteN"};
String currentQuote;    

void setup() {
  currentQuote = quotes[0];
}

void loop() {
  if (condition)
      currentQuote = quotes[random(N)];
}

How can I store my string array in flash memory and then retrieve individual elements when needed?

like image 221
Cyborg771 Avatar asked Oct 21 '22 07:10

Cyborg771


1 Answers

Directly from http://arduino.cc/en/Reference/PROGMEM

It is important to use the datatypes outlined in pgmspace.h. 
Some cryptic bugs are generated by using ordinary datatypes for program memory calls.
Below is a list of variable types to use. 
Floating point numbers in program memory do not appear to be supported.

prog_char      - a signed char (1 byte) -127 to 128
prog_uchar     - an unsigned char (1 byte) 0 to 255
prog_int16_t   - a signed int (2 bytes) -32,767 to 32,768
prog_uint16_t  - an unsigned int (2 bytes) 0 to 65,535
prog_int32_t   - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
prog_uint32_t  - an unsigned long (4 bytes) 0 to 4,294,967,295

So you can't use with the type String. I suggest to use another definition for quotes[], something like:

char a[][]={
    "quote1",
    "quote2",
    "...",
    "quoten",

};

By the way, the same page http://arduino.cc/en/Reference/PROGMEM has an example of what you need:

/*
 PROGMEM string demo
 How to store a table of strings in program memory (flash), 
 and retrieve them.

 Information summarized from:
 http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

 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 };

char buffer[30];    // make sure this is large enough for the largest string it must hold

void setup()              
{
  Serial.begin(9600);
}


void loop()           
{
  /* Using the string table in program memory requires the use of special functions to retrieve the data.
     The strcpy_P function copies a string from program space to a string in RAM ("buffer"). 
     Make sure your receiving string in RAM  is large enough to hold whatever
     you are retrieving from program space. */


  for (int i = 0; i < 6; i++)
  {
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.     
    Serial.println( buffer );
    delay( 500 );
  }
}
like image 101
GiulioG Avatar answered Oct 28 '22 20:10

GiulioG