HELP in PROGMEM

I couldn't find any solution on the web. I was wondering how to change the data inside a progmem.

#include "Arduino.h"
#include <avr/pgmspace.h>
//#include "world.h"
//#include "troll.h"
//#include "uewar.h"

#define SpinInterrupt 0
#define SpinInput 2


//Define cols/rows to ports
//column +
#define col0 3
#define col1 4
#define col2 5
#define col3 6
#define col4 7
#define col5 8
#define col6 9
#define col7 10
#define col8 11
 
//row -
#define row0 12
#define row1 13
#define row2 14
#define row3 15
#define row4 16
#define row5 17
#define row6 18
#define row7 19
 

 
#define LEDOrientation false
 
 
const int ImageColumns=131;
int ImageRows=72;
const int LEDEights=9;

 
#define ImageColumns 131
#define ImageRows 72
#define LEDEights 9
 
 
prog_uint8_t Image[ImageColumns][LEDEights] PROGMEM = {
  { 
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10110111, B10111001, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
}; 

 
volatile unsigned long microsPerPixelColumn = 10000;
volatile unsigned long microsPerPixelEight = 0;
volatile unsigned long lastSpinTime = 0;
volatile int column = 0;
volatile int row = 0;
volatile int LEDEight = 0;
volatile int CurrentColumns = 0;
 
unsigned long inturruptDebounce = 80;
bool bStop;
int eightpins[9] = {col0, col1, col2, col3, col4, col5, col6, col7, col8};
 
int pins[72][2] = {{col0, row0},
                   {col0, row1},
                   {col0, row2},
                   {col0, row3},
                   {col0, row4},
                   {col0, row5},
                   {col0, row6},
                   {col0, row7},
 
                   {col1, row0},
                   {col1, row1},
                   {col1, row2},
                   {col1, row3},
                   {col1, row4},
                   {col1, row5},
                   {col1, row6},
                   {col1, row7},
 
                   {col2, row0},
                   {col2, row1},
                   {col2, row2},
                   {col2, row3},
                   {col2, row4},
                   {col2, row5},
                   {col2, row6},
                   {col2, row7},
 
                   {col3, row0},
                   {col3, row1},
                   {col3, row2},
                   {col3, row3},
                   {col3, row4},
                   {col3, row5},
                   {col3, row6},
                   {col3, row7},
 
                   {col4, row0},
                   {col4, row1},
                   {col4, row2},
                   {col4, row3},
                   {col4, row4},
                   {col4, row5},
                   {col4, row6},
                   {col4, row7},
 
                   {col5, row0},
                   {col5, row1},
                   {col5, row2},
                   {col5, row3},
                   {col5, row4},
                   {col5, row5},
                   {col5, row6},
                   {col5, row7},
 
                   {col6, row0},
                   {col6, row1},
                   {col6, row2},
                   {col6, row3},
                   {col6, row4},
                   {col6, row5},
                   {col6, row6},
                   {col6, row7},
 
                   {col7, row0},
                   {col7, row1},
                   {col7, row2},
                   {col7, row3},
                   {col7, row4},
                   {col7, row5},
                   {col7, row6},
                   {col7, row7},
 
                   {col8, row0},
                   {col8, row1},
                   {col8, row2},
                   {col8, row3},
                   {col8, row4},
                   {col8, row5},
                   {col8, row6},
                   {col8, row7}
                  };
                  
                  
const char s[2] = "~"; //for cutting;
String inData;
char inData2[100]; // Allocate some space for the string
 

char *token;
char *token2;
char *token3;
char x1[100];
char x2[100] = " This is ACRLDS v2.0 :)  ";
char x3[100];
 
String tryData = "";
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
 // sensor setup

 
void setup() 
{
  pinMode(SpinInput, INPUT); //Reed switch
 
  pinMode(col0, OUTPUT);
  pinMode(col1, OUTPUT);
  pinMode(col2, OUTPUT);
  pinMode(col3, OUTPUT);
  pinMode(col4, OUTPUT);
  pinMode(col5, OUTPUT);
  pinMode(col6, OUTPUT);
  pinMode(col7, OUTPUT);
  pinMode(col8, OUTPUT);
 
  pinMode(row0, OUTPUT);
  pinMode(row1, OUTPUT);
  pinMode(row2, OUTPUT);
  pinMode(row3, OUTPUT);
  pinMode(row4, OUTPUT);
  pinMode(row5, OUTPUT);
  pinMode(row6, OUTPUT);
  pinMode(row7, OUTPUT);
 
  CurrentColumns = ImageColumns;
  lastSpinTime = micros();
 
  Clear();
 
  for(int j = 0; j < ImageRows; j++)
  {
    Clear();
    
    digitalWrite(pins[j][0], !LEDOrientation);
    digitalWrite(pins[j][1], LEDOrientation);
    delay(30);
  }
  attachInterrupt(SpinInterrupt, spinInterrupt, FALLING);
}
 
bool inInterrupt = false;
unsigned long spinTime = 0;
void spinInterrupt()
{
  if(lastSpinTime == 0)
  {
    lastSpinTime = micros();
    return;
  }
 
  if(!inInterrupt && micros() - lastSpinTime > inturruptDebounce)
  {
    inInterrupt = true;
    unsigned long newSpinTime = micros() - lastSpinTime;
    if(spinTime != 0 && (newSpinTime > spinTime*2 || newSpinTime < spinTime/2))
    {
      inInterrupt = false;
      return;
    }
    spinTime = newSpinTime;
 
    microsPerPixelColumn = spinTime / CurrentColumns;
    microsPerPixelEight = microsPerPixelColumn / LEDEights;
    lastSpinTime = micros();
    inInterrupt = false;
 
}
 
void loop()
{
  
    if(Comp("globe~")==0){
      
      /************************I WANT TO INSERT THE NEW VALUE OF PROGMEM HERE:******************/
 
prog_uint8_t Image[ImageColumns][LEDEights] PROGMEM = {
  { 
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10110111, B10111001, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  
};
}

}
  
  for(column = 0; column < CurrentColumns; column++)
  {
    for(LEDEight = 0; LEDEight < LEDEights ; LEDEight++)
    {
      DrawLEDGroupsAtOnce(LEDEight, column);
    }
  }
}


 
 
 
char Comp(char* This) {
 
while(Serial.available()) {
      inChar = Serial.read();
      inData.concat(inChar);
  }
  
  strcpy(inData2, inData.c_str());
   token = strtok(inData2, s);
            strcpy(x1,token);

                token = strtok(NULL, s);
              strcpy(x2,token);

                  token = strtok(NULL, s);
                  strcpy(x3,token);

if (strcmp(x3,This)  == 0) {

Serial.println(x1);
Serial.println(x2);
Serial.println(x3);

   inData = "";
   inChar = '\0';
    return(0);
}
else {
    return(1);
}

} 
 

void DrawLEDGroupsAtOnce(int eight, int column)
{
  prog_uint8_t imageEights = pgm_read_byte(&(Image[column][eight]));
 
  PORTB = (PORTB | B00110000) & ((imageEights << 4) | B11001111);
  PORTC = (PORTC | B00111111) & ((imageEights >> 2) | B11000000);
 
  digitalWrite(eightpins[eight], !LEDOrientation);
 
  if (microsPerPixelEight > 20)
  delayMicroseconds(microsPerPixelEight - 17);
 
  digitalWrite(eightpins[eight], LEDOrientation);
}
 
void Clear()
{
  for(int j = 0; j < ImageRows; j++)
  {
    digitalWrite(pins[j][0], LEDOrientation);
    digitalWrite(pins[j][1], !LEDOrientation);
  }
}

here is the error:

sketch_feb18b.ino: In function 'void spinInterrupt()':
sketch_feb18b:511: error: a function-definition is not allowed here before '{' token
sketch_feb18b:851: error: expected `}' at end of input

PS: I've cutted some portions of the data inside the progmem because the forum gives me an error. 9500 is the max chars.

(deleted)

I think the problem is here:

} // this closes out void setup

bool inInterrupt = false;
unsigned long spinTime = 0;
void spinInterrupt() // this is the start of a function
{

The 2 lines after setup ends are just hanging out - not part of anything.
Move them into a function, or put them before setup so they are global variables.

spycatcher2k:
PROGMEM is stored in the Flash - You cant change it in your code, Sorry.

My project is a POV sir (with text and image) controlled by an android app., the data is stored in that progmem. The whole project is now working. the text's color and its string can now be changed using the android phone, but I still need to change the image.
I really need to change the image. Is there any way that I could do just to change the image code? :frowning:

CrossRoads:
I think the problem is here:

} // this closes out void setup

bool inInterrupt = false;
unsigned long spinTime = 0;
void spinInterrupt() // this is the start of a function
{

The 2 lines after setup ends are just hanging out - not part of anything.
Move them into a function, or put them before setup so they are global variables.

thanks sir, I know that would just clean my code, but it doesn't solve my problem.

I really need to change the image. Is there any way that I could do just to change the image code?

Only if you move it into SRAM and drop the PROGMEM macro from the declaration. PROGMEM by definition is immutable once the application starts. If you leave it in PROGMEM you need to recompile the image to change it.

tripphippie:

I really need to change the image. Is there any way that I could do just to change the image code?

Only if you move it into SRAM and drop the PROGMEM macro from the declaration. PROGMEM by definition is immutable once the application starts. If you leave it in PROGMEM you need to recompile the image to change it.

can you show me how to use the SRAM?
I'll try my luck to use the flash rather. I'll edit the code, but I still want to know how to move to SRAM instead of using the progmem.

OK. UPDATE:
I've changed the declaration of IMAGE [x][y] progmem into this:

const int Image[ImageColumns][LEDEights] = {
};

NOW, I tried to VERIFY the whole code and it was verified. I have to wait for 6 hours to go to my school and try to upload the code to my project.
I hope it works!

I have one very important question, though:

  1. I can't fully say that the whole code will work, because of this: (I know this has something to do with AVR-GCC bla bla bla progmem, right? I've read about it a while ago just for a minute.).
  prog_uint8_t imageEights = pgm_read_byte(&(Image[column][eight]));

This code is in the method name: void DrawLEDGroupsAtOnce(int eight, int column)

ANSWER PLEASE

prog_uint8_t imageEights = pgm_read_byte(&(Image[column][eight]));

This code is not going to work properly. You will most likely be reading random garbage into imageEights. pgm_read_byte is for fetching data from PROGMEM into SRAM. When you dropped the PROGMEM attribute you told the compiler to place Image into SRAM. Since it is already there you don't need to load it.
I highly recommend you read Arduino Playground - Memory and PROGMEM - Arduino Reference

tripphippie:

prog_uint8_t imageEights = pgm_read_byte(&(Image[column][eight]));

This code is not going to work properly. You will most likely be reading random garbage into imageEights. pgm_read_byte is for fetching data from PROGMEM into SRAM. When you dropped the PROGMEM attribute you told the compiler to place Image into SRAM. Since it is already there you don't need to load it.
I highly recommend you read Arduino Playground - HomePage and PROGMEM - Arduino Reference

hi sir, I hope you won't go offline yet. pls pls pls. I'm reading already these two urls.
Can you share to me directly how to read bytes from SRAM/FLASH? I was searching on google about: "HOW TO READ BYTES" or pgm_read_byte alternative. ahaha.

I'm really tired because of this project. 1:17 AM here. Need to go to school at 6AM :smiley:

You don't have to do anything special to read from SRAM. That is the default. Normal variable are always read and written into SRAM. The special pgm_read_* functions are for explicitly reading from flash which is not a normal memory operation.

change this

prog_uint8_t imageEights = pgm_read_byte(&(Image[column][eight]));

into this

byte imageEights = Image[column][eight];

That should work. You should really try to understand WHY it works though. Read Harvard architecture - Wikipedia
It should be able to explain why PROGMEM exists in the first place.
Most processors are Von-Neumann architecture while the Atmega are all Harvard architecture.

The best use for PROGMEM is for large static pieces of data that only need access at any time to a subset of that data. Example: I use it for a chiptune library where I store songs in PROGMEM and then load them into a buffer that I reuse in SRAM for actually playing them back. I only have enough SRAM to load one song at a time so I store them in PROGMEM where I have more space. To make this work I use pgm_read_byte() to get the data out for the song. I hope that clarifies this whole PROGMEM thing and why or why not you would use it.

hello sir! After many weeks, I can now say that my latest code [no progmem] doesn't work. >.<. when I'm trying to run my POV, the leds are constantly turning on.

#include "Arduino.h"
#include <avr/pgmspace.h>
#define SpinInterrupt 0
#define SpinInput 2


//Define cols/rows to ports
//column +
#define col0 3
#define col1 4
#define col2 5
#define col3 6
#define col4 7
#define col5 8
#define col6 9
#define col7 10
#define col8 11
 
//row -
#define row0 12
#define row1 13
#define row2 14
#define row3 15
#define row4 16
#define row5 17
#define row6 18
#define row7 19
 
 
const int ImageColumns = 131;
int ImageRows = 72;
const int LEDEights = 9; 

const int Image[ImageColumns][LEDEights] ={
   { 
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10110111, B10111001, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10000111, B10111000, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  

  , {
    B11111111, B10011111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10011111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
};


 
#define LEDOrientation false
 
volatile unsigned long microsPerPixelColumn = 10000;
volatile unsigned long microsPerPixelEight = 0;
volatile unsigned long lastSpinTime = 0;
volatile int column = 0;
volatile int row = 0;
volatile int LEDEight = 0;
volatile int CurrentColumns = 0;
 
unsigned long inturruptDebounce = 80;
bool bStop;
int eightpins[9] = {col0, col1, col2, col3, col4, col5, col6, col7, col8};
 
int pins[72][2] = {{col0, row0},
                   {col0, row1},
                   {col0, row2},
                   {col0, row3},
                   {col0, row4},
                   {col0, row5},
                   {col0, row6},
                   {col0, row7},
 
                   {col1, row0},
                   {col1, row1},
                   {col1, row2},
                   {col1, row3},
                   {col1, row4},
                   {col1, row5},
                   {col1, row6},
                   {col1, row7},
 
                   {col2, row0},
                   {col2, row1},
                   {col2, row2},
                   {col2, row3},
                   {col2, row4},
                   {col2, row5},
                   {col2, row6},
                   {col2, row7},
 
                   {col3, row0},
                   {col3, row1},
                   {col3, row2},
                   {col3, row3},
                   {col3, row4},
                   {col3, row5},
                   {col3, row6},
                   {col3, row7},
 
                   {col4, row0},
                   {col4, row1},
                   {col4, row2},
                   {col4, row3},
                   {col4, row4},
                   {col4, row5},
                   {col4, row6},
                   {col4, row7},
 
                   {col5, row0},
                   {col5, row1},
                   {col5, row2},
                   {col5, row3},
                   {col5, row4},
                   {col5, row5},
                   {col5, row6},
                   {col5, row7},
 
                   {col6, row0},
                   {col6, row1},
                   {col6, row2},
                   {col6, row3},
                   {col6, row4},
                   {col6, row5},
                   {col6, row6},
                   {col6, row7},
 
                   {col7, row0},
                   {col7, row1},
                   {col7, row2},
                   {col7, row3},
                   {col7, row4},
                   {col7, row5},
                   {col7, row6},
                   {col7, row7},
 
                   {col8, row0},
                   {col8, row1},
                   {col8, row2},
                   {col8, row3},
                   {col8, row4},
                   {col8, row5},
                   {col8, row6},
                   {col8, row7}
                  };
                  
                  
const char s[2] = "~"; //for cutting;
String inData;
char inData2[100]; // Allocate some space for the string
 

char *token;
char *token2;
char *token3;
char x1[100];
char x2[100] = " This is ACRLDS v2.0 :)  ";
char x3[100];
 
String tryData = "";
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
 // sensor setup

 
void setup() 
{
  pinMode(SpinInput, INPUT); //Reed switch
 
  pinMode(col0, OUTPUT);
  pinMode(col1, OUTPUT);
  pinMode(col2, OUTPUT);
  pinMode(col3, OUTPUT);
  pinMode(col4, OUTPUT);
  pinMode(col5, OUTPUT);
  pinMode(col6, OUTPUT);
  pinMode(col7, OUTPUT);
  pinMode(col8, OUTPUT);
 
  pinMode(row0, OUTPUT);
  pinMode(row1, OUTPUT);
  pinMode(row2, OUTPUT);
  pinMode(row3, OUTPUT);
  pinMode(row4, OUTPUT);
  pinMode(row5, OUTPUT);
  pinMode(row6, OUTPUT);
  pinMode(row7, OUTPUT);
 
  CurrentColumns = ImageColumns;
  lastSpinTime = micros();
 
  Clear();
 
  for(int j = 0; j < ImageRows; j++)
  {
    Clear();
    
    digitalWrite(pins[j][0], !LEDOrientation);
    digitalWrite(pins[j][1], LEDOrientation);
    delay(30);
  }
  attachInterrupt(SpinInterrupt, spinInterrupt, FALLING);
}
 
bool inInterrupt = false;
unsigned long spinTime = 0;
void spinInterrupt()
{
  if(lastSpinTime == 0)
  {
    lastSpinTime = micros();
    return;
  }
 
  if(!inInterrupt && micros() - lastSpinTime > inturruptDebounce)
  {
    inInterrupt = true;
    unsigned long newSpinTime = micros() - lastSpinTime;
    if(spinTime != 0 && (newSpinTime > spinTime*2 || newSpinTime < spinTime/2))
    {
      inInterrupt = false;
      return;
    }
    spinTime = newSpinTime;
 
    microsPerPixelColumn = spinTime / CurrentColumns;
    microsPerPixelEight = microsPerPixelColumn / LEDEights;
    lastSpinTime = micros();
    inInterrupt = false;
  }
}
 
void loop()
{
  
     
  
  for(column = 0; column < CurrentColumns; column++)
  {
    for(LEDEight = 0; LEDEight < LEDEights ; LEDEight++)
    {
      DrawLEDGroupsAtOnce(LEDEight, column);
    }
  }
}

 
 
 
char Comp(char* This) {
 
while(Serial.available()) {
      inChar = Serial.read();
      inData.concat(inChar);
  }
  
  strcpy(inData2, inData.c_str());
   token = strtok(inData2, s);
            strcpy(x1,token);

                token = strtok(NULL, s);
              strcpy(x2,token);

                  token = strtok(NULL, s);
                  strcpy(x3,token);

if (strcmp(x1,This)  == 0) {

Serial.println(x1);
Serial.println(x2);
Serial.println(x3);

   inData = "";
   inChar = '\0';
    return(0);
}
else {
    return(1);
}

} 
 

void DrawLEDGroupsAtOnce(int eight, int column)
{
  byte imageEights = Image[column][eight];
 
  PORTB = (PORTB | B00110000) & ((imageEights << 4) | B11001111);
  PORTC = (PORTC | B00111111) & ((imageEights >> 2) | B11000000);
 
  digitalWrite(eightpins[eight], !LEDOrientation);
 
  if (microsPerPixelEight > 20)
  delayMicroseconds(microsPerPixelEight - 17);
 
  digitalWrite(eightpins[eight], LEDOrientation);
}
 
void Clear()
{
  for(int j = 0; j < ImageRows; j++)
  {
    digitalWrite(pins[j][0], LEDOrientation);
    digitalWrite(pins[j][1], !LEDOrientation);
  }
}

Any thoughts why this code doesn't work?

const int ImageColumns = 131;

int ImageRows = 72;
const int LEDEights = 9;

const int Image[ImageColumns][LEDEights]

Which Arduino are you using? I think you need a bigger one.

It's pretty likely that there is not enough RAM to hold your "Image." Right now it over 2300 bytes, and you have a lot of other data in RAM (x2, x2, x3, indata, pins), and an Uno only has 2048 bytes total RAM. It looks like you could halve your memory requirements by using "byte" instead of "int", but I don't know that that would be enough. That's probably why it was progmem in the first place.

Do you need to have the image be completely changed, or could you select one of several images stored in progmem?

[edit: fixed "image" --> "int"]

It looks like you could halve your memory requirements by using "byte" instead of "image"

sp. " instead of "int" "

westfw:

const int ImageColumns = 131;

int ImageRows = 72;
const int LEDEights = 9;

const int Image[ImageColumns][LEDEights]

Which Arduino are you using? I think you need a bigger one.

It's pretty likely that there is not enough RAM to hold your "Image." Right now it over 2300 bytes, and you have a lot of other data in RAM (x2, x2, x3, indata, pins), and an Uno only has 2048 bytes total RAM. It looks like you could halve your memory requirements by using "byte" instead of "int", but I don't know that that would be enough. That's probably why it was progmem in the first place.

Do you need to have the image be completely changed, or could you select one of several images stored in progmem?

[edit: fixed "image" --> "int"]

hi sir! thanks for your reply :slight_smile:
I am using a generic type of arduino UNO (Gizduino with ATMEGA328p SMD + UNO Bootloader).
by the way, the original project came from this site: http://v3-1255.vlinux.de/mediawiki/index.php/POV_globe

The project is really working fine. I could change the image, BUT, of course by ONLY burning the codes AGAIN to the microcontroller :frowning:
sample:

Is the RAM different from the FLASH memory of the chip?
"Binary sketch size: 7,522 bytes (of a 32,256 byte maximum)" <-- that is the size of the program. (I've deleted some parts of the code because the forum wouldn't let me to post exceeding 9500 characters).

or could you select one of several images stored in progmem?

-Can I do that? I will think of any way to select an image from the PROGMEM. I would really appreciate if you could help me. I would mention you sir in the acknowledgement part of my project's document. :smiley:

Flash is program memory, so no, it is not RAM

I will think of any way to select an image from the PROGMEM

It could be as simple as another dimension to your array.

It could be as simple as another dimension to your array.

hi sir AWOL! :slight_smile:
This is the code for the Progmem. I don't know how to add another dimension in this array.

prog_uint8_t Image[ImageColumns][LEDEights] PROGMEM = {
  { 
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10111111, B11111111, B11111111, B00000111, B11111100, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B11111111, B11111111, B00000111, B11110000, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B00101111, B10001111, B00000000, B11110000, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B00000111, B10001110, B00000000, B11110000, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B00011111, B10001110, B00000000, B11110000, B11111111, B11111111, B11111111  }
  , {
    B11110011, B00000011, B00000000, B00000000, B11110000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111011, B00000111, B00000000, B00000000, B11110000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B01111101, B00001000, B00000000, B00000000, B11100000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00111111, B00000000, B00000000, B00000000, B11000000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B00000000, B00000000, B00000000, B00000000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B00000001, B00000000, B00000000, B00000000, B11111100, B11111111, B11111111, B11111111  }
  , {
    B11111111, B00000000, B00000000, B00000000, B00000000, B11111000, B11111111, B11111111, B11111111  }
  , {
    B10111111, B00000000, B00000000, B00000000, B10000000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00111111, B00000000, B00000000, B00000000, B11000000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00001111, B00000000, B00000000, B00000000, B11100000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00000111, B00000000, B00000000, B00000000, B11100000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00000111, B00000000, B00000000, B00000000, B11100000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00000011, B00000000, B00000000, B00000000, B00000000, B11111111, B11111111, B11111111, B11111111  }
  , {
    B00000011, B00000000, B00000000, B00000000, B10000000, B11101111, B11111111, B11111111, B11111111  }
  , {
    B00000000, B00000000, B00000000, B00000000, B00000000, B10000110, B11111111, B11111111, B11111111  }
  , {
    B00000000, B00000000, B00000000, B00000000, B00000000, B00101110, B11111111, B11111111, B11111111  }
  , {
    B01000011, B00000000, B00000000, B00000000, B01000000, B11111000, B11111111, B11111111, B11111111  }
  , {
    B00100011, B00000000, B00000000, B00000000, B11000000, B11001111, B11111111, B11111111, B11111111  }
  , {
    B00110011, B00000000, B00000000, B00000000, B11000000, B10001111, B11111111, B11111111, B11111111  }
  , {

    B11111111, B00000011, B11111100, B11111111, B11111111, B11111111, B11111111, B11011111, B11111111  }
  , {
    B11111111, B00000111, B11111110, B11111111, B11111111, B11111111, B11111111, B11101111, B11111111  }
  , {
    B11111111, B00000111, B11111110, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11001111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10011111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B10011111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
  , {
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
};

By the way, I've checked the other Arduino Boards, such as the MEGAs. They have 8KB of SRAM and 4KB of EEPROM. that's huge. and the cost is huge as well. XD
I won't and can't consider buying a new board, cause I have already two boards in my project. One for the image and one for the text.

I don't know how to add another dimension in this array

Right between "Image" and the first opening square bracket.

ahaha. sorry sir. Of course I know how to add another dimension in array, I develop programs in vb.net and c# :slight_smile: (just my sideline job as a student), what I mean is: how am I suppose to add the binary codes of another image into the progmem? or how should I separate the codes?

for the globe map, say this is the code:

prog_uint8_t Image[ImageColumns][LEDEights] PROGMEM = {
  { 
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  }
};

I'll add a smiley image into the code:

prog_uint8_t Image[ImageColumns][LEDEights][ImageColumns2][LEDEights2] PROGMEM = {
  { 
    B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111  } //each row is composed of 72 num
//there are 131 columns
};

-is this correct? I just added another dimension in my array. where should I paste the Binary codes?
-I tried this:
at the end of the code, I added this:

  ,

  {
    { 
      B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111      }
    , {
      B11111111, B10110111, B10111001, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111      }
  }

};

also another "{" after the progmem =

the result is: "
sketch_mar01a:281: error: too many initializers for 'prog_uint8_t [9][2][9"

I would probably do something like:

prog_uint8_t Image1[ImageColumns][LEDEights] PROGMEM = { ... };
prog_uint8_t Image2[ImageColumns][LEDEights] PROGMEM = { ... };
prog_uint8_t Image3[ImageColumns][LEDEights] PROGMEM = { ... };
prog_uint8_t Image4[ImageColumns][LEDEights] PROGMEM = { ... };

uint8_t *imagelist[] = {image1, image2, image3, image4};