Object oriented like functions in RobotC

Hello all,
So I was going through my code to clean it up with more object oriented functions. I started with the the function I have for reading the RPM of the flywheels. Below is the basic structure of my my entire program with the complete readLaunchRPM function.

#pragma config(Sensor, dgtl1,  launchRE,       sensorQuadEncoder)
#pragma config(Sensor, dgtl3,  launchLE,       sensorQuadEncoder)
#pragma config(Motor,  port2,           LaunchL,       tmotorVex393HighSpeed_MC29, openLoop)
#pragma config(Motor,  port3,           LaunchR,       tmotorVex393TurboSpeed_MC29, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

#pragma platform(VEX)

//Competition Control and Duration Settings
#pragma competitionControl(Competition)
#pragma autonomousDuration(20)
#pragma userControlDuration(120)

#include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!

int RPMR;
int RPML;

//----------returning functions first decleration--------------//
float readLaunchRPM (int RPML, int RPMR);

void pre_auton()
{
	
}

task autonomous()
{
	// autonomous are here
}

task usercontrol()
{

	while (true)
	{
		// PID Switch cases and driver control are here

		//-----------calculate RPM's in driver control------------//
		wait1Msec(20);

		readLaunchRPM(RPML, RPMR);


		// display RPM's on the LCD
		clearLCDLine(0);
		displayLCDString(0, 1, "L: ");
		displayLCDNumber(0, 3, RPML);// 3
		displayLCDString(0, 8, "R: ");
		displayLCDNumber(0, 11, RPMR); // 11

		// Reset encoders
		ResetLaunch();
	}
}

typedef struct
{
	int L;
	int R;
	int AVGL;
	int AVGR;
} RPMStruct;

float readLaunchRPM (int RPML, int RPMR, RPMStruct RPM)
{
	float newReadingL;
	float oldReadingL;
	float checkDiffL;
	float newReadingR;
	float oldReadingR;
	float checkDiffR;
	int avgDiffL;
	int avgDiffR;

	oldReadingR = SensorValue[launchRE];
	oldReadingL = SensorValue[launchLE];
	wait1Msec(20);

	newReadingR = SensorValue[launchRE];
	newReadingL = SensorValue[launchLE];

	checkDiffR = newReadingR - oldReadingR; // target is 288
	checkDiffL = newReadingL - oldReadingL; // target is 288

	avgDiffR = checkDiffR * 0.2 + avgDiffR * 0.8;
	avgDiffL = checkDiffL * 0.2 + avgDiffL * 0.8;

	RPMR = (avgDiffR / 7.6) * 60;
	RPML = (avgDiffL / 7.6) * 60;

	SensorValue[launchLE] = 0;
	SensorValue[launchRE] = 0;

	RPM.L = RPML;
	RPM.R = RPMR;
	RPM.AVGR = avgDiffR;
	RPM.AVGL = avgDiffL;

	return RPM;
}

I thought RobotC could work with first and second declarations of functions. But when I try out the code I get this error:

**Error**:No body declared for referenced procedure 'readLaunchRPM'
**Error**:No body defined for procedure prototype 'readLaunchRPM'

I do not know why this is coming up. Does RobotC only run from the top of the code to the bottom and then end?
Thanks in advance.

You have a bunch of issues. You declare the prototype as


float readLaunchRPM (int RPML, int RPMR);

But the function is then defined as


float readLaunchRPM (int RPML, int RPMR, RPMStruct RPM)

and want’s you to pass a RPMStruct

but you then try and return a structure from that function where you told the compiler it was going to return a float.

perhaps this is what you were trying to do.

#pragma config(Sensor, dgtl1,  launchRE,       sensorQuadEncoder)
#pragma config(Sensor, dgtl3,  launchLE,       sensorQuadEncoder)
#pragma config(Motor,  port2,           LaunchL,       tmotorVex393HighSpeed_MC29, openLoop)
#pragma config(Motor,  port3,           LaunchR,       tmotorVex393TurboSpeed_MC29, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

#pragma platform(VEX)

//Competition Control and Duration Settings
#pragma competitionControl(Competition)
#pragma autonomousDuration(20)
#pragma userControlDuration(120)

#include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!

int RPMR;
int RPML;

// we need this function
void ResetLaunch() {};

//----------returning functions first decleration--------------//
void readLaunchRPM (int *RPML, int *RPMR);

void pre_auton()
{
  
}

task autonomous()
{
  // autonomous are here
}

task usercontrol()
{

  while (true)
  {
    // PID Switch cases and driver control are here

    //-----------calculate RPM's in driver control------------//
    wait1Msec(20);

    readLaunchRPM( &RPML, &RPMR);


    // display RPM's on the LCD
    clearLCDLine(0);
    displayLCDString(0, 1, "L: ");
    displayLCDNumber(0, 3, RPML);// 3
    displayLCDString(0, 8, "R: ");
    displayLCDNumber(0, 11, RPMR); // 11

    // Reset encoders
    ResetLaunch();
  }
}

void readLaunchRPM (int *RPML, int *RPMR )
{
  float newReadingL;
  float oldReadingL;
  float checkDiffL;
  float newReadingR;
  float oldReadingR;
  float checkDiffR;
  int avgDiffL;
  int avgDiffR;

  oldReadingR = SensorValue[launchRE];
  oldReadingL = SensorValue[launchLE];
  wait1Msec(20);

  newReadingR = SensorValue[launchRE];
  newReadingL = SensorValue[launchLE];

  checkDiffR = newReadingR - oldReadingR; // target is 288
  checkDiffL = newReadingL - oldReadingL; // target is 288

  avgDiffR = checkDiffR * 0.2 + avgDiffR * 0.8;
  avgDiffL = checkDiffL * 0.2 + avgDiffL * 0.8;

  *RPMR = (avgDiffR / 7.6) * 60;
  *RPML = (avgDiffL / 7.6) * 60;

  SensorValue[launchLE] = 0;
  SensorValue[launchRE] = 0;

  return;
}

So, what is the function of the “*” in the program, is it a replacement for the struct? Also at the end of the readLaunchRPM function it is not returning any value, in the while(true) loop for driver control will it be receiving the new calculations?

I am passing the variables (RPML and RPMR) by reference, that is, I’m passing “pointers” to the variables, this is one way of allowing a function to return more than one value. I didn’t really see what you were trying to achieve with the structure so I just removed it. I was only trying to answer your original question of creating a prototype for a function that is defined after it is first called.

The struct was supposed to help pass out the two different RPM’s in one function. And just to make sure I am getting this right, this code shows me a way of passing out variables in a “void” function in c. Cool, I have learned something new today:). Thanks J. Pearman.

There are lots of useful things you can use pointers for. Here are some examples of using pointers to structures.

typedef struct
{
    int L;
    int R;
    int AVGL;
    int AVGR;
} RPMStruct;

// A function that takes a pointer to a struct and updates its values
void MyFunction( RPMStruct *rpm )
{
    rpm->L = 1;
    rpm->R = 2;
    rpm->AVGL = 3;
    rpm->AVGR = 4;
}

// A function that returns a pointer to a structure
RPMStruct *MyFunction_2()
{
    static  RPMStruct  rpm;
    rpm.L    = 5;
    rpm.R    = 6;
    rpm.AVGL = 7;
    rpm.AVGR = 8;
    
    return( rpm );
}

// I will make this global to aid in debugging
RPMStruct   MyRpm;

task main()
{
    MyRpm.L    = 10;
    MyRpm.R    = 11;
    MyRpm.AVGL = 12;
    MyRpm.AVGR = 13;
    
    // Se we can see them in debug window
    wait1Msec(1000);
    
    // Pass pointer to struct
    MyFunction( &MyRpm );

    // Se we can see them in debug window
    wait1Msec(1000);

    // Get pointer to the static struct inside MyFunction_2
    RPMStruct  *r;
    r = MyFunction_2();
    
    // r now has useful values, we can copy them
    MyRpm.L    = r->L;
    MyRpm.R    = r->R;
    MyRpm.AVGL = r->AVGL;
    MyRpm.AVGR = r->AVGR;
    
    while(1) wait1Msec(10);
}

Ok, I think i get it. Thanks again.:slight_smile: