Calling motors from Include Files

What is the best ‘pattern’ for declaring motors and calling those motors from include files? If you declare the motors in ‘main.cpp’:

// A global instance of vex::brain used for printing to the V5 brain screen
vex::brain       Brain;
vex::motor RightMotor(vex::PORT12,true);
vex::motor LeftMotor(vex::PORT1,false);

// Custom Function Include
#include "CustomCode.h"

Then try to call those motors from CustomCode.h, it generates the error 'use of undeclared identifier ‘LeftMotor’, (The following function previously worked in VEXcode Preview 2, but doesn’t work in Preview 3).

image
Is there a best practice for how to declare motors so their globally available across the include files, or do you have to code the functions to include the motors as parameters?

void customDriveForward(vex::motor RightMotor, vex::motor LeftMotor, double rot) {
    RightMotor.startRotateFor(rot, vex::rotationUnits::rev);
    LeftMotor.startRotateFor(rot, vex::rotationUnits::rev);
}

I am not too sure about VexCode but in Pros at least you can use extern and this is a rough idea of how to do it
___________ name: config.h
#ifdef CONFIG_H
#define CONFIG_H

extern “motor constructor”;

#endif


custom functions:

________________filename: customlib.h
#ifndef LIB_H
#define LIB_H

extern void f( int target);
#endif
______________file name example: customlib.cpp

#include “customlib.h”
#include “config.h”

void f(int target){
//code using local var target
}


Then you would include the header for the custom lib and config in pros

This would be correct, use extern.

btw PROS, VEXcode, and VEX Coding Studio all use the GCC compiler tool chain - not sure about RMS, so from a C/C++ point of view the language is the same.

see this

1 Like

The linter is displaying errors but that doesn’t mean the code will not compile.

The program that displays the errors as you write code only has a partial picture of how you have structured your code. It can follow the path of the include files but will not know about global variables or anything else defined in other source files you have. For your CustomCode.h it understands how to follow vex.h but will have no idea what RightMotor is as it’s not part of any included file. There’s not much we can do about this, it really is bad practice to have functions in header files, that’s not the purpose of a header, it’s unfortunate that has been the pattern that ROBOTC forced us to use.
This problem is not unique to VEXcode, linters often have problems with header files, they are usually not files that would be compiled directly and when analyzed out of context often show errors.

This is how I would structure the code, if you currently have this.

gbr_1

You can see the project builds successfully but the linter is showing errors.

gbr_2

restructured to this.
same result when building, but linter is happy.

In practice both the motor external declarations and function prototypes would/should be placed in a header, just use vex.h for simple programs, or create a new header for more complex ones.

vex.h
/*----------------------------------------------------------------------------*/
/*                                                                            */
/*    Module:       vex.h                                                     */
/*    Author:       Vex Robotics                                              */
/*    Created:      1 Feb 2019                                                */
/*    Description:  Default header for V5 projects                            */
/*                                                                            */
/*----------------------------------------------------------------------------*/
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "v5.h"
#include "v5_vcs.h"

// prototype for function
void  driveForwards( int32_t speed );

extern vex::motor LeftMotor;
extern vex::motor RightMotor;
main.cpp
/*----------------------------------------------------------------------------*/
/*                                                                            */
/*    Module:       main.cpp                                                  */
/*    Author:       james                                                     */
/*    Created:      Wed Apr 17 2019                                           */
/*    Description:  V5 project                                                */
/*                                                                            */
/*----------------------------------------------------------------------------*/
#include "vex.h"

using namespace vex;

// A global instance of vex::brain used for printing to the V5 brain screen
vex::brain       Brain;

// define your global instances of motors and other devices here
vex::motor       LeftMotor( vex:: PORT1 );
vex::motor       RightMotor( vex:: PORT10, true );

int main() {
    int count = 0;
   
    driveForwards( 25 );
    
    while(1) {
        Brain.Screen.printAt( 10, 50, "Hello V5 %d", count++ );
        // Allow other tasks to run
        this_thread::sleep_for(10);
    }
}
drive.cpp
#include "vex.h"

using namespace vex;

void
driveForwards( int32_t speed ) {
    LeftMotor.spin(fwd, speed, velocityUnits::rpm );
    RightMotor.spin(fwd, speed, velocityUnits::rpm );
}
3 Likes