Society of Robots  Robot Forum
Software => Software => Topic started by: EXCodeX on June 04, 2014, 12:28:15 PM

Hii!!
I am working on a fast grid solving robot using Arduino MEGA as the main controller. The robot has to follow black lines on a white surface and navigate through the grid. I have used an IR sensor array of 7 sensors to measure the displacement of the robot from the line. The sensors are arranged as follows
LEFT RIGHT
S1 S2 S3 S4 S5 S6 S7
First I tried to develop proportional algorithm for the line following.The error signal (displacement from the line) was calculated by multiplying sensor values with appropriate weight and taking the weighted summation. ( sensor output logic 1 when it is on black line)
Error = (S1xw3) + (S2 xw2) + ( S3 xw1) + (S4 xw0) + ( S5 x w1) + (S6 x w2) + (S7 x w3)
w0 was always set to 0 and other weights were adjusted.
then this error sigal was used to adjust PWM values of 2 motors.
Using this method ,I was able to achieve line following but still I observed that the response f the robot is not very smooth. (Tried with P, PI and PID controllers).
Is there any better method to implement P controller for a digital sensor array?(to generate error signal)
Your suggestions are really appreciated . Thanks :)

Looking at your equation  if two sensors see the line you get a big number that would make it look like the line is further to one side than it really is compared to when only one sensor sees the line. How is your sensor spacing compared to the line width? Can it disappear between the sensors?
Also, even with perfect sensor inputs, your input to your P controller is going to only have discrete input values so you only get discrete output values so it is going to be somewhat jerky. Some type of software filtering may be in order to smooth things out.

thank you very much for the reply
please take a look at the attached picture for a diagram of senor placement.
As you have mentioned, I also think the robot's response is poor due to the discrete error values generated by the equation. Could you please explain how to change this equation to obtain better response. (or better approach)
I went through the details of 3 pi robot which is available at
http://www.pololu.com/docs/0J21/all#7.c (http://www.pololu.com/docs/0J21/all#7.c)
in 3pi robot , they use only 5 sensors & achieved very smooth response
Could you suggest any other algorithm or hardware change to obtain smooth response like in 3pi ?
thanks ! :)

It appears that they are using analog sensors instead of digital sensors to get a more continuous signal.
Looking at your picture  can you be sure that you always have three sensors "on"? If you sometimes have three on and then the line shifts slightly and you only have two on, your weighted sum is going to make big nonmonotonic steps. Can you make your robot communicate the weighted sum of the sensor outputs? Put it over the line and slide it back and forth with the motors off to see what your position values are doing. If they increase (or decrease) in consistent steps as you slowly slide from one extreme to the other, then all you need to do is a little exponential filter to smooth it out. If the numbers jump up and down then you need a different algorithm to estimate the line center.
Step 1 would be to get the data on what the sensors are actually reading.
Step 2 is to design the algorithm to use the data from the sensors.

In 3 pi robot ,they use discharge time of a capacitor to detect white and black surfaces. But is there a big difference between 3pi sensor outputs & digital sensor outputs when we are working with pure black & White surface (because in 3 pi sensor panel , white surface gives very high discharge time and black surface gives very low discharge time).
I did the experiment yo mentioned & observed the value of weighted sum using serial monitor. the value was changed in in consistent steps as u mentioned. Can you please explain little bit about the use of exponential filter to smooth it out?
I found a code of fast line follwing robot & they have used a sensor array of 8 for the line following.
First the sensor values (digital) were saved in to an array & weighted sum was calculated.
sum = 1*Sensors[0]+2*Sensors[1]+4*Sensors[2]+8*Sensors[3]+16*Sensors[4]+32*Sensors[5]+64*Sensors[6]+128*Sensors[7]
then the error was calculated as follows
Count=Sensors[0]+Sensors[1]+Sensors[2]+Sensors[3]+Sensors[4]+Sensors[5]+Sensors[6]+Sensors[7];
double error =((sum&0b10000000)/128)*4+((sum&0b01000000)/64)*3+((sum&0b00100000)/32)*2+((sum&0b00010000)/16)*1+((sum&0b00001000)/8)*(1)+((sum&0b00000100)/4)*(2)+((sum&0b00000010)/2)*(3)+((sum&0b00000001)/1)*(4);
error = error*1.0/Count;
I do not clearly understand what is done in the highlighted section. What is the meaning of taking bit wise and operation between sum and those binary numbers?
thanks a lot :)

