Exiting a pid loop for distance.

I came across a problem when writing pid loops for autonomous. The loop runs fine and puts me on my mark, but i cant seem to figure out how to exit the loop to continue onto the next bit of code. I thought it would be a simple. if (error < 3) then break; . And while this works fine for exiting the code the bot coasts when we do this. Now what i think would work is a sort of timer that checks the condition then starts the timer, if the condition is met after the timer is up then it will “break” or exit the loop. Hopefully that fixes the problem.

ps. I would prefer not to attach my code but if needed i can create a mock up of the part i’m talking about.

Most people put their PID loop in a background task and then have a global variable for the target.

You can then set the target value you want and inside the auton look for the error to be within a nice range to know you have settled near there versus crossing right by it and oscillate around the target. What I mean is you won’t always get exactly to target, but near the target. But sometimes that first occurrence of being near the target is not good enough so let it settle down.

So usually what you want is not only is error low but previous error is also low. This ensures that the motor as stabilized.

while(abs(error)>threshold||abs(previousError)>threshold)

I think I have it figured out.
errorR = Right Side
errorL = Left side

if((abs(errorL) && abs(errorR) < Threshold) && time1 > 250)
break;
if((abs(errorL) && abs(errorR) > Threshold))
resetTimer(T1);

this way it will finish out the loop.(or settle)

to explain a little better if we have just the simple if (error < threshold) when it hits that threshold it exits and sometimes the bot needs to back track to stop itself. It sends negative numbers to the motors to stop dead in the spot, but it doesn’t oscillate the whole rig. this way we get crisp precise movement for distance.

What tabor is saying I have tried, the problem with that is error is calculated inside the loop, and to start off with error will = 0. Therefore it wont enter the loop at all.

Be careful with those expressions. if((abs(errorL) && abs(errorR) > Threshold)) may not be evaluated to what you expect. http://en.cppreference.com/w/cpp/language/operator_precedence

Another little trick is to put a “kick out” timer to just give up and move on. Sometimes it works, sometimes it doesn’t since you are out of expected position.

Making a function out of this operation is useful too. wait_for_stuff_to_happen() kind of function with a loop… You sometimes need to wait on the movement of multiple items at once.

Okay so to solve that you just calculate the error initially once? Either that or you use a do while loop? Or set a boolean to be true inside the loop and only allow exiting if you have looped once?

if((abs(errorL) && abs(errorR) > Threshold)) this doesn’t work. Your currently only checking if errorL does not equal 0.

if((abs(errorL) > threshold && abs(errorR) > Threshold)) is what you were looking for.

Your solution also only says that the code was running for a total of a quarter second and never deals with how long the error had been small. If you wanted a watchdog timer to time out if an error occurs than this would be okay but that is not the goal.

So what I ended up doing is:
if(abs(errorL) > 10 || abs(errorR) > 10)
resetTimer(T1);
at the end of the loop. Then the whole loop is running in:
while(time1(T1) < 1000)

Thanks for all of your help guys. :slight_smile: