Unofficial Response To: "Progressive Programming?"

  1. 8 months ago

    EvolvingJon

    6 Oct 2017 C/C++ Developer #2903
    Edited 8 months ago by EvolvingJon

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

    Hi, i am currently programming a chain bar bot and was wondering if there was anything like progressive programming?
    So say i was to press button 5d once and it would go to a certain setpoint, is there a way to have it go to a different setpoint the next time i press the button 5d? and if there is, is there a way to refresh it to go back to the initial setpoint? Thanks for your help!

    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!

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

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

  3. @NinjaApple02 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.

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

  5. EvolvingJon

    7 Oct 2017 C/C++ Developer #2903

    @Barin The code given by @EvolvingJon is RobotC code.

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

    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.

  6. CHINESEISASIAN

    7 Oct 2017 Answer Southington Connecticut 195a

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

  7. CHINESEISASIAN

    8 Oct 2017 Southington Connecticut 195a

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

  8. EvolvingJon

    8 Oct 2017 C/C++ Developer #2903

    @CHINESEISASIAN 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.

  9. CHINESEISASIAN

    8 Oct 2017 Southington Connecticut 195a

    @EvolvingJon 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!

  10. CHINESEISASIAN

    11 Oct 2017 Southington Connecticut 195a

    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 ();
    
    		}
    	}
 

or Sign Up to reply!