Pololu Robotics & Electronics
My account Comments or questions? About Pololu Contact Ordering information Distributors

Individual Sensor Reading


Hi guys,

I am interested in accessing the individual IR sensor readings from the 3pi robot. I understand that there is a ‘read_line(**)’ function, but I followed it through the main file in ‘line-follower-pid.cproj’ files and several include files but ended up only finding the prototype for it.

Is there a way to access the mV for each individual sensor? I have tried printing out sensor[0], and sensor[1], but they give me 0 mV on the printout. Attached is a sample snippet from the code of interest in .png. ‘Test’.c’ contains the entire code.

Is the read_line() function definition not accessible?

test.c (7.8 KB)



The read_line() function returns the calibrated sensor readings, and they will only have meaningful values if you have previously calibrated the sensors; since you are getting nothing but zero, I am guessing you have not performed the calibration step. You probably want the raw sensor readings, which you can access by calling read_line_sensors(). You can find out more about both functions in the 3pi Robot functions section of the Pololu AVR Library command reference. By the way, neither the calibrated nor raw sensor readings will have units of millivolts (where did you get that test.c example?).

The library source code is fully available on Github. The functions for reading the 3pi line sensors are just wrappers for the more general functions in the PololuQTRSensors part of the library. Also, note that the C functions you have been calling (the ones that start with extern "C") are wrappers for C++ methods that can found be lower in the file.

- Ben


Hi Ben,

Thanks for your response. I have looked all over the file ‘test.c’ (which I obtained from the ‘line_follower’ project in the pololu avr library in the atmega328p examples) for the definition of read_line(). I have searched this code, and all other related analog libraries, including the PololuQTRSensors library, and have never seen an actual implementation of read_sensors(). I may have easily missed it, but I looked for quite a while before I gave up. Anyways, I have managed to solve the issue and can now read individual sensors by playing with the code for hours on end. There’s not much rhyme or reason to this solution but it works.

You must run the ‘auto-calibration’ routine where the motors spin back and forth for a few seconds, and then one must call the read_line() subroutine afterward. The read_line() subroutine has something to do with ‘arming’ the sensor. After that, meaningful data populates the program by using the calibrated_value[i] array.

Hope this helps someone somehow.



My above post links to the source code for those functions; are you still not able to find them?

It also seems like you ignored my comments that it sounds like you should be reading the raw sensor values using the read_line_sensors() function. The function you are using now (read_line()) only makes sense if you have calibrated your sensors to the line, since the readings returned by the function are being scaled to range from the minimum to the maximum values measured during the calibration phase (and these calibration scale factors are essentially undefined until you have calibrated the sensors). The “auto-calibration” routine you are running is just one way of calibrating the sensors.

- Ben



I hope this is the right topic.

I would like to improve the line follower program.
At first the 3Pi should deal with the sharp turns. I don’t have too much experience in C programming and in the MCUs I hope there is an easier solution. I think the program should monitoring the sensors separately.
Here is the idea.

instructables.com/id/Robot-L … ngle-Turn/

According to the previous posts I should use this : read_line_sensors(sensor_values,IR_EMITTERS_ON).
Unfortunately I don’t understand how I should use this in a program. Where can I set which sensor I would like to read?

I hope you can understand.

If you have other idea please share!



You might be able to do something similar using the qtr_read_line command from our AVR Library. When you use this command the value of each sensor is stored in the array you specify, and if you just want to check a specific sensor, you can look at the index of the array that corresponds to that sensor. You might look at the example code from the"The Main Loop(s)" section of the “Maze Solving” example project in the 3pi Robot User’s Guide as an example. In this example, qtr_read_line is used to store the sensor values in an array called sensors, which is then used to determine which directions the current intersection goes. I suspect detecting and handling acute angle turns will be a bit more complicated than this example, but you might find it helpful to see how the individual sensors can be checked.



[code]#include <pololu/3pi.h>

int main()
unsigned int sensorValues[5];

	unsigned int sensor=sensorValues[0];


Here is a small code. I would like to see the values of the first sensor but I can see just 0. Should I calibrate before I get the values or there are problems with the code?


It looks like you are not initializing the line sensors. This can be done by using the pololu_3pi_init(unsigned int line_sensor_timeout) function. Please note that it is recommended that you set the timeout to be between 500 and 3000us. You can find more information about this function in the “3pi Robot Functions” section of the AVR Library Command Reference.

Calibrating the sensors is not necessary when reading the raw values (which it looks like your code is doing by using read_line_sensors()), but if you use any of the functions that depend on a calibrated value (such as read_line_sensors_calibrated() or read_line()), you should calibrate.



[code]while(1 == 1)

	unsigned int sensors[5];
	unsigned int linesensors[5];
	unsigned int position = read_line(linesensors, IR_EMITTERS_ON);	
	sensor0 = sensors[0];
	sensor2 = sensors[2];
	sensor4 = sensors[4];
	proportional = position - 2000;
	derivative = proportional - last_proportional;
	integral += proportional;
	last_proportional = proportional;
	power_difference = proportional/20 + integral/10000 + derivative*2/3;
    if (sensor0 > 1500 && sensor2 > 1500 && sensor4 < 1000)
	if (sensor2 < 600 && sensor0 < 600 && sensor4 < 600 && x==1)
	 if (z==1 && sensor0 > 800)
	if (sensor4 > 1500 && sensor2 > 1500 && sensor0 < 1000)
		 while (sensor2> 600)
		{ set_motors(30,30);

	if (sensor2 < 600 && sensor4 < 600 && sensor0 <600 && x == 2)
		while (sensor4 < 700)
		{ set_motors(50,-50);
	if (z==2 && sensor2 > 700)
	if (power_difference < 0 && x==0)
			set_motors(max+power_difference, max);
	if (power_difference > 0 && x==0)
			set_motors(max, max-power_difference);

I wrote a program but it doesn’t work. After it set the 30,30 motor speed there is no any respond. The robot just goes straight. I tested the parts and it should work. Probably this is not the best program but it should work I think. I can’t see what the problem is with the code.


Is that your entire code? If so, it looks like you are still not initializing the sensors with the pololu_3pi_init(unsigned int line_sensor_timeout) function I mentioned in my last post. Could you try adding that and seeing if it fixes the problem? If not, I recommend simplifying your code until you get it working. Did you get the code you posted in your previous post working correctly? It looks like it should work if you initialize the sensors before your while loop.



It’s not the entire code. I solved the problem. It works fine but if I increase the speed above 100 this code is useless because cannot sense the line properly.


The 3pi should be capable of following a line faster than 100 (out of 255); if your robot loses the line when you increase the speed, you might need to adjust your PID coefficients in your code. If you want to continue increasing the speed of the robot and adjusting the PID values, this post by Ben has a lot of tips and suggestions that you might find helpful.