Program Issue

So the Void for the Button Up and the double target at the top of the loop aren’t responding. it is saying:
[clang] Cannot initialize a parameter of type ‘void (*)()’ with an lvalue of type ‘void (double)’: different number of parameters (0 vs 1)

Here is the code:

void tiltPID(double target)
{
double kp = 0.33;
double ki = 0.0005;
double kd = 0.2;

double proportion;
double totalError;
double integral;
double integralActiveZone = 90;
double integralPowerLimit = 50 / ki;
double derivative;
double finalPower;

double error = target;
double lastError = target;
vex::task::sleep(50);
while(abs(error) > 3){
error = target - Tilt.rotation(rotationUnits::deg);
error = target - Tilt2.rotation(rotationUnits::deg);
if(error == 0){
break;
}
proportion = kp * error;

if(abs(error) < integralActiveZone && error != 0){
totalError += error;
} 
else totalError = 0.0;

if(totalError > integralPowerLimit){
    totalError = integralPowerLimit;
}
if(totalError < -integralPowerLimit){
    totalError = integralPowerLimit;
}

integral = ki * totalError;

derivative = kd * (error - lastError);
lastError = error;

if(error == 0){
    derivative = 0;
}
finalPower = 0.5 * (proportion + integral + derivative)
Tilt.spin(fwd, finalPower, velocityUnits::pct);
Tilt2.spin(fwd,finalPower, velocityUnits::pct);
vex::task::sleep(20);

}
Tilt.stop();
Tilt2.stop();
}

