possible compiler malfunction

first, what my project is supposed to do. it is supposed to do image tracking on a robot for a competition (the goals will have retro-reflective tape on them, and the camera on the robot has an LED ring around). it will recieve a 60x45 pixel image from the network, but since i dont have the ethernet shield yet, i am using a static test picture, the RGB values of which are stored in the flash space. it first checks if each pixel falls within the given RGB bounds, and stores the results in a 2d array called binaryImage (it used to store true/false values in it, but i later changed it to have numbers. the basic idea is unchanged tho). it then removes any isolated pixels, since those can't possibly be right, by calling removeSmallParticles(). it then calls blobifyBinaryImage2(), which assigns contiguous regions an ID, and stores the id in binaryImage (blobifyBinaryImage() was an earlier attempt, long since abandonned. note that blobifyBinaryImage() is different than blobifyBinaryImage2(). also, the IDs start at 2. an id of 0 means the pixel is off, aka not a viable target. 1 means that the pixel is viable, but is awaiting blobification. thus, blobs start at 2). then, small blobs are eliminated, then the blobs are re-ID'd by changing the pixels back to 1, then blobifyBinaryImage2() again. throught the process, statuses are printed to various leds, a 7 segment display, and even a portable DVD player (using the TVout library) which lets me see what the board sees live.

now, since it will operate VERY differently if i have a camera plugged in vs not, i have a couple of precompiler directives to modify its behavior by simply commenting out a #define line (i also included a few novelty precompiler directives, such as a dummy loading screen, and letting out team mascot, lyle, blink, at the risk of using pointless delay()s). one such constant is DISABLE_CAMERA. when the constant is present, i want it to read my test image from flash memory. if i comment out DISABLE_CAMERA, i want it to declare a 2d array called colorImage to prepare to recieve an RGB image over the network. whether the code looks at testimage or colorImage is also taken care of by these precompiler directives.

So whats the problem? a portion of my code looks like

#define DISABLE_CAMERA
#ifndef DISABLE_CAMERA
  byte colorImage[2700][3];
#endif

(i know that is a huge array, and that it only leaves my mega with 92 bytes of ram. thats fine). now as any C/C++ programmer knows, i could easily replace that with

#define DISABLE_CAMERA
#ifndef DISABLE_CAMERA
  gt4ghuitregbuitregbre
#endif

and still get a clean compile, since the compiler skips will skip that portion. now is where things start to get freaky. when i compile, i get errors about how i, in a nutshell, forgot my prototypes. including prototypes does indeed quiet the compiler. according to the troubleshooting guide, there are well known circumstances in which this can occur. none of those apply to me. BUT get this: if i change #ifndef to #ifdef or comment out #define DISABLE_CAMERA or move it to an #else clause under #ifndef, or otherwise use the precompiler directives to tell it to compile, it will compile. it doesnt matter what i declare in that line. int x; has the same effect. if the compiler is clearly instructed to ignore its declaration, it goes haywire and gives me irrelevent errors (colorImage is not used anywhere in the code yet). if i tell it to look at the line, then it will compile (or not, depending on what the line is. i.e. valid syntax, etc). while i know that the compiler has issues generating prototypes under certain circumstances, i believe the problem is in the precompiler, not the actual compiler itself.
NOTES: i have a mega 2560 by OSEPP. since i am very pressed for memory, i use bytes and chars for virtually everything. the image that im processing is 4 basketball goals with retro-reflective tape around them. finally, my code (sorry its so sloppy)

imagetracking.ino (10.5 KB)

sorry. i just realized. where it says

#ifdef UNDEFINED_CONSTANT
  int x;
#endif

it should read

#ifndef DISABLE_CAMERA
  byte colorImage[2700][3];
#endif

however, as i said, it shouldn't matter!

  byte colorImage[2700][3];

Let me get my calculator out...

Yep, that's 8100 bytes. No Arduino has that much SRAM.

You don't have a compiler malfunction. You have a user error.

The mega 2560 has 8kb (1024=8192 -27003=92). at any rate, ram isn't the issue. heck, i should be able to replace byte colorImage[99999][9999] because the compiler is clearly instructed to not look at that line
i quote http://arduino.cc/en/Main/ArduinoBoardMega2560
SRAM 8 KB

No Arduino has that much SRAM.

Not strictly true

But I agree, unlikely to be a compiler issue.

The mega 2560 has 8kb (1024=8192 -27003=92)

Also true, but then there's stack, serial buffers, strings, variables...

what do you mean un likely to be a compiler issue? i very explicitly use the directives, and it downright ignores them . replace colorImane(2700)(3);(sorry for no square brackets too dificult to type on my phone) with, i dont care, int x;. you will get the same result. the only way its not a compiler issue is if its a precompiler issue

what do you mean un likely to be a compiler issue?

I mean, the compiler is robust.
The preprocessor is robust.
I think it unlikely that the problem lies there.

Unfortunately, there is a problem with the forum at the moment, and I can't download your code.

If memory serves me right (no pun intended), the IDE does build step before the precompiler that rearranges your #defines and creates function prototypes. I'm guessing you've run afoul of this step.

Perhaps someone who recalls what this build step does will join the thread and fill us in on whether it might be affecting your code in this instance. I could be barking up the wrong tree.

-br

here is imagetracking.ino /*This code (excluding external libraries) is the intellectual property of Team - Pastebin.com
here is lyle.cpp #include "lyle.h"PROGMEM const unsigned char lyle[] = { 53,45, 0x00, 0 - Pastebin.com
here is lyle.h

#include <avr/pgmspace.h>

extern const unsigned char lyle[];

here is testimage.cpp #include "testimage.h"PROGMEM prog_uchar testimage[][3] = {{134, 116, 76}, { - Pastebin.com
and here is testimage.h

#include <avr/pgmspace.h>

extern prog_uchar testimage[][3];

sorry if i violated any linking policies. also, you will need the TVout library

void recursivelyFloodPixelIdToAdjacentPixels(byte row, byte col, byte blobId)

In the general computing world, the motto "To iterate is human, to recurse, divine" may hold true, but in the microcontroller world, I wouldn't recommend it.

This:

#define DISABLE_CAMERA
#ifndef DISABLE_CAMERA
  gt4ghuitregbuitregbre
#endif

void setup()  { return; }
void loop() {return;}

produces this ( does not compile ):

#line 1 "_01_Initialisation.ino"

#define DISABLE_CAMERA
#ifndef DISABLE_CAMERA
  #include "Arduino.h"
gt4ghuitregbuitregbre
 

void setup();
void loop();
#line 4
gt4ghuitregbuitregbre
#endif

void setup()  { return; }
void loop() {return;}

When I add an include on top, it compiled fine:

#include <SPI.h>

#define DISABLE_CAMERA
#ifndef DISABLE_CAMERA
  gt4ghuitregbuitregbre
#endif

void setup()  { return; }
void loop() {return;}

It is just a result of the IDE, add your defines to a header file instead, might fix things.

it was the simplest algorithm that i could think of to flood fill a pixel/blob id to the contiguous blob. it runs quickly enough.

i believe the problem is in the precompiler, not the actual compiler itself.

That's fairly easy to confirm: just declare the array and see if the issue persists.

But I have to say that leaving 92 bytes is tight - you better make sure that you do indeed need no more than that.

dhenry:

i believe the problem is in the precompiler, not the actual compiler itself.

That's fairly easy to confirm: just declare the array and see if the issue persists.

But I have to say that leaving 92 bytes is tight - you better make sure that you do indeed need no more than that.

I would seriously recommend replacing your Arduino with a ChipKit MEGA32 - it has a 32-bit CPU on it with 128KiB of RAM, and 512KiB of Flash. It'd give you just a touch more breathing space...

dhenry: im not at my computer right now (im at school) but i know that 92 bytes is very tight. i am not sure exactly how i will implememnt this until i do physical testing, but 92 bytes is a worst case scenario. even so, i can store multiple values in one byte by using bitshift operators if the values are small enough.
pYro: how would #Including <SPI.h> help? i am not using any SPI anything

fizyplankton:
pYro: how would #Including <SPI.h> help? i am not using any SPI anything

Adding a #include of anything at the top of the program changes how the IDE pre-processes the .ino file into a .cpp file - it gets around the problem by moving it to a different part of the program.

have you tried using the 5 files i gave you plus the #include <SPI.h> and you got a clean compile? even though i am at school, i can SSH into my comp to try your change. i just dont know how to compile it via command line

fizyplankton:
dhenry: im not at my computer right now (im at school) but i know that 92 bytes is very tight. i am not sure exactly how i will implememnt this until i do physical testing, but 92 bytes is a worst case scenario. even so, i can store multiple values in one byte by using bitshift operators if the values are small enough.
pYro: how would #Including <SPI.h> help? i am not using any SPI anything

The working output is still wrong ( the ide adds #include "Arduino.h" inside the #ifndef ), the spi.h adds in the arduino header, which other libraries will do. This whole mess is why I encourage you to stick your defines in a header to avoid it being messed with.

A lot of the programs I work with have code like.

#ifndef CAMERA_CODE
#define CAMERA_CODE

// declarations here

#endif

I notice in your example, the first two lines seem to be the other way around.

That format is most often seen as a wrapper around an entire header file contents. It prevents the code being included twice in the event that another header includes the header as well as you including the header yourself.

It is not used for optional compilation of different portions of the code.