Moving an array of structs to PROGMEM?

Hi, I have the following struct:

struct ScaleStruct
{
    String Name;
    uint8_t size;
    uint8_t width1;         //Without Fitting the scale
    uint8_t width2;         //fitting the scale
    uint16_t ScaleMapping;
};

I have 12 instances of this struct declared on my sketch:

ScaleStruct Scale[12];

The thing is that all the data stored inside the structs are Constants, and I want to know if it it posible to move them to the Program Memory, and if so, how do I do it??

This is an example of how I fill the data of the structs:

  uint8_t KeyCount = 55; // BUTTONS - 1
    
  Scale[0].Name = F("Chromatic");
  Scale[0].size = 12;
  Scale[0].width1 = KeyCount;
  Scale[0].width2 = KeyCount;
  Scale[0].ScaleMapping = 0b0000111111111111;
  
  Scale[1].Name = F("Major");
  Scale[1].size = 7;
  Scale[1].width1 = KeyCount + 40;             
  Scale[1].width2 = KeyCount + 29;
  Scale[1].ScaleMapping = 0b1000010110101011;
  
  Scale[2].Name = F("Natural Minor");
  Scale[2].size = 7;
  Scale[2].width1 = KeyCount + 40;
  Scale[2].width2 = KeyCount + 29;
  Scale[2].ScaleMapping = 0b1000011010110101;

The data never changes in the code

Thanks! :slight_smile:

I solved it.

For anyone wanting to know, this is what I did.

I changed:

ScaleStruct Scale[12];

to :

const ScaleStruct Scale[12] PROGMEM = 
{
  {"Chromatic", 12, 55, 55, 0b0000111111111111},
  {},
  {},
  {},
  {},
  {},
  {},
  {},
  {},
  {},
  {},
  {},  
};

All the data is loaded when declared, and for Example, I can just call Scale[ x ].Name, right?

I'm a bit confused.

it’s a bit convoluted and you need to know what is the format of the data stored

here is an example

#include <avr/pgmspace.h>

enum situation_t : uint8_t {single, couple, RIP};

// this is the standard approach for Arrays of strings as documented in https://www.arduino.cc/en/Reference/PROGMEM
const char s0[] PROGMEM = "single";
const char s1[] PROGMEM = "couple";
const char s2[] PROGMEM = "rest in peace";

const char* const descriptionSituation[] PROGMEM = {s0, s1, s2};

// Now if you want your own structure and have some strings as well in the structure
struct myStructure {
  const char * firstName;
  const uint8_t d;
  const uint8_t m;
  const uint16_t y;
  situation_t situation;
};

//the strings are char array, you define them first somewhere in flash memory
const char auguste[] PROGMEM = "Auguste";
const char camille[] PROGMEM = "Camille";
const char victor[] PROGMEM = "Victor";
const char juliette[] PROGMEM = "Juliette";
const char cheche_romo[] PROGMEM = "Cheche Romo";

// and then use the reference for your table definition
const myStructure population[] PROGMEM =
{
  {auguste, 12, 11, 1840, RIP}, // the structure holds a pointer in memory for the first name
  {camille, 8, 12, 1864, RIP},
  {victor, 26, 2, 1802, RIP},
  {juliette, 10, 4, 1806, RIP},
  {cheche_romo, 1, 1, 2000, single}
};

const uint16_t nbElements = sizeof(population) / sizeof(population[0]);

void setup() {
  char buffer[30]; // needs to be large enough

  Serial.begin(115200);
  for (int i = 0; i < nbElements; i++)
  {
    Serial.print(F("------------  ")); Serial.print(i); Serial.println(F("  ------------"));
    strcpy_P(buffer, (char*)pgm_read_word(&(population[i].firstName)));
    Serial.println( buffer );

    Serial.print( (uint8_t) pgm_read_byte_near(&(population[i].d)) ); Serial.print("/");
    Serial.print( (uint8_t) pgm_read_byte_near(&(population[i].m)) ); Serial.print("/");
    Serial.println( (uint16_t) pgm_read_word_near(&(population[i].y)) );

    strcpy_P(buffer, (char*)pgm_read_word(&(descriptionSituation[(uint8_t) pgm_read_byte_near(&(population[i].situation))])));
    Serial.println( buffer );
  }
  Serial.println(F("------------------------------"));
}

void loop() {}

Great!, got it working now, thanks! =)

cool :slight_smile:

have a look at my example in #2

J-M-L:
have a look at my example in #2

My bad, thanks btw =)

no problem :slight_smile: