Unofficial Response To: "Progressive Programming?"

This is a response to the post made in the Official Tech Support Channel by @CHINESEISASIAN .

There are many ways that you could accomplish this, one way that you could go about this is to maintain a variable with your current iteration through a set point array (or use something like switch statements). This means that you just need to refer back to the variable to tell which action to take next with your program.

Here are 2 examples of this in code. Both untested but intended to show the concepts at work:
Using an array:

// We are going to assume that you have a PID controller position setup with
// a setpoint interface of some description. This is just an eg.
bool setArmControllerSetpoint(int setPointPos);

unsigned byte armIterationStep = 0; // Init Step var
int armIterationSetpoints[2] = {120, 130}; // 2 example Setpoints provided

bool Btn5DPressed = false;
bool Btn5UPressed = false;
bool result; // E.g. debug info as returned by setArmControllerSetpoint

// Main loop
while(true) {
    // We are going to be using something similar to a toggle switch here
    // to make sure we only accept each individual press.
    if(vexRT[Btn5D] && !Btn5DPressed) {
        Btn5DPressed = false; // Toggle Switch Code
        
        // Here we will set the setpoint to the controller to the setpoint that
        // corrosponds to the armIterationSetpoints array. 
        // If this is the first time you press the button, armIterationStep 
        // will be 0 so we will get the 1st element of armIterationSetpoints (which is 120).
        result = setArmControllerSetpoint(armIterationSetpoints[armIterationStep]);
        
        // Check that we sucessfully set the setpoint
        if(result)
            writeDebugStreamLine("Error setting setpoint for ARMPID with value: %d", armIterationSetpoints[armIterationStep]);
        
        // Then we increase armIterationStep so that next time we will use the 2nd element of the armIterationSetpoints array.
        armIterationStep++; // Add 1
    }
    // We will make it possible to press the button again once it has been released.
    else if(!vexRT[Btn5D] && Btn5DPressed) {
        Btn5DPressed = true;
    }
    // Reset button 
    if(vexRT[Btn5U] && !Btn5UPressed) {
        Btn5UPressed = true; // Toggle Switch Code
        
        // We reset armIterationStep to the default of 0
        armIterationStep = 0;
        
        // Will be 0 so we will get the 1st element of armIterationSetpoints (which is 120).
        result = setArmControllerSetpoint(armIterationSetpoints[armIterationStep]);
        
        // Check that we sucessfully set the setpoint
        if(result)
            writeDebugStreamLine("Error setting setpoint for ARMPID with value: %d", armIterationSetpoints[armIterationStep]);
    }
    else if(!vexRT[Btn5U] && Btn5UPressed) {
        Btn5UPressed = false;
    }
}

Using switch statements:

// We are going to assume that you have a PID controller position setup with
// a setpoint interface of some description. This is just an eg.
bool setArmControllerSetpoint(int setPointPos);

unsigned byte armIterationStep = 0; // Init Step var
bool Btn5DPressed = false;
bool Btn5UPressed = false;
bool result; // E.g. debug info as returned by setArmControllerSetpoint

const int DEFAULT_ARM_VALUE 120

/ Main loop
while(true) {
    // We are going to be using something similar to a toggle switch here
    // to make sure we only accept each individual press.
    if(vexRT[Btn5D] && !Btn5DPressed) {
        Btn5DPressed = true; // Toggle Switch Code
        
        // Setup a switch statement that will switch what this button does based
        // what iteration step it is on and choose what to run based on that.
        switch(armIterationStep)) {
            case 0: // First time
                result = setArmControllerSetpoint(120);
                break;
            case 1: // Second time
                result = setArmControllerSetpoint(130);
                break;
            // case 2,3,4,5,6 etc
            case default: // This will run if none of the other cases suit
                // In this e.g we reset the arm to its default value
                result = setArmControllerSetpoint(DEFAULT_ARM_VALUE);
                break; 
        }
        
        // Check that we sucessfully set the setpoint
        if(result)
            writeDebugStreamLine("Error setting setpoint for ARMPID with case ID: %d", armIterationSetup);
        
        // Then we increase armIterationStep so that next time we will use the 2nd switch case.
        armIterationStep++; // Add 1
    }
    // We will make it possible to press the button again once it has been released.
    else if(!vexRT[Btn5D] && Btn5DPressed) {
        Btn5DPressed = true;
    }
    // Reset button 
    if(vexRT[Btn5U] && !Btn5UPressed) {
        Btn5UPressed = true; // Toggle Switch Code
        
        // We reset armIterationStep to the default of 0
        armIterationStep = 0;
        
        // Reset to default value
        result = setArmControllerSetpoint(DEFAULT_ARM_VALUE);
        
        // Check that we sucessfully set the setpoint
        if(result)
            writeDebugStreamLine("Error setting setpoint for ARMPID with case ID: %d", armIterationSetup);
    }
    else if(!vexRT[Btn5U] && Btn5UPressed) {
        Btn5UPressed = false;
    }
}

