How to declare arrays in another (not main) tab?

hi

so the question is if it's possible to declare arrays in another tab?, i.e. not in the tab where you have void setup and void loop. I like to declare functions in different tabs for fast switching but it doesn't seem to work for arrays. I need to declare 16 arrays, and the number will increase and I don't want to have them all in the main tab.

It is possible so you will need to post your code so it can be reviewed.

well there is not much to the code yet.

I’m building a midi controller that will send macros, i.e. sets of midi messages.
Now I have 16 macros planned, but I will be adding more as I will expand the hardware.

here is a rough draft:


const int macro01[6] = {1,2,3,4,5,6};
const int macro02[5] = {33,44,55,66,77};
const int macro03[5] = {14,12,43,3,73};
// and so on, 16 arrays and more

const byte buttonArray[2] ={2, 3}; //array of connected buttons
const byte buttonCount = 2; //amount of connected buttons

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

for (byte a=0; a<buttonCount; a++) //Initializes the button pins as inputs
{
pinMode(buttonArray[a], INPUT);
delay(1);
}

}

void loop() {

}


I want to put the macros declared at the top into another tab, or maybe into an external file (if that is a better solution).

I want to put the macros declared at the top into another tab, or maybe into an external file (if that is a better solution).

Another tab is another file.

So what is the problem? You don't seem to have them split out yet. What error are you getting?

If you are declaring in one file and then using in another, you will need to declare the array as 'extern' in the file where is is not declared, like

extern int varname;

if I split them, then whenever I need to get a value from one of the arrays e.g.

Serial.print(macro01[1]);

I get the error:

'macro01' was not declared in this scope

Have you declared the macro arracys as extern? If you haven't, try it. If it still does not work, post the two files...

re

I was declaring them wrong:

extern const int macro01; instead of extern const int macro01[];

thanks for helping me out!

didn't want to start a new topic, got another Q:

I'd like to have the array list in a separate file, maybe a class, text or perhaps an excel file, this would make changing the macros easier with no need to use the Arduino IDE.

What are the options here? Maybe you guys know of some tutorials?

I'd like to have the array list in a separate file

You can do that.

maybe a class

Possible, but the fact that you have to ask makes me think "unlikely".

text

The compiler doesn't care what extension you use. The file must be a text file, though, containing compilable code.

or perhaps an excel file

No.

this would make changing the macros easier with no need to use the Arduino IDE.

Despite the name, they aren't macros.

naut:
re

I was declaring them wrong:

extern const int macro01; instead of extern const int macro01;

Hrm, I’m still new to the arduino platform, but my C/C++ skills are good enough to say that that shouldn’t work. The 1st you stated is not an array, the 2nd one is. However, you cannot state an array as extern without stating the array size (though I think doing that may not work properly either, you’d have to try it to see).

You probably want to put these in a header file (.h extention) and then include that file using the #include “filename.h” directive (where filename.h is the name of the header file you created.

Doing this will do a few things actually.

  • It will separate the data from the code, which is considered a good idea anyway.
  • By declaring the array as a const and have it embedded in the code where it is going to be used (as opposed to having it as an extern which will in all likelihood defeat the compiler’s optimizer), if you reference only the elements of the array using constants indices, then the array will not actually be saved in your image, freeing up space. Since you’re writing these arrays probably as a way of spitting them out again in a sequence (accessing them using a loop), this will probably not be the case, but can be useful to know for other uses.

Things to be careful when using a header file. Don’t include the file multiple times as it very similar to as if you took that file and inserted it right where you specified the #include directive. In other words, it would be like you declared all the stuff you have in that file multiple times, resulting in a redeclaration error. There are ways around this by using some other marco directives (look up C macros #if defined/#ifdef/#define/#else/#endif for more info), however, it is unlikely you would be doing this, so I wouldn’t worry about it too much.

Good luck.

One other thing. If you start having lots of data, this could represent a problem in your code's storage and execution.

In storage, you have only a limited amount of FLASH memory (see your board specs for details, but the UNO has 2k)

In execution, you have a limited amount of SRAM (again see your board specs for details but the UNO has 32k)

For more information on this see point 8 here: http://arduino.cc/forum/index.php/topic,97455.0.html and here: http://playground.arduino.cc/Learning/Memory

For a way of reducing your SRAM footprint, see here: http://www.arduino.cc/en/Reference/PROGMEM

Hope this helps.

Adrian

adrian_h:
However, you cannot state an array as extern without stating the array size

Really? What happens?

adrian_h:
In storage, you have only a limited amount of FLASH memory (see your board specs for details, but the UNO has 2k)

In execution, you have a limited amount of SRAM (again see your board specs for details but the UNO has 32k)

Other way 'round actually, 32K flash program memory, 2K static RAM for data, stack, etc.

you cannot state an array as extern without stating the array size

You can declare it as a point to the same type as the array and it would have to work …

thanks for all the help, I'll try out the header file option, might just be what I'm looking for.

Quote this would make changing the macros easier with no need to use the Arduino IDE.

Despite the name, they aren't macros.

yep, I should have written arrays.

However, you cannot state an array as external without stating the array size (though I think doing that may not work properly either, you'd have to try it to see).

I did declare the size of the arrays but not in the main tab.

For a way of reducing your SRAM footprint, see here: http://www.arduino.cc/en/Reference/PROGMEM

I did try declaring the arrays with PROGMEM, but then I was getting garbage instead of midi messages. Maybe I overlooked something, I'll have to try it again.

Oops, yeah, your right. Was in a bit of a hurry when I posted that. Nice catch.

marco_c:

you cannot state an array as extern without stating the array size

You can declare it as a point to the same type as the array and it would have to work …

I think you meant as a pointer, but actually, you and I are both wrong. First I’d like to apologize as I’ve been using quite a few other languages recently that do bounds checking. Something that C/C++ does NOT do for built in arrays.

You can declare an extern array without bounds and it will work. When declaring an non-extern array, specifying the bounds will only flag an error if the initialization set exceeds the array size stated. However, if you want to access an element that exists beyond the bounds of the array (either negatively or positively), that is quite ok from the compiler’s perspective.

In case you didn’t get that the first time, C/C++ DOES NO BOUNDS CHECKING ON BUILT IN ARRAYS.

If you have your array in a separate .cpp file and have it declared as an extern pointer in your main file (which is what I think marco_c was suggesting), you would not get an error (I’m not sure why) but what happens is that upon linking, the extern pointer will be the value (not the address) of first element in the array. Not what you want.

So what you can do is one of two things, put the data into a .cpp file or into a .h file.

If you put it into a .h file, it would look like this (EDIT: not something like):
macro.h

const int macro01[6] = {1,2,3,4,5,6};
const int macro02[5] = {33,44,55,66,77};
const int macro03[5] = {14,12,43,3,73};
// and so on, 16 arrays and more

mainSketch

#include "macro.h"

const byte buttonArray[2] ={2, 3};  //array of connected buttons
const byte buttonCount = 2;   //amount of connected buttons

void setup() {
    Serial.begin(9600);
 
    for (byte a=0; a<buttonCount; a++)  //Initializes the button pins as inputs
    {
      pinMode(buttonArray[a], INPUT);
      delay(1);
    }   

}

void loop() {
 
 
}

While, if you want to put it into a .cpp file, you would do something like this:
macro.cpp

const int macro01[6] = {1,2,3,4,5,6};
const int macro02[5] = {33,44,55,66,77};
const int macro03[5] = {14,12,43,3,73};
// and so on, 16 arrays and more

mainSketch

extern const int macro01[6];
extern const int macro02[5];
extern const int macro03[5];
// and so on, 16 arrays and more

const byte buttonArray[2] ={2, 3};  //array of connected buttons
const byte buttonCount = 2;   //amount of connected buttons

void setup() {
    Serial.begin(9600);
 
    for (byte a=0; a<buttonCount; a++)  //Initializes the button pins as inputs
    {
      pinMode(buttonArray[a], INPUT);
      delay(1);
    }   

}

void loop() {
 
 
}

I say something like because this actually doesn’t work. Seems the const is causing problems due to either the optimizer or the optimizer’s interaction with the linker. When compiling a const array variable, the variable is given a different prefix to that of a non-const variable. But strangely, an extern const variable name just gets a non-const prefix. Not sure why this is but if you change the .cpp file remove all of the const directives OR add extern directives (one or the other not both), this works fine.

I.e. this:

extern const int macro01[6] = {1,2,3,4,5,6};
extern const int macro02[5] = {33,44,55,66,77};
extern const int macro03[5] = {14,12,43,3,73};
// and so on, 16 arrays and more

or this:

int macro01[6] = {1,2,3,4,5,6};
int macro02[5] = {33,44,55,66,77};
int macro03[5] = {14,12,43,3,73};
// and so on, 16 arrays and more

The header file would, IMHO, be the better choice though.

EDIT: I remember why now extern is required in my 2nd last example. It modifies the symbols for the linker to share the data across modules. I WOULD NOT recommend using my last example as this is a kluge.

As PeterH vaguely pointed out at first and more explicitly later, if using a source (.cpp) file to initialize (define) your data, it is better using extern in a header file declaring that variable while defining it’s value in a source file and including that header file in all source files that it is used in (including the source file that defines it) as well as in the main sketch file.

However, putting constants in a header file is fine in practice. DO NOT put non-constants into a header file as this can result in linking problems.

adrian_h: So what you can do is one of two things, put the data into a .cpp file or into a .h file.

If you put it into a .h file, it would look something like this:

While, if you want to put it into a .cpp file, you would do something like this:

No, and no. That's not the appropriate way to declare and define an initialised array in C++. Google will explain how this works - there's no need for you to try to guess how it works.

PeterH: No, and no. That's not the appropriate way to declare and define an initialised array in C++. Google will explain how this works - there's no need for you to try to guess how it works.

Sorry? Who's guessing? Not me, that's for sure.

What exactly are you thinking about? Are you talking about C++ containers such as vectors? That's not what was asked here.

it worked, I moved the midi macro arrays to an external .h file, placed it into the library folder,... the sketch compiles and runs as it supposed to. Thanks for the help!

Your welcome. Please don't forget to up karma for those that help. :)