Error during compilation using multiple files: "array bound is not an integer constant before ']' token"

Hello everybody!
Just some background on the code, I am making some improvements on old Maze solving robot code. I have two Maze solver robots that are similar and share a lot of code, so I was trying to separate the different functions (sensor reading, output functions, movement, etc) in different files to better organize the code. I tried to make all the variable definitions in one header file, to easily change the code to one specific robot without changing any of the rest of code.

Now to the problem itself, two const int variables declared in one .h file, used to declare the size of arrays in other .h file, are not being recognized as const or int, even if I use the "extern" qualifier during declaration to tell the compiler the variables are defined elsewhere. Below is the code that is generating the error:

In RoboChassiDeGrilo.h (header file who defines the pins and other variables related to one specific robot)

#include "Arduino.h"

const int pinoC1E = 2, pinoC2E = 4, pinoC1D = 3, pinoC2D = 7; //Pinos de cada sensor do encoder
volatile long pulsosEncD = 0, pulsosEncE = 0; // Pulsos lidos em cada encoder
volatile long pulsosAntE = 0, pulsosAntD = 0; //Pulsos anteriores, utilizados para saber quanto cada motor girou

const int numUltras = 3, tamFiltro = 3; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons; 

//there is more code below, but it is not important to the problem

In lituraSensores.h (header file related to sensor readings of the robot)

#include "Arduino.h"

#include <Wire.h> //Inclui a biblioteca de comunicacao I2C
#include <Adafruit_TCS34725.h> //Inclui a biblioteca com as configuracoes do TCS34725

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_2_4MS, TCS34725_GAIN_16X); //Declara o sensor de cor e indica as configuracoes desejadas

extern void encoderE(), encoderD();
extern const int pinoC1E, pinoC2E, pinoC1D, pinoC2D; //Pinos de cada sensor do encoder

extern const int numUltras, tamFiltro; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons
extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

typedef struct //Define a estrutura de dados do Ring Buffer que guardará as "tamFiltro" ultimas leituras do ultrassom
{
  int lastIndex; //Salva em qual posicao do vetor foi colocada a ultima leitura
  float leituras[tamFiltro]; //Vetor que guarda as leituras
} leituraUltra;

//there is more code below, but it is not important to the problem

This is the error messages I get during compilation:

leituraSensores.h:12: error: array bound is not an integer constant before ']' token

 extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

leituraSensores.h:17: error: array bound is not an integer constant before ']' token

   float leituras[tamFiltro]; //Vetor que guarda as leituras

Even using the "extern" qualifier during the definition of the variables does not help (theoretically that would enable the external linkage of the variables). In case anyone wants to give a deeper look in the code, it is here: Maze solver CommonCoreV1.

Any idea what am I doing wrong?
Thanks for your attention!

I guess you should do like this:

extern const int numUltras;

Now you have made the elements inside your array of type const int.

I am not really experienced in extern keyword, so it might not work ..

in

extern const int numUltras, tamFiltro; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons
extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

the value of numUltras is not known

try including lituraSensores.h in lituraSensores.h

Hi! Sorry, I forgot to mention I included all the .h files in the main program, in this case, in CommonCoreV1.ino:

#include "RoboChassiDeGrilo.h"

#include "leituraSensores.h"
#include "funcoesSaida.h"
#include "movimentacao.h"



byte state = 0, numManobra = 0;
char trajeto[50];

void setup()
{

//there is more code below, but it is not important to the problem

I thought that the compiler would already know the values of numUltras and tamFiltro by the time the other headers are included, but I don't have a lot of experience in separating code. I will try the suggestions, thanks for the help!

strange it should work
I have RoboChassiDeGrilo.h

#include "Arduino.h"

const int pinoC1E = 2, pinoC2E = 4, pinoC1D = 3, pinoC2D = 7; //Pinos de cada sensor do encoder
volatile long pulsosEncD = 0, pulsosEncE = 0; // Pulsos lidos em cada encoder
volatile long pulsosAntE = 0, pulsosAntD = 0; //Pulsos anteriores, utilizados para saber quanto cada motor girou

const int numUltras = 3, tamFiltro = 3; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons; 

and leituraSensores.h

#include "Arduino.h"

//#include <Wire.h> //Inclui a biblioteca de comunicacao I2C
//#include <Adafruit_TCS34725.h> //Inclui a biblioteca com as configuracoes do TCS34725

//Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_2_4MS, TCS34725_GAIN_16X); //Declara o sensor de cor e indica as configuracoes desejadas

extern void encoderE(), encoderD();
extern const int pinoC1E, pinoC2E, pinoC1D, pinoC2D; //Pinos de cada sensor do encoder

extern const int numUltras, tamFiltro; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons
extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

typedef struct //Define a estrutura de dados do Ring Buffer que guardará as "tamFiltro" ultimas leituras do ultrassom
{
  int lastIndex; //Salva em qual posicao do vetor foi colocada a ultima leitura
  float leituras[tamFiltro]; //Vetor que guarda as leituras
} leituraUltra;

and CommonCoreV1.ino

#include "RoboChassiDeGrilo.h"

#include "leituraSensores.h"
//#include "funcoesSaida.h"
//#include "movimentacao.h"

byte state = 0, numManobra = 0;
char trajeto[50];

void setup()
{
  Serial.begin(115200);
  Serial.println(numUltras);
}

void loop() {
  // put your main code here, to run repeatedly:

}

it compiles, links, uploads and run - serial monitor displays

3

I assume you have your .ino and .h files in the same directory?

Hi!
In this case, the array is also const because it is where the pins of the ultrasonic sensors are attached. Thanks for the solution presented! I tried it but unfortunately it didn't work. The changes were:

On leituraSensores.h (on the first post I called it lituraSensores.h, but it was a typo, sorry) I changed:

#include "Arduino.h"

#include <Wire.h> //Inclui a biblioteca de comunicacao I2C
#include <Adafruit_TCS34725.h> //Inclui a biblioteca com as configuracoes do TCS34725

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_2_4MS, TCS34725_GAIN_16X); //Declara o sensor de cor e indica as configuracoes desejadas

extern void encoderE(), encoderD();
extern const int pinoC1E, pinoC2E, pinoC1D, pinoC2D; //Pinos de cada sensor do encoder

extern const int numUltras; //Número de ultrassons 
extern const int tamFiltro; //Tamanho do vetor utilizado para filtragem por mediana dos ultrassons
extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

typedef struct //Define a estrutura de dados do Ring Buffer que guardará as "tamFiltro" ultimas leituras do ultrassom
{
  int lastIndex; //Salva em qual posicao do vetor foi colocada a ultima leitura
  float leituras[tamFiltro]; //Vetor que guarda as leituras
} leituraUltra;

\\more code below

and in RoboChassiDeGrilo.h I changed:

#include "Arduino.h"

const int pinoC1E = 2, pinoC2E = 4, pinoC1D = 3, pinoC2D = 7; //Pinos de cada sensor do encoder
volatile long pulsosEncD = 0, pulsosEncE = 0; // Pulsos lidos em cada encoder
volatile long pulsosAntE = 0, pulsosAntD = 0; //Pulsos anteriores, utilizados para saber quanto cada motor girou

extern const int numUltras = 3; //Número de ultrassons
extern const int tamFiltro = 3; //Tamanho do vetor utilizado para filtragem por mediana dos ultrassons; 
const int pinoUltra[numUltras] = {16, 14, 15}; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

//more code below

but the error keeps the same :frowning:. I think horace is right, compiler is not understanding the value of numUltras and tamFiltro, I will investigate more.

Hi horace.
Yes, they are all in the same directory. I am also intrigued why this is not working, in principle it should. Maybe there is some better practice I am not following? I will try to replicate your test and increment the code step by step, to determine where the problems arise. Thank you very much for the attention!

if I compile your .zip code I don't see the error messages you had in post #1 but I do get

C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp: In function 'void parado(int)':
movimentacao.cpp:6:3: error: 'motorDrive' was not declared in this scope
   motorDrive('e', 'b', 255);
   ^~~~~~~~~~
In file included from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:2:0:
leituraSensores.h:12:37: error: array bound is not an integer constant before ']' token
 extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados
                                     ^
leituraSensores.h:17:27: error: array bound is not an integer constant before ']' token
   float leituras[tamFiltro]; //Vetor que guarda as leituras
                           ^
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp: In function 'void ringBuf(leituraUltra*, float)':
leituraSensores.cpp:35:10: error: 'struct leituraUltra' has no member named 'leituras'
   ultra->leituras[ultra->lastIndex] = leitura; //Coloca a leitura no índice correto
          ^~~~~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp: In function 'float medianFilter(leituraUltra)':
leituraSensores.cpp:45:17: error: 'struct leituraUltra' has no member named 'leituras'
       if (ultra.leituras[i] < ultra.leituras[i + 1])
                 ^~~~~~~~
leituraSensores.cpp:45:37: error: 'struct leituraUltra' has no member named 'leituras'
       if (ultra.leituras[i] < ultra.leituras[i + 1])
                                     ^~~~~~~~
leituraSensores.cpp:47:23: error: 'struct leituraUltra' has no member named 'leituras'
         maior = ultra.leituras[i + 1];
                       ^~~~~~~~
leituraSensores.cpp:48:15: error: 'struct leituraUltra' has no member named 'leituras'
         ultra.leituras[i + 1] = ultra.leituras[i];
               ^~~~~~~~
leituraSensores.cpp:48:39: error: 'struct leituraUltra' has no member named 'leituras'
         ultra.leituras[i + 1] = ultra.leituras[i];
                                       ^~~~~~~~
leituraSensores.cpp:49:15: error: 'struct leituraUltra' has no member named 'leituras'
         ultra.leituras[i] = maior;
               ^~~~~~~~
leituraSensores.cpp:53:16: error: 'struct leituraUltra' has no member named 'leituras'
   return ultra.leituras[1]; //Retorna a mediana das leituras ordenadas. Mudar aqui caso o tamFiltro mude
                ^~~~~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp: In function 'char lerCor(Adafruit_TCS34725, char)':
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:70:21: warning: invalid conversion from 'int*' to 'uint16_t* {aka unsigned int*}' [-fpermissive]
   sensor.getRawData(&verm, &verd, &azul, &bran); //Funcao da biblioteca do sensor que le os valores obtidos pelo mesmo
                     ^~~~~
movimentacao.cpp:9:24: error: 'pulsosEncE' was not declared in this scope
   long pulsosParadaE = pulsosEncE, pulsosParadaD = pulsosEncD; //Salva qual a posicao em que o comando de parar foi dado ao motor
                        ^~~~~~~~~~
In file included from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.h:4:0,
                 from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:2:
C:\Users\bb\Documents\Arduino\libraries\Adafruit_TCS34725-master/Adafruit_TCS34725.h:206:8: note:   initializing argument 1 of 'void Adafruit_TCS34725::getRawData(uint16_t*, uint16_t*, uint16_t*, uint16_t*)'
   void getRawData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c);
        ^~~~~~~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:70:28: warning: invalid conversion from 'int*' to 'uint16_t* {aka unsigned int*}' [-fpermissive]
   sensor.getRawData(&verm, &verd, &azul, &bran); //Funcao da biblioteca do sensor que le os valores obtidos pelo mesmo
                            ^~~~~
In file included from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.h:4:0,
                 from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:2:
C:\Users\bb\Documents\Arduino\libraries\Adafruit_TCS34725-master/Adafruit_TCS34725.h:206:8: note:   initializing argument 2 of 'void Adafruit_TCS34725::getRawData(uint16_t*, uint16_t*, uint16_t*, uint16_t*)'
   void getRawData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c);
        ^~~~~~~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:70:35: warning: invalid conversion from 'int*' to 'uint16_t* {aka unsigned int*}' [-fpermissive]
   sensor.getRawData(&verm, &verd, &azul, &bran); //Funcao da biblioteca do sensor que le os valores obtidos pelo mesmo
                                   ^~~~~
