Hi all. We are having difficulties with a bit of code. Here is what we are trying to do:
When we push a button on the controller the code will execute a “dump” command. This command would run the lift up to a set height, then at a certain height it would continue to run the lift up WHILE also opening the claw. The intention being we will then have momentum while the claws open to give the stars a bit more chance to get to the far zone. We can do this manually driving, but we want it to be a button that we push to auto execute the entire dump command. It would then stop both the lift and claw motors at the appropriate height, where the driver would then take over again…run the lift down and continue on collecting objects.
We are using a potentiometer to track the angle of the lift. We know that we want the lift to run up at full power until the potentiometer reads a value of approximately 1450. At that point, we want the lift to CONTINUE going up but ALSO run the claws open to execute a dump. At a value of 1950 we are at our maximum safe height we do not want to pass (for tipping reasons) and all lift and claw motors would stop. Again, ALL of this would self execute with the single push of a button.
We are not master coders. We have tried several variations to get this to work and can’t seem to figure it out. Our last effort used “tasks”, which I will quote below. It did not execute properly.
Also, we want to be able to still drive while running this command (backup while pressing this dump command to save time), so it can’t “override” other code.
Any thoughts?
task dump1()
{
while (SensorValue[liftpot] < 1450) //run the lift up and claws at low power to hold objects
{
motor[leftlift2] = 127;
motor[leftlift1] = 127;
motor[rightlift2] = 127;
motor[rightlift1] = 127;
motor[leftclaw] = 20;
motor[rightclaw] = 20;
}
}
task dump2()
{
while (SensorValue[liftpot] >= 1450 && SensorValue[liftpot] < 1950) //keep running the lift and open claws (to give momentum while dumping)
{
motor[leftlift2] = 127;
motor[leftlift1] = 127;
motor[rightlift2] = 127;
motor[rightlift1] = 127;
motor[leftclaw] = -127;
motor[rightclaw] = -127;
}
}
task dump3()
{
while (SensorValue[liftpot] >= 1950) //once we reach our "full height" stop all motors
{
motor[leftlift2] = 0;
motor[leftlift1] = 0;
motor[rightlift2] = 0;
motor[rightlift1] = 0;
motor[leftclaw] = 0;
motor[rightclaw] = 0;
}
}
THE BELOW BIT WOULD BE IN USER CONTROL:
if (vexRT[Btn7D] == 1)
{
startTask (dump1);
startTask (dump2);
startTask (dump3);
}
It would probably be better just to take the code from the tasks into the user control loops, and switch the while statements to if statements. If you use a task, it’ll switch between the tasks every 25ms or so, and it’ll be more accurate, and more efficient if you just put all of those while loops as conditionals within the User Control Loop. Not that you cannot do it with tasks, but it is ill-advised.
I’m not sure if I understand. We tried doing it in the user control loop originally, but that didn’t work. The reason seems to be because we push a button to activate the “auto dump” command, but we also have other buttons that manually run the lift and the claw separately…and those buttons are not being pressed. So therefore we have one bit of code telling the robot to “dump”, but then the next cpu cycle it checks if we are pressing our regular lift and claw buttons, which we are not…so it instantly turns the motors off.
Not sure if that makes sense…basically we have two conflicting statements at once…and we don’t know how to rectify that properly while still maintaining the functionality of the claw and lift buttons AND the “auto dump” code.
I encourage teams to use functions to handle different actuators at the same time. Each function will let the calling program know if the motors are finished moving.
Actuator positions are declared in the global scope and then the functions are called to move the motors to those positions. Once all of the actuators return false, meaning they are at the desired position, then the autonomous task continues on to the next step.
You can use any version of PID (P, PI) to calculate the motor speed and direction.
Here is a rough draft:
#pragma config(Sensor, dgtl1, QuadLift, sensorQuadEncoder)
#pragma config(Sensor, dgtl3, QuadClaw, sensorQuadEncoder)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
long newLiftPosition, newClawPosition, newDrivePosition;
char MoveArm(){
if(SensorValue(QuadLift) != newLiftPosition)
{
//move lift motors
return 1; //Tell program the lift is still moving.
}
//stop lift motors
return 0; //Tell program the lift is done moving
}
char MoveClaw(){
if(SensorValue(QuadClaw) != newClawPosition)
{
//move claw motors
return 1; //Tell program the claw is still moving.
}
//stop claw motors
return 0; //Tell program th claw is done moving
}
task autonomous()
{
//Step 1 - close claw
newClawPosition = 80;
newLiftPosition = 0;
while(MoveClaw() || MoveArm()){
wait1Msec(50);
}
//Step 2 - lift and keep claw closed
newClawPosition = 80;
newLiftPosition = 350;
while(MoveClaw() || MoveArm()){
wait1Msec(50);
}
//Step 2 - keep lift up and open claw
newClawPosition = 30;
newLiftPosition = 350;
while(MoveClaw() || MoveArm()){
wait1Msec(250);
}
}
bool isDumping = false;
THE BELOW BIT WOULD BE IN THE USER CONTROL WHILE LOOP:
if (vexRT[Btn7D] == 1)
{
while(vexRT[Btn7D] == 1);
isDumping = true;
}
if(isDumping)
{
if (SensorValue[liftpot] < 1450) //run the lift up and claws at low power to hold objects
{
motor[leftlift2] = 127;
motor[leftlift1] = 127;
motor[rightlift2] = 127;
motor[rightlift1] = 127;
motor[leftclaw] = 20;
motor[rightclaw] = 20;
}
if (SensorValue[liftpot] >= 1450 && SensorValue[liftpot] < 1950)
{
//keep running the lift and open claws (to give momentum while dumping)
motor[leftlift2] = 127;
motor[leftlift1] = 127;
motor[rightlift2] = 127;
motor[rightlift1] = 127;
motor[leftclaw] = -127;
motor[rightclaw] = -127;
}
if (SensorValue[liftpot] >= 1950) //once we reach our "full height" stop all motors
{
motor[leftlift2] = 0;
motor[leftlift1] = 0;
motor[rightlift2] = 0;
motor[rightlift1] = 0;
motor[leftclaw] = 0;
motor[rightclaw] = 0;
isDumping = false;
//thus getting you out of the if loop while the rest of the drive while loop is continuing
}
}
This is what I was trying to get across. Hope this helps. I hope that answers the question.
I think I understand what you are saying with that code. We will give that a shot this evening. My only question is; will we be able to drive while the “dump” code is executing? I don’t think we will, because we will be locked in that loop…right? We want to be able to be backing up while we press the dump command.
We are a bit novice to “advanced” programming. I’m not sure if I understand what this code is doing. I will try to parse through it later and give it a shot. (for example, we have never even used the “char” command…probably should be embarrassed about that) But thank you for the input!
Yep! That’s the beauty of keeping everything within the same while loop! As long as you place everything under the same while loop, and use if statements, you will never be “locked” into a single loop. And actually, in practice, I believe (emphasis on believe), my and @Pete 's code will work the same way. He just uses functions to send speeds to the lift - which is the correct thing to do - and also uses functions handle my version of the isDumping boolean variable.