#Include Errors

File “C:\Users\23reit\Desktop\VEX TP 2018-19\Lift.c” compiled on May 06 2018 12:17:37
Info*:Include file ‘C:\Users\USERNAME\Desktop\VEX TP 2018-19\main.c’ has already been opened.
Info*:Include file ‘C:\Users\USERNAME\Desktop\VEX TP 2018-19\main.c’ has already been opened.
Info*:Include file ‘C:\Users\USERNAME\Desktop\VEX TP 2018-19\main.c’ has already been opened.
Info*:Include file ‘C:\Users\USERNAME\Desktop\VEX TP 2018-19\Lift.c’ has already been opened.
Info*:Include file ‘C:\Users\USERNAME\Desktop\VEX TP 2018-19\main.c’ has already been opened.
Info*:Include file ‘C:\Users\USERNAME\Desktop\VEX TP 2018-19\main.c’ has already been opened.
Error:Undefined variable ‘GyroMaximumError’. ‘short’ assumed.
Warning:Symbol ‘abs’ is ‘deprecated’ definition. There may be alternate symbol with equivalent functionality.
Error:Undefined variable ‘GyroKp’. ‘short’ assumed.
Error:Undefined variable ‘GyroKi’. ‘short’ assumed.
Error:Undefined variable ‘GyroKd’. ‘short’ assumed.
Error:Undefined variable ‘DriveMaximumError’. ‘short’ assumed.
Error:Undefined variable ‘DriveKp’. ‘short’ assumed.
Error:Undefined variable ‘DriveKi’. ‘short’ assumed.
Error:Undefined variable ‘DriveKd’. ‘short’ assumed.
Error:Undefined variable ‘RestHeight’. ‘short’ assumed.
Error:Undefined variable ‘ShortPoleHeight’. ‘short’ assumed.
Error:Undefined variable ‘TallPoleHeight’. ‘short’ assumed.
Error:Undefined variable ‘MaximumHeight’. ‘short’ assumed.
Info*:Include file ‘C:\Users\23reit\Desktop\VEX TP 2018-19\main.c’ has already been opened.
Info*:Include file ‘C:\Users\23reit\Desktop\VEX TP 2018-19\Lift.c’ has already been opened.
Info*:Include file ‘C:\Users\23reit\Desktop\VEX TP 2018-19\DriveBase.c’ has already been opened.
Error:Duplicate variable declaration of ‘MaximumHeight’
Error:Variable ‘MaximumHeight’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘ShortPoleHeight’
Error:Variable ‘ShortPoleHeight’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘TallPoleHeight’
Error:Variable ‘TallPoleHeight’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘RestHeight’
Error:Duplicate variable declaration of ‘GyroKp’
Error:Variable ‘GyroKp’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘GyroKi’
Error:Variable ‘GyroKi’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘GyroKd’
Error:Variable ‘GyroKd’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘GyroMaximumError’
Error:Duplicate variable declaration of ‘DriveKp’
Error:Variable ‘DriveKp’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘DriveKi’
Error:Variable ‘DriveKi’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘DriveKd’
Error:Variable ‘DriveKd’ has been previously defined with a different value.
Error:Duplicate variable declaration of ‘DriveMaximumError’

All these errors comes up in my codes. I separated the codes into Lift.c, DriveBase.c, Autons.c, LCD.c, Variables.c and Main.c
I have all the variables which has errors in Variables.c and uses them in other separate codes. Then these errors comes up. What can I do?

Most likely your includes are messed up, if not outright circular.
Good on your part to split the code into multiple units, but you also need to properly form a dependency graph. Including a C file is a tricky endeavour - under a traditional C compiler, you’d split your code into declarations (.h files, headers only) and definitions (actual implementations, .c files), but since RobotC has no notion of independent compilation units and linking, you need to include .c files.

Make sure only your main.c includes the remaining files and if you can handle a simple acyclic dependency graph, you could be fine. If you have cycles (i.e. Autons.c uses something from LCD.c and vice versa), you’d have to split the function/variable prototypes into a header file (.h) and include the header file instead.

See https://vexforum.com/t/program-structure-proposal/45132/1 for some inspiration.