In file included from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.h:4:0,
                 from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:2:
C:\Users\bb\Documents\Arduino\libraries\Adafruit_TCS34725-master/Adafruit_TCS34725.h:206:8: note:   initializing argument 3 of 'void Adafruit_TCS34725::getRawData(uint16_t*, uint16_t*, uint16_t*, uint16_t*)'
   void getRawData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c);
        ^~~~~~~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:70:42: warning: invalid conversion from 'int*' to 'uint16_t* {aka unsigned int*}' [-fpermissive]
   sensor.getRawData(&verm, &verd, &azul, &bran); //Funcao da biblioteca do sensor que le os valores obtidos pelo mesmo
                                          ^~~~~
In file included from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.h:4:0,
                 from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:2:
C:\Users\bb\Documents\Arduino\libraries\Adafruit_TCS34725-master/Adafruit_TCS34725.h:206:8: note:   initializing argument 4 of 'void Adafruit_TCS34725::getRawData(uint16_t*, uint16_t*, uint16_t*, uint16_t*)'
   void getRawData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c);
        ^~~~~~~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:9:24: note: suggested alternative: 'pulseIn'
   long pulsosParadaE = pulsosEncE, pulsosParadaD = pulsosEncD; //Salva qual a posicao em que o comando de parar foi dado ao motor
                        ^~~~~~~~~~
                        pulseIn
In file included from C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:1:0:
movimentacao.cpp:10:54: error: 'pulsosEncD' was not declared in this scope
   while (abs(pulsosEncE - pulsosParadaE) > 10 && abs(pulsosEncD - pulsosParadaD) > 10) //Enquanto o robo nao estiver em uma posicao proxima aonde deveria parar
                                                      ^
C:\Users\bb\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:94:18: note: in definition of macro 'abs'
 #define abs(x) ((x)>0?(x):-(x))
                  ^
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\leituraSensores.cpp:85:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:10:54: note: suggested alternative: 'pulseIn'
   while (abs(pulsosEncE - pulsosParadaE) > 10 && abs(pulsosEncD - pulsosParadaD) > 10) //Enquanto o robo nao estiver em uma posicao proxima aonde deveria parar
                                                      ^
C:\Users\bb\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:94:18: note: in definition of macro 'abs'
 #define abs(x) ((x)>0?(x):-(x))
                  ^
movimentacao.cpp:10:67: error: 'pulsosParadaD' was not declared in this scope
   while (abs(pulsosEncE - pulsosParadaE) > 10 && abs(pulsosEncD - pulsosParadaD) > 10) //Enquanto o robo nao estiver em uma posicao proxima aonde deveria parar
                                                                   ^
C:\Users\bb\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:94:18: note: in definition of macro 'abs'
 #define abs(x) ((x)>0?(x):-(x))
                  ^
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:10:67: note: suggested alternative: 'pulsosParadaE'
   while (abs(pulsosEncE - pulsosParadaE) > 10 && abs(pulsosEncD - pulsosParadaD) > 10) //Enquanto o robo nao estiver em uma posicao proxima aonde deveria parar
                                                                   ^
C:\Users\bb\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:94:18: note: in definition of macro 'abs'
 #define abs(x) ((x)>0?(x):-(x))
                  ^
movimentacao.cpp:23:11: error: 'LED1' was not declared in this scope
   pinMode(LED1, LOW);
           ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:23:11: note: suggested alternative: 'EEDR'
   pinMode(LED1, LOW);
           ^~~~
           EEDR
movimentacao.cpp:24:11: error: 'LED2' was not declared in this scope
   pinMode(LED2, LOW);
           ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:24:11: note: suggested alternative: 'EEDR'
   pinMode(LED2, LOW);
           ^~~~
           EEDR
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp: In function 'void curva(char, char, byte)':
movimentacao.cpp:34:7: error: 'motorDrive' was not declared in this scope
       motorDrive('e', 'f', 100);
       ^~~~~~~~~~
