📜 ⬆️ ⬇️

Sharp Infrared Range Finder

Good afternoon, I want to share my method of working with Sharp's infrared range finders using the example of a Sharp GP2D120 model (4-40 cm).

I will describe in detail the compilation of the processing function and give an example of the application. The advantage of this feature is that it allows you to use the entire working range of any rangefinder.

Your robot will no longer lose obstacles.

1 - We read documentation


Each sensor already has a measured volt-ampere characteristic, which is the model name. Considering the specifics of the sensors, the manufacturer set the distance to the obstacle in accordance with the output voltage:
')


According to the schedule, we determine the voltage corresponding to each distance and write to two arrays:

float voltage[] = {2.7, 2.34, 2.00, 1.78, 1.56, 1.4, 1.265, 1.06, 0.92, 0.8, 0.74, 0.66, 0.52, 0.42, 0.36, 0.32}; float distanse[] = {4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 25.0, 30.0, 35.0, 40.0}; int len = 16; //      


2 - Implement interpolation


First, we interrogate the sensor several times (10) and take the average value to avoid random noise:

 int senPin = 0; // "Analog In",    int out = 0; for (int i = 0; i < 10; i++){ out += analogRead(senPin); delay(8); //     } out = out/10; 


Knowing that in Arduin analogRead () gives values ​​from 0 to 1023, and Sharp sensors from 0 to 5 Volts, we transform out to volts and find the position of this value in the voltage array:

 int pos = 0; float volt_read = out * 0.00488758553; // 5 / 1023 = 0.00488758553 if((voltage[0] > volt_read) && (voltage[N-1] < volt_read)){ // ,      for (int i = 0; i < N-1; i++) { if(volt_read >= voltage[i+1]){ pos = i; break; } } } 


The penultimate step.

Interpolating the graph, we calculate the distance corresponding to the output voltage.



 float y1 = voltage[pos]; float x1 = distance[pos]; float y2 = voltage[pos + 1]; float x2 = distance[pos + 1]; float distance_out = (x2 - x1)*(y1 - volt_read)/(y1 - y2) + x1; //     123  145 


3 - We assemble function


 float getDistance(int senPin){ float voltage[] = {2.7, 2.34, 2.00, 1.78, 1.56, 1.4, 1.265, 1.06, 0.92, 0.8, 0.74, 0.66, 0.52, 0.42, 0.36, 0.32}; float distanse[] = {4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 25.0, 30.0, 35.0, 40.0}; int len = 16; int out = 0; int pos = 0; for (int i = 0; i < 10; i++){ out += analogRead(senPin); delay(8); } out = out/10; float volt_read = out * 0.00488758553; // 5 / 1023 = 0.00488758553 if((voltage[0] > volt_read) && (voltage[N-1] < volt_read)){ for (int i = 0; i < N-1; i++) { if(volt_read >= voltage[i+1]){ pos = i; break; } } float y1 = voltage[pos]; float x1 = distance[pos]; float y2 = voltage[pos + 1]; float x2 = distance[pos + 1]; float distance_out = (x2 - x1)*(y1 - volt_read)/(y1 - y2) + x1; return distance_out } else return -1.0; } 


4 - Properly use


Experimentally, I noticed that the function works best if you run it with an interval of 15 milliseconds for any number of range finders:

 void updateDistance{ float D1 = getDistance(0); delay(15); // ... float D6 = getDistance(5); delay(15); } 


For DIY lovers, I note that the code has been tested on such an installation:



Thanks for attention.

Source: https://habr.com/ru/post/226359/


All Articles