Each of the binary masks selects one of the eight sensor inputs.
Because the bits have different values when treated as integer, the scale factor for each of the bits has to be predivided by the value of the bit it is scaling.

Thanks ! Could you please explain it little bit more. is there any advantage of using this method rather than the method I mentioned in the first post to calculate the error value?

I did the experiment yo mentioned & observed the value of weighted sum using serial monitor. the value was changed in in consistent steps as u mentioned. Can you please explain little bit about the use of exponential filter to smooth it out?
Good. That rules out a lot of problems.
So, your controller is getting an input that steps from one value to another as you go from one side to the other and the main problem appears to be that you only get discrete steps in your output. I suspect that it tends to jerk back and forth a bit as you step back and forth across the boundary of one of the input steps? You could slow down the gains a bit, or as mentioned use a software filter such as:
FilteredValue = FilterConstant*RawValue + (1FilterConstant)*FilteredValue;
Where the FilteredValue is the output of your exponential filter, RawValue is the output from your sensor array summation, and FilterConstant is a constant value (between 0 and 1) that you adjust to control how fast the FilteredValue responds to a step change in the RawValue. FilterConstant = 1 will behave like you have now  no filtering.
You also have to initialize FilteredValue to a reasonable value when you power up (usually your first sample of RawValue)
Example of the results at different FilterConstants:
The disadvantage to the filtering is that you slow your response rate down.

Thank you very much jkerns for your valuable information. I tried the equation you provided and I could obtain better response than before. :) :)
I have one more little thing to get clarified
as I mentioned above , I found following algorithm in a fast line following robot. its response was really fast and smooth. could you please explain what is actually done there?
i am bit confused about what they have done with binary masks .
Is this a better way of calculating error ?
sum = 1*Sensors[0]+2*Sensors[1]+4*Sensors[2]+8*Sensors[3]+16*Sensors[4]+32*Sensors[5]+64*Sensors[6]+128*Sensors[7]
then the error was calculated as follows
Count=Sensors[0]+Sensors[1]+Sensors[2]+Sensors[3]+Sensors[4]+Sensors[5]+Sensors[6]+Sensors[7];
double error =((sum&0b10000000)/128)*4+((sum&0b01000000)/64)*3+((sum&0b00100000)/32)*2+((sum&0b00010000)/16)*1+((sum&0b00001000)/8)*(1)+((sum&0b00000100)/4)*(2)+((sum&0b00000010)/2)*(3)+((sum&0b00000001)/1)*(4);
error = error*1.0/Count;

sum = 1*Sensors[0]+2*Sensors[1]+4*Sensors[2]+8*Sensors[3]+16*Sensors[4]+32*Sensors[5]+64*Sensors[6]+128*Sensors[7]
The above line appears to take binary values (0 or 1) and stick them into particular bits of "sum"  the value of sensors[0] would end up in bit zero, the value of sensors[1] ends up in bit 1 etc.
then the error was calculated as follows
Count=Sensors[0]+Sensors[1]+Sensors[2]+Sensors[3]+Sensors[4]+Sensors[5]+Sensors[6]+Sensors[7];
So, count contains the number of sensors indicating 1
double error =((sum&0b10000000)/128)*4+((sum&0b01000000)/64)*3+((sum&0b00100000)/32)*2+((sum&0b00010000)/16)*1+((sum&0b00001000)/8)*(1)+((sum&0b00000100)/4)*(2)+((sum&0b00000010)/2)*(3)+((sum&0b00000001)/1)*(4);
sum&0b10000000) is doing a bitwise and so the end result will be either 128 (if bit 7 is set) or 0 the values of any bit other than the 7th (start counting at 0) will be ignored since they are "and" with a 0
Divide by 128 to get either 1 or 0 depending on the state of sensor[7]
multiply by 4 to weight the value of sensor 7 by 4
error = error*1.0/Count;
weighted sum divided by number of sensor "on"
Seems like more screwing around with binary numbers than would be necessary, but there could be reason.

Thanks jkerns :) :) :) :)