Ben,
As per my recent email, please find attached code. It uses/references the autoscale function code, that can be found on
Arduino Playground site.
void read_sharpIR()
{
set_analog_mode(MODE_10_BIT);
long int reading1 = analog_read_millivolts(4);
delay_ms(33);
long int reading2 = analog_read_millivolts(4);
delay_ms(33);
long int reading3 = analog_read_millivolts(4);
IR_dist_measure_mv = (int)((reading1+reading2+reading3/*+reading4+reading5*/)/3);
int corr_cm[16]= {20 ,30 ,40 ,50 ,60 ,70 ,80 ,90 ,100,110,120,130,140,150,160,170};
int corr_mv[16] = {2500,2000,1550,1250,1050,900,800,715,650,600,550,500,475,450,425,400};
if(IR_dist_measure_mv >= corr_mv[0])
{
distance_calculated_in_cm = corr_cm[0];
IR_dist_measure_mv = corr_mv[0];
}
else if((IR_dist_measure_mv >= corr_mv[1]) && (IR_dist_measure_mv <= corr_mv[0]))
{
distance_calculated_in_cm = autoscale(corr_mv[1], corr_mv[0],corr_cm[1],corr_cm[0], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[2]) && (IR_dist_measure_mv <= corr_mv[1]))
{
distance_calculated_in_cm = autoscale(corr_mv[2], corr_mv[1],corr_cm[2],corr_cm[1], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[3]) && (IR_dist_measure_mv <= corr_mv[2]))
{
distance_calculated_in_cm = autoscale(corr_mv[3], corr_mv[3],corr_cm[3],corr_cm[2], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[4]) && (IR_dist_measure_mv <= corr_mv[3]))
{
distance_calculated_in_cm = autoscale(corr_mv[4], corr_mv[3],corr_cm[4],corr_cm[3], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[5]) && (IR_dist_measure_mv <= corr_mv[4]))
{
distance_calculated_in_cm = autoscale(corr_mv[5], corr_mv[4],corr_cm[5],corr_cm[4], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[6]) && (IR_dist_measure_mv <= corr_mv[5]))
{
distance_calculated_in_cm = autoscale(corr_mv[6], corr_mv[5],corr_cm[6],corr_cm[5], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[7]) && (IR_dist_measure_mv <= corr_mv[6]))
{
distance_calculated_in_cm = autoscale(corr_mv[7], corr_mv[6],corr_cm[7],corr_cm[6], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[8]) && (IR_dist_measure_mv <= corr_mv[7]))
{
distance_calculated_in_cm = autoscale(corr_mv[8], corr_mv[7],corr_cm[8],corr_cm[7], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[9]) && (IR_dist_measure_mv <= corr_mv[8]))
{
distance_calculated_in_cm = autoscale(corr_mv[9], corr_mv[8],corr_cm[9],corr_cm[8], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[10]) && (IR_dist_measure_mv <= corr_mv[9]))
{
distance_calculated_in_cm = autoscale(corr_mv[10], corr_mv[9],corr_cm[10],corr_cm[9], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[11]) && (IR_dist_measure_mv <= corr_mv[10]))
{
distance_calculated_in_cm = autoscale(corr_mv[11], corr_mv[10],corr_cm[11],corr_cm[10], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[12]) && (IR_dist_measure_mv <= corr_mv[11]))
{
distance_calculated_in_cm = autoscale(corr_mv[12], corr_mv[11],corr_cm[12],corr_cm[11], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[13]) && (IR_dist_measure_mv <= corr_mv[12]))
{
distance_calculated_in_cm = autoscale(corr_mv[13], corr_mv[12],corr_cm[13],corr_cm[12], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[14]) && (IR_dist_measure_mv <= corr_mv[13]))
{
distance_calculated_in_cm = autoscale(corr_mv[14], corr_mv[13],corr_cm[14],corr_cm[13], IR_dist_measure_mv);
}
else if((IR_dist_measure_mv >= corr_mv[15]) && (IR_dist_measure_mv <= corr_mv[14]))
{
distance_calculated_in_cm = autoscale(corr_mv[15], corr_mv[14],corr_cm[15],corr_cm[14], IR_dist_measure_mv);
}
else if(IR_dist_measure_mv <= corr_mv[15])
{
distance_calculated_in_cm = corr_cm[15];
IR_dist_measure_mv = corr_mv[15];
}
};
The function works well. It seems to be giving me the 1cm resolution I had hoped for, at least upto 1m range.
I have to do more test for more than one meter. However, the manufacturer curve data is very accurate. This is
confirmed with a laser dot pointer and a tape measure to confirm measurements.
Above the 1 meter mark, you can get an error of 2cm or more. The biggest factor seems to be the angle of the object being detected.
That is, I used a hard cover text book standing at 90ºC, then slightly slanted to the horizontal. This seemed to effect the reading.
I am using a blue and red surface. Although when I test it, I will try with different surfaces. A mirror surface, a black surface, a red and while ceraminc
tile. the laser pointer comes in handy becuase you can tell exactly where the reflection is taking place.
The power(x,y) method in the math.h library took two long to be feasible. Lienar interpolation was the least MCU intensive. After some trial error, I found that sampling every 100ms is about the right rate for the RP5 speed. At 40ms, it is the best for a single reading.
With the code, I have averaged out three readings before conditionally testing the millivolt output. However, 15 conditional test statements
appears inefficient in terms of coding style. Perhaps if you had a look at the code, you may be able to suggest ways to improve it/shorten it.
I am happy to share this code with others. I can provide photos and other relevant data. I am getting upto 170cm (down to 400mV) at the moment.
Is there anyway I can turn off the ADC (ie port A), for the purpose of saving battery power?
Regards,
Carl