RobotC Code Help

Hi I am trying to create a program that will move an arm to a certain point using a potentiometer and have the program set to when the button is pressed and while the potentiometer is less than the target angle move the motor. I want to do this while still being able to have the functionality of the other parts of my robot like the drive etc. but whenever I test this the function will work but I am unable to move the other parts of the robot…pls help thanks!
My code looks like this:

void lift()
{
if(VexRT[Btn5U]==1)
{
while(SensorValue[pot]<100)
{
motor1=127;
}
}
}

while(1==1)
{
lift();
drive();
intake();
}

What is happening in your code is that when it gets to lift(); the programme gets trapped in the while(SensorValue[pot]<100) loop.

I haven’t coded in a while and am not sure if this will fix the issue, but you might want to try this:


void lift()
{
     if((VexRT[Btn5U]==1)&&(SensorValue[pot]<100))
     {
          motor1=127;
     }
}

while(1==1)
{
     lift();
     drive();
     intake();
}

If this dosen’t fix the issue, you might want to look into using tasks to allow multiple parts of the robot to run simultaneously.

No, @rxian , that won’t work and the if statement behaves very differently than intended in the OP.

You have a couple options. Coding it the way you’re coding it, you would want to add a delay into lift()'s while loop and make tasks out of all three: lift(), drive(), and intake(). An alternative would be to do all these things together within the main while(1==1){} statement, using an if statement to start the loop (button press) and an if statement to turn off the motor (if the pot reaches where you want).

Also, how do you stop your motor when it gets where you want it? I don’t see anything ever setting its value to 0.

When i test it out the motor seems to stop without having to add a program for a stop

Can you post the code for the other two functions?

The way that I would do it would be to have an if statement and a boolean. If the boolean is true, it would allow you to control that part of the motor and if the boolean is false, it would move itself.


void setDrive(int left, int right) {
   motor[right] = right;
   motor[left] = left;
}

void setArm(int speed) {
   motor[arm] = speed;
}

int buttonToPower(int upChannel, int downChannel, int power) {
   return vexRT[upChannel] ? power : vexRT[downChannel] ? -power : 0;
}

bool move(int position) {
   if (SensorValue[pot] < position) {
      setArm(127);
      return false;
   } else {
      return true;
   }

task main() {
   bool moveArm = true;
   while (true) {

      setDrive(vexRT[Ch3], vexRT[Ch4]);

      if (moveArm) {
         setArm(buttonToPower(Btn5U, Btn5D, 127));
         moveArm = !vexRT[Btn7U];
      } else {
         moveArm = moveArm(100);
      }
   }
}

As you can see, as long as Btn7U is not pressed, moveArm will be true and you can manually control the robot. When you press Btn7U, control goes to the moveArm function, stopping you from being able to move the arm. However the setDrive function remains untouched. When the potentiometer reaches the position inputted, control is returned back to the driver.

Using tasks for something this simple is outright lazy.

This is overly complicated to accomplish what was requested in the OP, but it does look sound upon cursory inspection.

The simple approach:

void lift() {
  static bool enabled = false; //Not sure if this works in RobotC, but this would be my preferred approach if using standard C

  if (VexRT[Btn5U]) {
    enabled = true;
  }

  if (enabled) {
    if (SensorValue[pot] < 100) {
      motor[motor1]=127;
    } else {
      motor[motor1] = 0;
      enabled = false;
    }
  }
}

task main() {
  while (true) {
    lift();
    drive();
    intake();

    delay(10); //Good practice
  }
}

If the above code does not work, use this instead:

bool liftEnabled = false;
void lift() {
  if (VexRT[Btn5U]) {
    liftEnabled = true;
  }

  if (liftEnabled) {
    if (SensorValue[pot] < 100) {
      motor[motor1]=127;
    } else {
      motor[motor1] = 0;
      liftEnabled = false;
    }
  }
}

task main() {
  while (true) {
    lift();
    drive();
    intake();

    delay(10); //Good practice
  }
}

I use this approach in my own code for locking the base and for lowering the catapult to just above firing so I know that it works. I can see why you think that this is overly complicated but it does have the advantage of keeping all the functions generic and keeps the specific buttons in the main task. If I want to change the button mapping, I can find it in the main task, not in the hundreds of lines in the header files.

I agree. That’s why I suggested using if-then statements. I’m someone who has regularly commented here about not needing tasks when people have asked about tasks in RobotC Graphical.

Not sure I’d call that the simple approach, though. This does the same thing:

void lift() {
   if (SensorValue[pot] >= 100) {
      motor[motor1]=0;
   }
   else if (VexRT[Btn5U]) {
      motor[motor1] = 127;
   }
}

But I don’t think your code will work, nor do I think mine will. I don’t think any of us can fix it yet. Why does motor1 ever stop? I don’t see any code saying motor[motor1]=0; in the original post. So that must be hidden inside drive() or intake(), even if not obvious, right? If that is the case, as soon as we remove the while loop to let other things operate, that 0 motor1 is being given somewhere should interfere with the 127 we’re passing to it. That’s why I asked about the rest of the code.

Yes, that is something I like. I prefer to see all the assignment of buttons in one place. That is why I suggested putting this in main() with if-then statements. Of course, once I’ve done that with code that only needs a single such statement with two options, I’m not sure it even warrants its own function. Just comment it well. But you could comment beside the function call to identify what buttons it uses, too, which would let you know about all of them in one spot.