PID line Follower

I made a line follower robot using PID algorithm. I read QTR-8A with 8 channel ADC and calibrate sensors for white line on black base. But i have a problem. My robot is vibratintg on a straight road or when it is turning curves. It turns curves perfectly but it is vibrating… Can you help me about this vibrating problem?


It sounds like it might just be a problem with the tuning of your PID constants. Also, I notice that don’t seem to be using your constant Kd anywhere and are instead using an effective Kd of 1.

- Ben

Sorry for wrong code which Kp is not used. I edited the code. I changed my Kp value to 1 and robot is overshooting line on curves. If i give a value more than 5 my robot is not overshooting line but it is vibrating. I will post a video here tomorrow because all stuff about robot is in my office computer.
What do you say about my “calibrate();” algorithm? Do you think it works fine? I am reading sensor array only with IR emitters on. If you offer me reading sensors by pulsing IR emitters on-off like your 3pi robot can you give an example of code? Thanks!

Your code is somewhat difficult to read, but it looks as if your calibration routine is being done right. The one thing I can’t tell is how much time the calibration takes. Note that it is very important that all eight sensors be exposed to both the line and the course background during the calibration phase. Otherwise, you will have improperly calibrated sensors and will be dealing with bad data. You probably don’t need to worry about calibrating for ambient IR by reading with the emitters off, especially if you avoid running on courses with a lot of varying ambient IR (such as letting direct sunlight from a window fall across a part of the course). A better solution would probably just be to put some sort of shield around the sensors that keeps out ambient light.

As I said, it seems like your problems are due to poorly tuned PID constants. You will need to play around with Kp and Kd until you get the results you’re hoping for. Note that optimal Kp and Kd will also depend on your maximum speed and on the nature of the course itself (material, sharpness of the turns, etc). For line following, my experience is that you don’t need to worry about Ki (the integral term can be zero). I suggest you try getting it working okay with just Kp (make Kd zero) and then try adding in Kd and tweaking Kp until you get something that works as well as possible.

- Ben

Hi!. My robot is following line now. But i think it doesn’t remember which sensor last saw the line. My robot turns right going curves good but when it comes a left going curve it gets out of line.

Thank you for cleaning up your code. Unfortunately, the uncertainties I mentioned in my previous post still apply:

I think you need to find a way to better understand what is going on. Do you have an LCD on your robot or a way to connect it to a computer so you can print out data? Basically, you should calibrate your robot like normal, and then slowly slide it over the line while looking at the line position as reported by your code (the sensor variable) as well as the individual calibrated line sensor readings (the eight sense[ i ] variables). You want to make sure that all of your sensors are giving good readings, and you want to verify that the line position variable you’re using for your PID is for the most part monotonically increasing as the line moves from left to right beneath your sensors.

Also, you probably want to build into your code a routine that determines if the line is lost and remembers where you last saw the line. For example, if the sum of all of the line sensor readings falls below a certain threshold, you know that you lost the line to the left or right depending on where you last saw it:

int readLine(unsigned int *sensor_values)
	unsigned char i, on_line = 0;
	unsigned long avg; // this is for the weighted total, which is long
	                   // before division
	unsigned int sum; // this is for the denominator which is <= 64000
	static int last_value=0; // assume initially that the line is left.


	avg = 0;
	sum = 0;

	for(i=0;i<8;i++) {
		int value = sensor_values[i];

		// keep track of whether we see the line at all
		if(value > 200) {
			on_line = 1;
		// only average in values that are above a noise threshold
		if(value > 50) {
			avg += (long)(value) * (i * 1000);
			sum += value;

		// If it last read to the left of center, return 0.
		if(last_value < 8*1000/2)
			return 0;
		// If it last read to the right of center, return the max.
			return 8*1000;

	last_value = avg/sum;

	return last_value;

- Ben

Thanks for quick reply Ben. At calibration phase i move robot on line and push it back. My uC is PIC18F2550 @20MHz. I will try your code tomorrow and see how it works. I will upload here my robot’s video tomorrow. It will be a nice line follower when it finished. Thanks again…

Once again, I want to stress that you should print out some debugging statements either to an LCD or to a computer so you have a better idea of what’s going on. Also, I suggest you use an LED or some other signal to indicate when the calibration phase starts and when it ends so you get a better idea of how long it takes and so you can be sure that you have had time to expose all eight sensors to the line. Note that it’s very important that you do not pick up the robot during the calibration phase as this can expose the sensors to conditions that it will not experience on the course and lead to faulty calibration.

- Ben

Note that the simple process of pushing your robot by hand during calibration means you’re going to be accidentally pressing the sensors closer to the surface, which will change your readings. Far better would be to have your robot run itself forward and backward for few seconds, so it can calibrate using readings as realistic as possible.

(For fun, try a short script that just shows the current sensor values on the LCD repeatedly. Now push your robot a little bit; you’ll be surprised how much the values change just from your hand’s pressure.)

I am using a led to show calibrating starts and ends. You will see this in video. I calibrate robot by turning wheels up-down by hand. So i think sensors arent getting closer or far to surface.

Her is the video

I appreciate the video, but it’s hard to say what might be wrong. If you really want to troubleshoot the situation, you need to look at the sensor values your program is relying on. Ideally, you could log or stream the values while it’s running to get a better idea of what’s going on right when it leaves the line, or you could use LED feedback to indicate certain the presence of certain conditions you want to test for.

My suspicion is that your problem occurs when the sensors briefly lose the line on the curve. If you don’t take steps to detect the lost line and remember where you last saw it, you will just drive straight (your line position algorithm just returns the center sensor location when all sensors see the same thing) rather than correcting. It’s possible you also need to better tune your PID constants so that your robot reacts to curves fast enough to keep the sensors over the line.

- Ben

Hi! My robot is following line very good now. It was some hard but i made it at last. Thank you for your replies Ben and Lertulo.
Here is a video:

Thanks for the video. Was your problem fixed when you implemented detecting a lost line? You can definitely see some points in the video where all the sensors are briefly off the line. I’m glad to hear you got it working!

- Ben

I didnt implement your code because i was doing something like it already in my code.But there was a missing line in my read_sensor algorithm.
So thanks for your helps. Do you think the robot is following the line smooth? Speed is low in the video because of, power of batteries are low.

Yeah, it didn’t appear to wobble, but your turns had relatively large radii. You should make sure you try it out on a course that has turns as sharp as you expect to encounter in your competition.

- Ben

Here is a new video…