arry in PROGMEM

I want to use large size array's for animating leds.
It works fine when the array is not to large, and not using progmem.
But when I put the same small array (as a test) in progmem, the readings out of the array are completly wrong (serial printed the results for this test).
nothing like those numbers in the array like -22874.
It almost looks like it's ready some random data, sometimes with patern like results.
Ones it was reading a completly diferent array somehow.

The only code I added to put the array into PROGMEM are...

#include <avr/pgmspace.h>

and put PROGMEM in the array code like this...

int lightningbrightnessArray[117] PROGMEM ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 93, 131, 110, 75, 58, 24, 14, 154, 124, 112, 36, 71, 41, 16, 24, 25, 10, 10, 5, 4, 2, 2, 1, 1, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 34, 30, 46, 25, 23, 10, 7, 5, 4, 4, 3, 1, 1, 0, 28, 11, 6, 3, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

When I remove "PROGMEM" it works fine, but can't get longer array's into ram.

What can be the problem here? Why are the results not the same?

Do you have read this?

// save some unsigned ints
PROGMEM  prog_uint16_t charSet[]  = { 65000, 32796, 16843, 10, 11234};

unsigned int displayInt;
int k;    // counter variable

// read back a 2-byte int
 displayInt = pgm_read_word_near(charSet + k)

p.s. when I create an array I don't specific the size between the square, leave the calculations to the compiler :wink: I think it is much safer (in your case it is easy to go wrong with 117 items ;))

You have to use the right data type eg

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

If your using led's you might only need 255 levels so you could also use prog_uint8_t. this would save space.
Depending on what your doing you might want to copy whole chunks of PROGMEM into a array in RAM this can be done like this.

memcpy_P (RAM_BLOCK,(uint8_t*)pgm_read_word(&PROGMEM_BLOCK), sizeof(RAM_BLOCK));

This is memory intensive so you can also read them out individually as in the arduino examples.

You might already know this i don't know but hope it's a help.

int lightningbrightnessArray[117] PROGMEM ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 93, 131, 110, 75, 58, 24, 14, 154, 124, 112, 36, 71, 41, 16, 24, 25, 10, 10, 5, 4, 2, 2, 1, 1, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 34, 30, 46, 25, 23, 10, 7, 5, 4, 4, 3, 1, 1, 0, 28, 11, 6, 3, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

The variable name implies that these values will be used in a call to analogWrite() to set the intensity of the LED. If that is the case, the values are restricted to the range 0 to 255, which is the size of a byte, which is half the size of an int, which means that you are wasting half the space you have allocated.

Perhaps PROGMEM isn't even necessary...

I tried something, but it isn't working yet. I'am only a beginner in Arduino.
This is what I have tried...

This is how I made the array (it really has 1441 values, but I did not paste that here to keep it clear).

PROGMEM  prog_uchar lightningbrightnessArray[1441]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xxxxxxxxxxxx};

This is how I made the test, it serial prints the values from the array.
"array_counter" counts in a loop from 1 to 1441.

Serial.println (pgm_read_word_near(lightningbrightnessArray + (array_counter)));

I still get wrong values back with this serial print.
I think I am doing the reading part wrong here. I can't use the examples, don't know enough about it.

Should that be like this maybe.

Serial.println (pgm_read_byte(&lightningbrightnessArray + (array_counter)));

it's a bit of a guess it might not work.

prog_uchar is a 1 byte datatype.

pgm_read_word_near returns a word, which in AVR land is two bytes.

So ya, your values aren't going to be right.

And for future reference, you'll get the best feedback by providing complete working code, not single line snippets. If the sketch is too large to post, then just attach it as a separate file. If it's really large, then spend at least some time reducing it to the smallest piece of complete code that produces the problem.

This is a test code for the array...

#include <avr/pgmspace.h>

PROGMEM  prog_uchar lightningbrightnessArray[10]  = {0, 5, 20, 60, 120, 255, 0, 255, 0, 255};
int array_counter = 0;


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


void loop (){
  if (array_counter == 10)  {
          array_counter = 0;
        }  
        else  {
          array_counter = array_counter + 1;
        }
        
  Serial.println (pgm_read_byte(&lightningbrightnessArray + (array_counter)));
  delay (200);
}

On my serial monitor I now get these readings...

?
Þ
ê
ª
±
á
"
Ñ
£


So not working yet.

Try changing this line:

Serial.println (pgm_read_byte(&lightningbrightnessArray + (array_counter)));

to this

Serial.println ( (unsigned int) pgm_read_byte(&lightningbrightnessArray + (array_counter)));

The 'unsigned int' is telling the function this is a number, not a character, which appears to be what you are outputting there.

It still doesn't work, but I do get a patern of 10 numbers, only the wrong ones...

My serial print...

147
222
234
170
177
225
34
209
163
144
0
147
222
234
170
177
225
34
209
163
144
0

I got it working, but now I'am using prog_int16_t, these are 2bytes.
I already implemented this in my flashlight led animation, an array of 1441, and it works perfectly.
But I only need numbers between 0 and 255.
Anyone knows how to save them as 1 byte to save space?

This is my working 2 byte code...

#include <avr/pgmspace.h>

prog_int16_t lightningbrightnessArray[10] PROGMEM = {0, 5, 20, 60, 120, 255, 0, 255, 0, 255};
int array_counter = 0;


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


void loop (){
  if (array_counter == 10)  {
          array_counter = 0;
        }  
        else  {
          array_counter = array_counter + 1;
        }

Serial.println (pgm_read_word_near(lightningbrightnessArray + array_counter));


  delay (200);
}
 if (array_counter == 10)  {
          array_counter = 0;
        }  
        else  {
          array_counter = array_counter + 1;
        }

Any good reason not to use a "for" loop?

pgm_read_byte_near

If your using led's you might only need 255 levels so you could also use prog_uint8_t. this would save space.
Depending on what your doing you might want to copy whole chunks of PROGMEM into a array in RAM this can be done like this

My earlier post had the info in it. Use the prog_uint8_t type this is a of one byte from 0 to 255. This type isn't in the arduino documentation but i think it is in the avr doc. I picked it up from other threads my self i think it's a generic data type that might be used in other things as well, there is a few more but there not much use really. Anyway it works.

EVP:
You have to use the right data type eg

prog_char

From what I can see, prog_char and friends are nothing more than a typedef of the base type with the PROGMEM added in:

typedef char prog_char PROGMEM;

It is slightly handy because I gather that you would have to put typedef char PROGMEM prog_char instead, according to some compiler option I do not follow. But declarations like this are equally valid:

char foobar[] PROGMEM = { 'f', 'o', 'o'... };

I didn't know that , i was puting both..Duuu..:slight_smile: