5

Now the code I'm writing in Arduino (Using Arduino) uses multiple 2-dimensional arrays. Now when I print some thing using the Serial Monitor it prints it correctly but when I declare and initialize the 2-dimentional array it won't print it.

Code:

void setup()
{
  Serial.begin(9600);
  int image_width = 56;
  int image_height = 96;


  int image_result[image_width][image_height];
  for (int i=0; i<image_height; i++) {
    for (int j=0; j<image_width; j++) {
      image_result[j][i] = 5;
    }
  }

  Serial.print("code works");
}

Now in this case "code works" does not print but when I remove the array declaration and initialization code works is printed. What is the problem?

Do 2 dimensional arrays work differently in Arduino or is it a space issue?

  • Even a one-dimensional array of 5376 bytes, on a processor with 2048 bytes, will fail. – Nick Gammon Aug 20 '15 at 20:50
  • I meant, 10752 bytes. I overlooked that each array item is 2 bytes. Bear in mind you don't even have all of those 2048 bytes available. The Serial transmit and receive buffers alone use up 128 bytes. – Nick Gammon Aug 21 '15 at 6:02
  • Well if I connect a micro-SD car is there some method to declare array in that memory? – George J. Adams Aug 21 '15 at 6:04
  • You can connect a SD card and write data to your heart's content. However you can't "declare the array in memory" on it. What is your application here? An Arduino with 2 KB of RAM isn't the best thing for image processing. – Nick Gammon Aug 21 '15 at 6:08
  • I need to read a small BMP file in an array of ints in Arduino and need to do some processing on it. And the file size is 56 by 96 pixels. – George J. Adams Aug 21 '15 at 6:10
9

2D arrays work fine on arduino, but you run out of space very quickly.

An uno has 2 kilobytes of ram; your array has 56*96 = 5376 2-byte elements.

I would guess that you are writing over some critical memory value with a 5 at some point causing the program to fail.

| improve this answer | |
  • Not only over memory, but probably also over all the I/O registers. – Edgar Bonet Aug 20 '15 at 20:03
  • 16 bit addressing, with SRAM starting from 256. So that's 65279 bytes of address space. So you won't reach that. Also, I'm pretty sure there is some kind of protection preventing this from happening. – Gerben Aug 20 '15 at 20:17
  • There is no protection. The CPU registers are memory-mapped starting at address 0, then the I/O registers from address 32, then the statically-allocated RAM starts at address 256. – Edgar Bonet Aug 23 '15 at 6:36
2

You are trying to use more memory than you have available: 96 * 56 * 2 = 10.752KBytes. Not much that the MCU can do when this happens.

If you look into the datasheet, you'll see that your microcontroller (ATmega328p) only has 2KBytes of RAM.

I guess the question then, is to ask yourself if you really need that large an array. You may consider getting an external flash chip or an SDcard shield. If you only need it for read-only purposes (such as a lookup table), you can use some of your flash program memory (you have 32KBytes).

| improve this answer | |
  • I'm using a SDcard sheild but I'm reading the data into an array declared like this. How would I be able to use the SD Card memory. – George J. Adams Aug 21 '15 at 5:58
  • 2
    You don't usually need to deal with all 5376 elements of your array at one instant. Consider dividing up your image into smaller chunks for processing. Depending on the kind of processing that you do, you may require different smarts to optimize the process. ;-) – bot3663369 Aug 21 '15 at 6:33
  • Can one write data on the flash memory again and again. What do you mean by read-only? How does one write the data once on it. For example I want to write the image data on the flash memory one. How will I be able to do it? – George J. Adams Aug 21 '15 at 6:40
  • I am referring to your program flash memory. AFAIK, you can only write to the program flash during programming. One you boot your MCU, the program flash is used as read-only memory (so that we don't mess up the program when it's running.) Since you want to write your data, the program flash is not suitable. – bot3663369 Aug 21 '15 at 8:59
  • Do you really need to process the whole image in one go? As I've mentioned before, you can divide your image to smaller blocks, say chunk[8][8] would be a comfortable size for Arduino to swallow, and it works well even if you use convolution filters. (Having said that, I must stress that the Arduino Uno is ill-suited for any serious image processing application.) – bot3663369 Aug 21 '15 at 9:08
0

Indeed, this is an issue of RAM available. If you do not need 8 bits per piece of data (if you are perhaps willing to reduce image quality, for example), consider compacting your data such that you have multiple piece of data per bit. For example, hex values or BCD (binary coded decimals) could work, depending on the size of each piece of data.

| improve this answer | |
  • The OP wants to read a BMP file into memory, so I doubt it can be turned into BCD very usefully. – Nick Gammon Aug 22 '15 at 6:58
  • That's a good point. Perhaps he's willing to significantly decrease his image quality? Either way, additional storage would be wise. – Dodo Aug 22 '15 at 7:27
0

As others have noted, your array is larger than the available RAM in your Arduino. Others mentioned Flash memory which could be a solution for you. Your Arduino has 32 KB of memory which could hold your array. See the following reference for more info about Flash memory. Keep in mind that Flash and EEPROM have a limited number of write cycles before becoming unreliable.

Hidden Powers - storing data in Flash and EEPROM

| improve this answer | |
0

In case the matrix is mostly empty or anyway has values that can be calculated programmatically, sparse arrays might come to the rescue. It requires memory allocation and hopping, so the access time to individual elements is not deterministic, but you can calculate the worst-case scenario.

| improve this answer | |
-1

This is what I fed my Uno:

#define IMAGEWIDTH 56
#define IMAGEHEIGHT 96

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

  int i, j;
  int image_result[IMAGEWIDTH][IMAGEHEIGHT];

  for (i = 0; i < IMAGEWIDTH; i++) {
    Serial.print("\nIMAGEWIDTH ");
    Serial.print(i + 1);
    Serial.println(":");
    for (j = 0; j < IMAGEHEIGHT; j++) {
      image_result[i][j] = i + j;
      Serial.print("image_result[");
      Serial.print(i + 1);
      Serial.print("][");
      Serial.print(j + 1);
      Serial.print("]: ");
      Serial.println(image_result[i][j]);
    }
  }
  Serial.println(F("\nDone!"));
}

void loop() {
}

This will run over the whole array, while printing progress over Serial, which then print "Done!" once it is. I suggest changing:

#define IMAGEWIDTH 56
#define IMAGEHEIGHT 96

To lesser values, unless you have a few good minutes at hand.

| improve this answer | |
  • 2
    This is not at all going to solve his problem. It isn't time, it is the size of the array. 56 * 96 * 2 (an int is two bytes) uses 10752 bytes. Your Uno has 2048 bytes. The issue is not time, it is storage. – Nick Gammon Aug 21 '15 at 5:59
  • 1
    Nick was right, this hasn't solved my problem. Anyway, thanks for trying. – George J. Adams Aug 21 '15 at 9:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.