In its simplest form the two programs above are just this pseudocode:

if someone presses Btn5D button:
    use the value that we have to tell us what to do
    Add 1 to the value so we do something different next time.
if someone presses the reset button (Btn5U):
    reset the value to 0
    use the value at 0 to tell us what to do (to reset position on the arm)

Best of luck!

This is really helpful! I was also wondering how to do this. Do you know how to do this in RobotC by any chance?

The code given by @EvolvingJon is RobotC code.

Oh, oops. I was looking at it on my phone and I didn’t recognize it on a phone.

It should be noted that it is completely untested RobotC code ;). I don’t even have a proper syntax-highlighting text editor let alone a copy of RobotC with me. Hopefully it illustrates the way you can go about getting this result though.

Thanks so much @EvolvingJon. I’ve been trying to figure out how to do this for a long time!

Also where would I put this. driver control? pre auton?

You would put it in driver control as that’s where you are receiving your your joystick inputs/states :). Similar to how you would put generic control code into your driver control loop.

okay thanks!

so its been going good but im getting 2 errors on the “bool setArmControllerSetpoint(int setPointPos);” heres a link to my code, I was wondering if you could let me know what Im doing wrong. The errors are on the bool statement mentioned and they say “Error:No body declared for referenced procedure ‘setArmControllerSetpoint’” and “Error:No body defined for procedure prototype ‘setArmControllerSetpoint’”.

#pragma config(Sensor, dgtl2,  enc1,           sensorRotation)
#pragma config(Sensor, dgtl3,  enc2,           sensorRotation)
#pragma config(Sensor, dgtl4,  encW,           sensorRotation)
#pragma config(Sensor, dgtl5,  encA,           sensorNone)
#pragma config(Motor,  port2,           arm,           tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port3,           claw,          tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port4,           lift1,         tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port5,           lift2,         tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port6,           left,          tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port7,            ,             tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port8,            ,             tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port9,           right,         tmotorVex393_MC29, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

#pragma platform(VEX2)
#pragma competitionControl(Competition)
#include "Vex_Competition_Includes.c"

const static int MAX_MOTOR_SPEED = 127;
const static int MIN_MOTOR_SPEED = -127;

struct PIDValues
{
	float kP;
	float kI;
	float kD;
	float error;
	float errorSum;
	float lastError;
	float errorD;
	float motorDumperOutput;
	int setpoint;
	int output;
};

// Init Step var
bool Btn5DPressed = false;
bool Btn5UPressed = false;
bool result; // E.g. debug info as returned by setArmControllerSetpoint
const int DEFAULT_ARM_VALUE=120;

struct PIDValues armPID;

void armUp () //pid for pokers
{
	armPID.error = armPID.setpoint - SensorValue[encA];
	armPID.errorSum +=armPID.error;
	armPID.errorD = armPID.error - armPID.lastError;
	armPID.lastError = armPID.error;

	armPID.output = armPID.kP * armPID.error + armPID.kI * armPID.errorSum + armPID.kD * armPID.errorD;

	armPID.output = armPID.output > MAX_MOTOR_SPEED ? MAX_MOTOR_SPEED  :  armPID.output;
	armPID.output = armPID.output < MIN_MOTOR_SPEED ? MIN_MOTOR_SPEED  :  armPID.output;

	/*	if(vexRT[Btn5U])
	{
	armPID.setpoint=180;
	}
	else if(vexRT[Btn6U])
	{
	armPID.setpoint=360;
	}
	else if (vexRT[Btn7L])
	{
	armPID.setpoint=0;
	}

	motor[arm]=armPID.output;*/
}

struct PIDValues liftPID;

void liftisbad()
{
	liftPID.error = liftPID.setpoint - SensorValue[encA];
	liftPID.errorSum +=liftPID.error;
	liftPID.errorD = liftPID.error - liftPID.lastError;
	liftPID.lastError = liftPID.error;

	liftPID.output = liftPID.kP * liftPID.error + liftPID.kI * liftPID.errorSum + liftPID.kD * liftPID.errorD;

	liftPID.output = liftPID.output > MAX_MOTOR_SPEED ? MAX_MOTOR_SPEED  :  liftPID.output;
	liftPID.output = liftPID.output < MIN_MOTOR_SPEED ? MIN_MOTOR_SPEED  :  liftPID.output;

	/*if(vexRT[Btn5D])
	{
	liftPID.setpoint=180;
	}
	else if(vexRT[Btn6D])
	{
	liftPID.setpoint=360;
	}
	else if (vexRT[Btn8L])
	{
	liftPID.setpoint=0;
	}*/
}

struct PIDValues drivePID;

void PID4Drive ()
{
	drivePID.error = drivePID.setpoint - SensorValue[encW];
	drivePID.errorSum +=drivePID.error;
	drivePID.errorD = drivePID.error - drivePID.lastError;
	drivePID.lastError = drivePID.error;

	drivePID.output = drivePID.kP * drivePID.error + drivePID.kI * drivePID.errorSum + drivePID.kD * drivePID.errorD;

	drivePID.output = drivePID.output > MAX_MOTOR_SPEED ? MAX_MOTOR_SPEED  :  drivePID.output;
	drivePID.output = drivePID.output < MIN_MOTOR_SPEED ? MIN_MOTOR_SPEED  :  drivePID.output;
}

int deg15 = 150;

int deg45 = 450;

int deg90 = 900;

int deg120 = 1200;

int deg150 = 1500;

int deg180 = 1800;

int deg360 = 3600;

int right1;

int left1;

void drivefwd (int p)
{
	motor[right]=p;
	motor[left]=p;

}

void armINT (int p)
{
	motor[arm]=p;
}

void pivot (int p)
{
	motor[left]=p;
	motor[right]=-p;
}

void lifter (int p)
{
	motor[lift1]=p;
	motor[lift2]=p;
}

void armMove (int p)
{
	motor[arm]=p;
}

	void pre_auton()
	{
		bStopTasksBetweenModes = true;
	}

	task autonomous()
	{
		if(SensorValue[encW]>4386)
		{
			drivefwd(127);
		}
		drivefwd(0);
		wait1Msec(100);
	}


	void drive()
	{                         //This is for the tank drive
		int right=vexRT[Ch2];
		int left=vexRT[Ch3];

		motor[left]=left;
		motor[right]=right;

		/*left= vexRT[Ch3] + vexRT[Ch1];
		right= vexRT[Ch3] - vexRT[Ch1];

		motor[leftB]=left;
		motor[leftF]=left;
		motor[rightB]=right;
		motor[rightF]=right;*/

		//motor[left]=vexRT[Ch4]+vexRT[Ch3];
		//motor[right]=vexRT[Ch4]-vexRT[Ch3];
	}

	bool setArmControllerSetpoint(int setPointPos);

	void armer()
	{

		unsigned byte armIterationStep = 0;
		
		if(vexRT[Btn5D] && !Btn5DPressed)
		{
			Btn5DPressed = true; 
			switch(armIterationStep)
			{
			case 0:
				armPID.setpoint = 120;
				break;
			case 1:
				armPID.setpoint = 130;
				break;
			case 2:
				armPID.setpoint = 150;
				break;

			default: 
				result = setArmControllerSetpoint(DEFAULT_ARM_VALUE);
				break;
			}
			if(result)
				writeDebugStreamLine("Error setting setpoint for ARMPID with case ID: %d", armIterationStep);

			armIterationStep++; 
		}
		else if(!vexRT[Btn5D] && Btn5DPressed) {
			Btn5DPressed = true;
		}

		if(vexRT[Btn5U] && !Btn5UPressed) {
			Btn5UPressed = true; 

			armIterationStep = 0;

			
			result = setArmControllerSetpoint(DEFAULT_ARM_VALUE);

			
			if(result)
				writeDebugStreamLine("Error setting setpoint for ARMPID with case ID: %d", armIterationStep);
		}
		else if(!vexRT[Btn5U] && Btn5UPressed) {
			Btn5UPressed = false;
		}
	}

	task usercontrol()
	{

		SensorType[in8] = sensorNone;
		wait1Msec(1000);
		SensorType[in8] = sensorGyro;
		wait1Msec(2000);


		armPID.kP = 1;
		armPID.kI = 0;
		armPID.kD = 1;
		armPID.setpoint = 0;



		while (true)
		{
			drive();
			armUp();
			liftisbad();
			PID4Drive();
			armer ();

		}
	}