# PID line follow with three sensors in Not eXactly C

I'm currently working on a line-following robot which uses three sensors to follow a black line. The sensors are pretty much in line and right next to each other.

Right now, I'm doing a simple line follow: if on the line go forward, otherwise turn left or right to regain the line. This means that the robot is wiggling along the line most of the time.

I'm looking for a better way for this robot to follow the line using three sensors. The program I'm writing is in Not eXactly C code. I'm trying to get the robot to utilize the power of PID control, but I'm not sure how one would go about writing a three-sensor PID line-follower program in NXC.

• I'm looking for an answer that provides good, usable NXC code
– shea
Commented Jan 18, 2013 at 3:49

I dont use NXC, so I am hesitant to propose this as an answer, but I will comment that the sensors ARE linear - not binary. They measure dark, grey, and light - On, middle, off of line. You simply devise a scheme to get a unique #, and use that as the SetPoint to PID - works great. See Mindsensors light array for sample NXC code for their array. Adopt it to 3 sensors.

I don't know if this helps or not but is the scheme I use in RobotC; (higly shortened)

int LSA_GetAvg()
{
char value[8];
int som = 0;
int bits = 0;
for (int i=0;i<8;i++)
if (value[i] < 0x32)
{
som += ((8-i)*10);
bits++;
}
return som / bits;
}

main loop {

int avg = LSA_GetAvg();
printf("avg %d\n", avg);

if (avg != 0)
{
steering = S3Pid(Oval, avg, 45, elapsedTime); // 45 is our goal, set point
printf("Steer %d\n", steering);

motor[LEFT] = clipBAD((basePower - steering), -100, 100);
motor[RIGHT] = clipBAD((basePower + steering), -100, 100);
}
else
{
// stuff gone wrong, we lost the line, check packed bits=0xff for a crossing
PlaySound(soundBlip);
}

}


Edit: as I look at that OLD code - i see that is is not very optimum, and would work just fine with 3 binary sensors - just FYI.

I don't think traditional PID control is appropriate per se, since your sensors only provide a binary "is the line under me" signal; PID controls need to be able to calculate error (error = actual - desired). Also, you need motors that can adjust their speed instead of simply turning on and off.

One way to get PID control might be to increase the number of sensors from 3 to 9, with barely-overlapping sense area. That might get you a range of 17 values, 9 from sensors and 8 more in cases where 2 adjacent sensors are triggered. I'm not sure how many points you'll need to be able to measure in order for PID control to become effective.

A more abstract way to approach this would be to consider the wiggles-per-second to be the value controlled by the PID. In this case, the PID would control the maximum difference in speed between the two motors -- the maximum rate of turn. If your robot is wiggling to much, such a PID should cause it to turn in more gradual arcs. In this case, the correct target wiggles-per-second will depend on the radius of the tightest turn that the robot will have to make.