movimentacao.cpp:36:15: error: 'LED1' was not declared in this scope
       pinMode(LED1, HIGH);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:36:15: note: suggested alternative: 'EEDR'
       pinMode(LED1, HIGH);
               ^~~~
               EEDR
movimentacao.cpp:37:15: error: 'LED2' was not declared in this scope
       pinMode(LED2, LOW);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:37:15: note: suggested alternative: 'EEDR'
       pinMode(LED2, LOW);
               ^~~~
               EEDR
movimentacao.cpp:41:7: error: 'motorDrive' was not declared in this scope
       motorDrive('e', 't', 100);
       ^~~~~~~~~~
movimentacao.cpp:43:15: error: 'LED1' was not declared in this scope
       pinMode(LED1, LOW);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:43:15: note: suggested alternative: 'EEDR'
       pinMode(LED1, LOW);
               ^~~~
               EEDR
movimentacao.cpp:44:15: error: 'LED2' was not declared in this scope
       pinMode(LED2, HIGH);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:44:15: note: suggested alternative: 'EEDR'
       pinMode(LED2, HIGH);
               ^~~~
               EEDR
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:48:21: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     else if (angulo = 180) //tempo necessario para curva de 180º
              ~~~~~~~^~~~~
movimentacao.cpp:55:7: error: 'motorDrive' was not declared in this scope
       motorDrive('e', 'f', 160);
       ^~~~~~~~~~
movimentacao.cpp:57:15: error: 'LED1' was not declared in this scope
       pinMode(LED1, HIGH);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:57:15: note: suggested alternative: 'EEDR'
       pinMode(LED1, HIGH);
               ^~~~
               EEDR
movimentacao.cpp:58:15: error: 'LED2' was not declared in this scope
       pinMode(LED2, LOW);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:58:15: note: suggested alternative: 'EEDR'
       pinMode(LED2, LOW);
               ^~~~
               EEDR
movimentacao.cpp:62:7: error: 'motorDrive' was not declared in this scope
       motorDrive('e', 't', 160);
       ^~~~~~~~~~
movimentacao.cpp:64:15: error: 'LED1' was not declared in this scope
       pinMode(LED1, LOW);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:64:15: note: suggested alternative: 'EEDR'
       pinMode(LED1, LOW);
               ^~~~
               EEDR
movimentacao.cpp:65:15: error: 'LED2' was not declared in this scope
       pinMode(LED2, HIGH);
               ^~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:65:15: note: suggested alternative: 'EEDR'
       pinMode(LED2, HIGH);
               ^~~~
               EEDR
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp:69:21: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     else if (angulo = 180) //tempo necessario para curva de 180º
              ~~~~~~~^~~~~
C:\Users\bb\AppData\Local\Temp\arduino_build_271497\sketch\movimentacao.cpp: In function 'void frenteQuad(char, char)':
movimentacao.cpp:78:5: error: 'motorDrive' was not declared in this scope
     motorDrive('e', 'f', velBase);
     ^~~~~~~~~~
movimentacao.cpp:87:5: error: 'motorDrive' was not declared in this scope
     motorDrive('e', 'f', velTurbo);
     ^~~~~~~~~~

I think you are missing a few includes, e.g. #include "funcoesSaida.h" in movimentacao..cpp

Hello!
I found something interesting. I tried to make the same modifications you made, but it gives the same error as before during compilation on my PC (if interested, the folder of the debug version of the code I made based on your changes is here). I suspect it may be related to the version of the IDE I am using (1.85 :melting_face:, on Windows). What version of Arduino IDE are you using? Thanks a lot for the attention!

1.8.13 on Windows 10

Oh, my bad! Really, I forgot this include. I added it and updated the folder. When I compile, unfortunately I get the same error as before:

leituraSensores.h:12: error: array bound is not an integer constant before ']' token

 extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

                                     ^

leituraSensores.h:17: error: array bound is not an integer constant before ']' token

   float leituras[tamFiltro]; //Vetor que guarda as leituras

                           ^