I’m not sure with RobotC’s odd structure, but normally .h files will have this in them:

#ifndef HEADER_FILE
#define HEADER_FILE

the entire header file file

#endif

The whole point of that is so that you don’t try to define things repeatedly when you include the same file multiple times.

Yikes. So you’re trying to make everything into global variables? That would be undoing a good chunk of the point of functions. Most likely this file hasn’t been included properly. Maybe one file is missing its inclusion of Variables.c?

First, RobotC has somehow contrieved way of handling includes. While the ifdef include guards would work, they aren’t really needed or helpful with RobotC, since RobotC won’t process the files again anyway, while it warns about the repeated includes.

So if you see “Duplicate variable declaration of ‘DriveKi’”, it means the variable is really defined at multiple places - go search for it. If you need to make a variable available to multiple source files, you can declare it first and only define it at one place. I guess that is what you’re trying to do with your variables.c file. The proper structure might better look like:

Variables**.h**


extern int DriveKi; // no value assigned, this is just a declaration with "extern", no storage allocated

DriveBase**.c**


#include "Variables.h"
float DriveKi = DRIVE_KI_CONSTANT; // actual definition which allocates memory for the variable and initializes it

But as @callen pointed out, most of those variables should better be kept local to the usage site. For the DriveKi, I don’t think other files need to have access to the value. The only globals that I’d expect shared accross files would be things like lift PID target, that would be modified by your joystick code and utilized by your lift PID code.

That gets us back to your motivation for extracting the variables to a separate file. My best guess is that you wanted them concentrated at one place for easy access to the initial value, e.g. for PID tuning. But that would be better served by a different common pattern, a header file with definitions. Such as:

Config.h:


#define DRIVE_KI_CONSTANT 0.03
#define DRIVE_KP_CONSTANT 1.5
#define DEIVE_KD_CONSTANT 0.5

DriveBase.c


float  DriveKi = DRIVE_KI_CONSTANT;
float  DriveKp DRIVE_KP_CONSTANT;
float  DriveKd DEIVE_KD_CONSTANT;

@callen, @nenik Sorry for the late reply. Thank you. I have my variables all in different local files now. I just wanted easy access to tune Kp, Ki, Kd etc. Another thing, now when I compile the MAIN.C code, I get no errors. But when I compile the DRIVEBASE.C and LIFT.C, I get errors:

File “C:\Users\USERNAME\Desktop\VEX TP 2018-19\DriveBase.c” compiled on May 07 2018 06:55:00
Warning:Unreferenced task ‘GyroPID’
Error:Undefined variable ‘Gyro’. ‘short’ assumed.
Error:Undefined variable ‘RightDrive1’. ‘short’ assumed.
Error:Undefined variable ‘RightDrive2’. ‘short’ assumed.
Error:Undefined variable ‘LeftDrive1’. ‘short’ assumed.
Error:Undefined variable ‘LeftDrive2’. ‘short’ assumed.
Error:Undefined variable ‘LeftDriveEncoder’. ‘short’ assumed.
Error:Undefined variable ‘RightDriveEncoder’. ‘short’ assumed.

All these are motors and encoders but do I have to add motor configuration etc. to the drivebase files too?

You need to include what I would normally call main.h, but in RobotC’s implementation seems to be main.c instead. This is where RobotC places all the #pragma statements.

@callen, I do have a main.c which has motor configurations and has the #include “drivebase.c” in the main.c. Can I ignore the errors?

Just don’t try to compile any of those other files. RobotC has no notion of a project or even a compilation unit, so pressing compile on LIFT.C has a little chance of producing anything useful. Always switch to main.c before compilation, it will compile everything included.
I have even suggested to my team to rename everything to .h - if you’re in a .h file, RobotC UI disables the compile button, so you won’t try to compile it by a mistake.

Sure, but this is backward for the variables (probably needed for drivebase.c’s functions). drivebase.c is looking for a bunch of variables and doesn’t know where to find them. You need to tell drivebase.c where to find them. That’s what #include does. So you need #include main.h or whatever the RobotC version of that is within drivebase.c.

@nenik Thank you! Got it!

@callen Thank you too! I understand #include now!