void usercontrol(void) {
Controller1.ButtonUp.pressed(tiltPID);

Thank you

1 Like

The callback for pressed is a void type with no arguments. You defined it with 1 argument but there is no way to pass it that argument.

vex::controller::button.pressed

Function

Returns: void

Overloads:

pressed(void(*callback)(void))

Description

Sets the function to be called when the button is pressed.

Parameters:

Name Type Description
callback void(*)(void) A reference to a function.
1 Like

i’m confused. so do i change the void in the button press to this:
pressed(void(*callback)(void))

Or do i change the targets to the voids?

you cannot have an argument passed to the callback function. So it would need to be defined as follows:

void tiltPID(void) {
...
}

However, if you have a specific target in mind when using the button you can create an intermediary callback function that selects the value of target to past to tiltPID. Then tiltPID can have a argument and the intermediate function would look like this.

void buttonTilt(void) {
  tiltPID(50);
}
...
// example may not be accurate I don't use VEXCode
main () {
...
Controller1.ButtonUp.pressed(buttonTilt);
...
}

ed: for readability

3 Likes

so this will go around the whole pid loop or above the user control

it looks like you need a structure like:

void tiltPID(double target) {
// code here
}

void buttonTilt (void) {
  tiltPID(50);
}

void usercontrol (void) {
  Controller1.ButtonUp.pressed(buttonTilt); // this may be able to be called from pre_auton().

  while (1) {
    // code here
 }
}

void main (void) {
// standard competition template
}
3 Likes

NO ERRORS THANK YOU VERY MUCH !

2 Likes

the button isnt working now even though i called it

what is the problem then? No errors but the button doesnt respond to the command.

copy code here so we can see it.

If you want to test the callback is working you can replace the code in tiltPID() with

Controller1.Screen.clearScreen();

// Set the cursor (text starting point) to row 1, column 1
Controller1.Screen.setCursor(1,1);

// Print formatted on the first line
Controller1.Screen.print("In tiltPID!");

mostly copied form VCS example

If the text shows up on the controller then the problem is with the PID not the callback.

3 Likes

hold on. Let me find the code lol

void tiltPID(double target)
 {    
double kp = 0.33;     
double ki = 0.0005;
double kd = 0.2;
//need to tune the constants

double proportion;
double totalError;
double integral;
double integralActiveZone = 90;       //need to tune this with the constants
double integralPowerLimit = 50 / ki;  //this will probably need to be adjusted too, depending on the velocity units
double derivative;
double finalPower;

double error = target;
double lastError = target;
vex::task::sleep(50);
while(abs(error) > 3){    // will go until tray is within 3 degrees of target;
    error = target - Tilt.rotation(rotationUnits::deg);
    error = target - Tilt2.rotation(rotationUnits::deg);
    if(error == 0){
        break;
    }
    proportion = kp * error;
    
    if(abs(error) < integralActiveZone && error != 0){
    totalError += error;
    } 
    else totalError = 0.0;
    
    if(totalError > integralPowerLimit){
        totalError = integralPowerLimit;
    }
    if(totalError < -integralPowerLimit){
        totalError = integralPowerLimit;
    }

    integral = ki * totalError;
    
    derivative = kd * (error - lastError);
    lastError = error;
    
    if(error == 0){
        derivative = 0;
    }
    finalPower = 0.5 * (proportion + integral + derivative); //.5 is the gain; can adjust that as needed
    Tilt.spin(fwd, finalPower, velocityUnits::pct);
    Tilt2.spin(fwd,finalPower, velocityUnits::pct);
    vex::task::sleep(20);
}
Tilt.stop();
Tilt2.stop();
 }
 void buttonTilt (void) {
   tiltPID(100);
 }
 


void usercontrol(void) {
Controller1.ButtonUp.pressed(buttonTilt);



  int LISpeedPCT=100;
  int RISpeedPCT=100;
  int ArmSpeedPCT=100;
  int RightaSpeedPCT=100;
  int TiltSpeedPCT=50;
  


  while (true) {

     int RSpeed = Controller1.Axis2.position();
int LSpeed = Controller1.Axis3.position(); 
RR.spin(directionType::fwd, RSpeed, velocityUnits::pct);
LR.spin(directionType::fwd, LSpeed, velocityUnits::pct);

    
    
    if(Controller1.ButtonR1.pressing()) {
      RI.spin(directionType::fwd, RISpeedPCT, velocityUnits::pct);
      LI.spin(directionType::fwd, LISpeedPCT, velocityUnits::pct);

    }

    else if(Controller1.ButtonR2.pressing()) {
      RI.spin(directionType::rev, RISpeedPCT, velocityUnits::pct);
      LI.spin(directionType::rev, LISpeedPCT, velocityUnits::pct);
    }
    else{
      LI.stop(brakeType::hold);
      RI.stop(brakeType::hold);
    }

    if(Controller1.ButtonL1.pressing()) {
      Arm.spin(directionType::fwd, ArmSpeedPCT, velocityUnits::pct);
      Righta.spin(directionType::fwd, RightaSpeedPCT, velocityUnits::pct);
    }


    else if(Controller1.ButtonL2.pressing()) {
      Arm.spin(directionType::rev, ArmSpeedPCT, velocityUnits::pct);
      Righta.spin(directionType::rev, RightaSpeedPCT, velocityUnits::pct);
    }

    else{
      Arm.stop(brakeType::hold);
      Righta.stop(brakeType::hold);
    }

    if(Controller1.ButtonRight.pressing()) 
     { Tilt.spin(directionType::fwd, TiltSpeedPCT, velocityUnits::pct);
     Tilt2.spin(directionType::fwd, TiltSpeedPCT, velocityUnits::pct);
     RI.setStopping(coast);
     LI.setStopping(coast);
    }

    else if(Controller1.ButtonLeft.pressing()) {
      Tilt.spin(directionType::rev, TiltSpeedPCT, velocityUnits::pct);
      Tilt2.spin(directionType::rev, TiltSpeedPCT, velocityUnits::pct);
      RI.setStopping(coast);
     LI.setStopping(coast);
    }

    else{
      Tilt.stop(hold);
      Tilt2.stop(hold);
    }
   

 
  }

edit: mods added code tags, please try and use them in future.

will check in the morning when I have robot near me.

1 Like

ok thank you. We just want to see if we can make stacking a little bit easier.

bad idea to try and control motors from two different tasks (ie. main and an event handler)

4 Likes

event handler?

Im sorry i am new to programming.

The problem is that you have two different paths that Tilter.stop() will get called. While this may not be technically what happens, but when you press ButtonUp, essentially a task gets created to run the call-back (buttonTilt in this case). So now buttonTilt and usercontrol are running at the same time (really not true, but the OS provides the illusion this is the case). Now, buttonTilt is trying to move the Tilter motor. At the same time, un usercontrol, assuming neither ButtonLeft nor ButtonRight are being pressed, the control of that if statement falls thru to Tilt.stop().

TL;DR - You have two things fighting for control over issuing commands to the Tilt motor - one trying to move it while the other tries to stop it.

5 Likes

so i should put the button up command above the user control? and get rid of the manual if statements for the tilter?

My goal was to use the loop for a 9 stack but i can also self stack stuff

1 Like