In electronics, anything that only goes full-left or full-right, (or full-on, full-off, etc.) is known as bang-bang. Usually this introduces unacceptable noise, vibration or erratic behavior in circuits or actuators.
When I see that the 3PI sample line follower code only uses
set_motors(0,100);
and
set_motors(100,0);
and
set_motors(100,100);
…I am immediately suspicious that this control can’t be fast or smooth. Shutting down a high speed motor abruptly and shifting from stop to a high speed often can’t be a great idea.
I’m going to try three refinements. I’ll let you know how they work.
First, instead of only two possible states, I’ll divide the possible speeds into five instead of two. I think this will give finer, smoother control.
So the source would look like:
while(1)
{
unsigned int position = read_line(sensors,IR_EMITTERS_ON);
if (position < 1000) set_motors( 0,100); // too far left
else if(position < 1500) set_motors( 50,100); // a little to the left
else if(position < 2500) set_motors(100,100); // well centered
else if(position < 3000) set_motors(100, 50); // a little to the right
else set_motors(100, 0); // too far right
}
The second possibility is to divide the readings from zero to 4,000 into say 40 different increments so that the change in motor speed would be much less abrupt.
And thirdly, how about infinite control? Meaning, make the algorithm so that you just plug the 0 - 4,000 number into an equation that accurately adjusts both motors very finely.
My theory is that smaller, finer adjustments to motor speeds will allow the 3PI to react quicker and more smoothly to changes in sensor readings.
When this works, I’ll change the 100 to a constant so that I can gradually increase the constant until 3PI finds its maximum speed just under loss of control. Something like:
const int MAX = 100;
while(1)
{
unsigned int position = read_line(sensors,IR_EMITTERS_ON);
if (position < 1000) set_motors( 0, MAX); // too far left
else if(position < 1500) set_motors(MAX/2, MAX); // a little to the left
else if(position < 2500) set_motors(MAX, MAX); // well centered
else if(position < 3000) set_motors(MAX, MAX/2); // a little to the right
else set_motors(MAX, 0); // too far right
}
…then by just changing MAX, I can experiment easily with higher speeds.