C:\Users\arthu\AppData\Local\Temp\arduino_build_462593\sketch\leituraSensores.cpp: In function 'void ringBuf(leituraUltra*, float)':

leituraSensores.cpp:35: error: 'struct leituraUltra' has no member named 'leituras'

   ultra->leituras[ultra->lastIndex] = leitura; //Coloca a leitura no índice correto

          ^

C:\Users\arthu\AppData\Local\Temp\arduino_build_462593\sketch\leituraSensores.cpp: In function 'float medianFilter(leituraUltra)':

leituraSensores.cpp:45: error: 'struct leituraUltra' has no member named 'leituras'

       if (ultra.leituras[i] < ultra.leituras[i + 1])

                 ^

leituraSensores.cpp:45: error: 'struct leituraUltra' has no member named 'leituras'

       if (ultra.leituras[i] < ultra.leituras[i + 1])

                                     ^

leituraSensores.cpp:47: error: 'struct leituraUltra' has no member named 'leituras'

         maior = ultra.leituras[i + 1];

                       ^

leituraSensores.cpp:48: error: 'struct leituraUltra' has no member named 'leituras'

         ultra.leituras[i + 1] = ultra.leituras[i];

               ^

leituraSensores.cpp:48: error: 'struct leituraUltra' has no member named 'leituras'

         ultra.leituras[i + 1] = ultra.leituras[i];

                                       ^

leituraSensores.cpp:49: error: 'struct leituraUltra' has no member named 'leituras'

         ultra.leituras[i] = maior;

               ^

leituraSensores.cpp:53: error: 'struct leituraUltra' has no member named 'leituras'

   return ultra.leituras[1]; //Retorna a mediana das leituras ordenadas. Mudar aqui caso o tamFiltro mude

I will try to update my IDE and see if the error vanishes. Thank you very much!

you have to have the includes in the correct order, e.g . in leituraSensores.cpp

#include "Arduino.h"
#include "RoboChassiDeGrilo.h"
#include "leituraSensores.h"

and in movimentacao.cpp

#include "Arduino.h"
#include "funcoesSaida.h"
#include "movimentacao.h"
#include "RoboChassiDeGrilo.h"

I think because you have a lot of definitions in your header files you will get multiple definitions at link time
only put declarations in header files, i.e. using extern, and the definitions in the .ino and .cpp files

Perfect, I tried to do that, taking all the definitions from "RoboChassiDeGrilo.h", (where all the definitions occur), and putting all of them on "RoboChassiDeGrilo.cpp":

"RoboChassiDeGrilo.h":

#include "Arduino.h"

extern const int pinoC1E, pinoC2E, pinoC1D, pinoC2D; //Pinos de cada sensor do encoder
extern volatile long pulsosEncD = 0, pulsosEncE = 0; // Pulsos lidos em cada encoder
extern volatile long pulsosAntE = 0, pulsosAntD = 0; //Pulsos anteriores, utilizados para saber quanto cada motor girou

extern const int numUltras, tamFiltro; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons
extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados
\\more code below

"RoboChassiDeGrilo.cpp":

#include "Arduino.h"
#include "RoboChassiDeGrilo.h"

const int pinoC1E = 2, pinoC2E = 4, pinoC1D = 3, pinoC2D = 7; //Pinos de cada sensor do encoder
volatile long pulsosEncD = 0, pulsosEncE = 0; // Pulsos lidos em cada encoder
volatile long pulsosAntE = 0, pulsosAntD = 0; //Pulsos anteriores, utilizados para saber quanto cada motor girou

const int numUltras = 3, tamFiltro = 3; //Número de ultrassons e Tamanho do vetor utilizado para filtragem por mediana dos ultrassons;
const int pinoUltra[numUltras] = {16, 14, 15}; //Pinos em que os ultrassons esquerda, frente, direita estao conectados

//more code below

However, the error persists, now happening on the "RoboChassiDeGrilo.h" itself:

In file included from C:\Users\arthu\Documents\Arduino\Labirinto Common Core\CommonCoreV1\CommonCoreV1.ino:1:0:
RoboChassiDeGrilo.h:8:37: error: array bound is not an integer constant before ']' token
 extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados
                                     ^
In file included from C:\Users\arthu\Documents\Arduino\Labirinto Common Core\CommonCoreV1\CommonCoreV1.ino:3:0:
leituraSensores.h:11:37: error: array bound is not an integer constant before ']' token
 extern const int pinoUltra[numUltras]; //Pinos em que os ultrassons esquerda, frente, direita estao conectados
                                     ^
leituraSensores.h:16:27: error: array bound is not an integer constant before ']' token
   float leituras[tamFiltro]; //Vetor que guarda as leituras

Thanks!

Is it really correct to do the extern declaration like this:

extern const int pinoUltra[numUltras];

rather than like this:

extern const int pinoUltra[];

I'm not sure the file containing the extern declaration can know the size of the array, only that is IS an array.

Hello!
The correct declaration is really

extern const int pinoUltra[];

Using it, the errors related to pinoUltra disappear. However, I don't know how to handle the error regarding the leituras[] array, since it is needed to define the size of the array (it is inside a typedef).
Thanks for the insight!

Your problem there is the compiler does not know the value of tamFiltro at compile time, so it cannot possibly know the size of the array. You simply cannot do that. Array size MUST be a known value when the array is defined. But, you can define the typedef in the first header file, where all the constants are defined, then simply instantiate an instance of it in the second header file. Or, put the typedef in its own header file.

Thanks for the insight, it was very fruitful.
Searching more about the subject, I found this explanation in a similar problem, which corroborates what you say:

In C++ the compilation process consists of 3 basic steps:

  1. Preprocessing of all source files done by preprocessor.
  2. Compilation for every translation unit (.cpp file) done by compiler. For every translation unit compiler creates an object file.
  3. Linking of all object files done by linker. The output is an executable file.

In C++ the keyword extern for compiler means that the variable is 'somewhere' defined. The compiler doesn't know the variable's real address but by placing keyword extern it's assured that the variable really exists and the linker will be able to find its address by its name when creating the executable file.

The problem here is that compiler in step 2 wants to create the object file but it doesn't known how big the array is going to be because it doesn't know the value of these constants. Yes, linker in step 3 will finally find them when putting together all object files but it's too late for compiler. So it generates that error.

I decided to move the constant tamFiltro to the "leituraSensores.h" since I think i will rarely change it, and all the uses of this constant are whitin the functions in the "leituraSensores.cpp".

The constant numUltras was a little more complicated, because it is used both in the main program and in "RoboChassiDeGrilo.cpp". I think I found a (maybe messy) workaround by defining it in the "RoboChassiDeGrilo.h", but only if it was not defined previously. This way, I avoid any re-definition problem:

In "RoboChassiDeGrilo.h":

#ifndef numUltrasDefinido //Only definition in the header file (the others are in the .cpp file)
  #define numUltrasDefinido 1 //This is done because the compiler needs to know the size of the arrays declared beforehand, only possible if the constant is in the header
  const int numUltras = 3; //Número de ultrassons
#endif //this definition is conditional in order to avoid redefinition if the header is called more than once

With those modifications, I am able to compile the program without problems. In case anyone wants to experiment further, the most recent version is now on here. Thanks to everybody who dedicated their time to help me, it's very appreciated! I hope to be able to help some day!

Messy is not the word I would use. At some point, it is likely to come back and bite you in the a**. I suggest you find a solution that does NOT require the #ifndef. There IS a way to do it...

do you use Header Guards in your .h files?
they help to avoid multiple definition problems

e.g. in "RoboChassiDeGrilo.h":

#ifndef _RoboChassiDeGrilo_h_
#define _RoboChassiDeGrilo_h_
.....
#endif

using #ifndef ensures that the header file is included if RoboChassiDeGrilo_h is not defined, i.e. the header has not already been included

Hi! That is a good idea, it is better than guarding only the variable, and it is more standard practice. I will implement this change, thank you for the insight!