Sharp GP2Y0A21YK proximity - wrong values

Hi!

I got a Sharp GP2Y0A021YK promity sensor and wired it to 5V/GND/Analog0.

It works but sometimes it get wrong values after uploading a sketch or turning the arduino off and on again or after just turn it on.

Normally the sensor measures from 10-80cm, but sometimes its only 10 - about 40cm, when i move further away it stays at about 40cm.

Then i have plug off/on the sensor or turn the arduino off/on several times until it works.

Thats really annoying, i got no ideas. :-[

I cant show you my script atm (its at home) but its a simple if else:
value = analogread(0);
if (value <= 82) {} else if (value <= 92) {} else if (value <= 162) {} etc
which is lightning up a led bargraph.

Kind regards, SJB

Thats the code:

int sensorPin = 0;    // input pin for the sensor
int bar1 = 2;      // select the pin for the LED
int bar2 = 3;
int bar3 = 4;
int bar4 = 5;
int bar5 = 6;
int bar6 = 7;
int bar7 = 8;
int bar8 = 9;
int bar9 = 10;
int bar10 = 11;
int volt = 0;  // variable to store the value coming from the sensor
int zeit = 10; // *10 = Gesamtzeit - total time

void setup() {
  // Serial.begin(9600);
  pinMode(bar1, OUTPUT);  
  pinMode(bar2, OUTPUT);  
  pinMode(bar3, OUTPUT);  
  pinMode(bar4, OUTPUT);  
  pinMode(bar5, OUTPUT);  
  pinMode(bar6, OUTPUT);  
  pinMode(bar7, OUTPUT);  
  pinMode(bar8, OUTPUT);  
  pinMode(bar9, OUTPUT);  
  pinMode(bar10, OUTPUT);  
}

void loop() {
  
  volt = analogRead(sensorPin); 
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  delay(zeit);
  volt = volt + analogRead(sensorPin);
  volt = volt / 9;
  
  // Serial.println(volt);  
  if (volt <= 82) {
    // >= 80cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, LOW);
    digitalWrite(bar3, LOW);
    digitalWrite(bar4, LOW);
    digitalWrite(bar5, LOW);
    digitalWrite(bar6, LOW);
    digitalWrite(bar7, LOW);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 92) {
    // >= 70cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, LOW);
    digitalWrite(bar4, LOW);
    digitalWrite(bar5, LOW);
    digitalWrite(bar6, LOW);
    digitalWrite(bar7, LOW);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 102) {
    // >= 60cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, LOW);
    digitalWrite(bar5, LOW);
    digitalWrite(bar6, LOW);
    digitalWrite(bar7, LOW);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 123) {
    // >= 50cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, LOW);
    digitalWrite(bar6, LOW);
    digitalWrite(bar7, LOW);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 154) {
    // >= 40cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, HIGH);
    digitalWrite(bar6, LOW);
    digitalWrite(bar7, LOW);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 184) {
    // >= 30cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, HIGH);
    digitalWrite(bar6, HIGH);
    digitalWrite(bar7, LOW);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 266) {
    // >= 20cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, HIGH);
    digitalWrite(bar6, HIGH);
    digitalWrite(bar7, HIGH);
    digitalWrite(bar8, LOW);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 328) {
    // >= 15cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, HIGH);
    digitalWrite(bar6, HIGH);
    digitalWrite(bar7, HIGH);
    digitalWrite(bar8, HIGH);
    digitalWrite(bar9, LOW);
    digitalWrite(bar10, LOW);
  } else if (volt <= 461) {
    // >= 10cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, HIGH);
    digitalWrite(bar6, HIGH);
    digitalWrite(bar7, HIGH);
    digitalWrite(bar8, HIGH);
    digitalWrite(bar9, HIGH);
    digitalWrite(bar10, LOW);
  } else if (volt > 461) {
    // < 10cm
    digitalWrite(bar1, HIGH);   
    digitalWrite(bar2, HIGH);
    digitalWrite(bar3, HIGH);
    digitalWrite(bar4, HIGH);
    digitalWrite(bar5, HIGH);
    digitalWrite(bar6, HIGH);
    digitalWrite(bar7, HIGH);
    digitalWrite(bar8, HIGH);
    digitalWrite(bar9, HIGH);
    digitalWrite(bar10, HIGH);
  }
  delay(zeit);                  
}

The average is for minimizing spikes.

SJB

Maybe if you change your picture. I find that insulting.

I changed my picture ;)

I searched 5min for the Options in the User CP, until i found the "Profile" button :D

SJB

Your code is far longer than it needs to be. Using array and loops would shorten the code considerably.

int barPin[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

That’s one line of code, instead of the 10 you are using now.

Reading the sensor could be done in a loop, too:

int volt = 0;
for(int i=0; i<10; i++)
{
   volt += analogRead(sensorPin);
   delay(zeit);
}
volt /= 10;

7 lines of code, instead of the 18 you have.

Fewer lines of code means fewer opportunities for errors to creep in.

You use 10 lines of code for each level. You could do it like this:

int litCount = 0;
if(volt <= 82)
   litCount = 1;
else if(volt <= 92)
   litCount = 2;
// additional else if's for the other values

Once you know how many bars to light up:

for(int b=0; b<10; b++)
{
   if(b<=litCount)
     digitalWrite(barPin[b], HIGH); // Turn the bar on
   else
     digitalWrite(barPin[b], LOW); // Turn the bar off
}

The data sheet for your sensor shows a pretty shallow slope from 40 to 80 cm, with the voltage changing from about 0.75V to 0.4V. This difference is small, but certainly detectable by the Arduino. I don’t see anything in your code that would explain the problem.

Take the arduino out of the equation. Feed the sensor 5 volts and hook a voltmeter up to the output. Play around with moving around the sensor and switching it on and off whilst watching the voltage. That will establish if the problem is in the arduino / coding or the sensor isn’t working properly. First rule of problem solving : simplify the problem…

Yeah, i know, my code is very long, thanks for shortening it :wink:

I turned the Arduino on and it hangs on 10-19cm now, the sensor layed on the floor and pointed to the floor.
When i had the 10-40cm problem, it layed on the floor pointing to the ceiling.
I dont know if the sensor get stuck when its powered up and pointing to something out of the 10-80cm range??

I’m still searching for my voltmeter :-?

SJB

I shortened the code now, but there are 10 bars on, i looked on the serial monitor, the values are atm between 365-390, still not correct but only 9 bars should be turned on?

else if (volt <= 461) { litCount = 9; }

int sensorPin = 0;    // input pin for the sensor
int barPin[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; 
int barPinCount = 10;
int volt = 0;  // variable to store the value coming from the sensor
int zeit = 100; // *10 = Gesamtzeit - total time

void setup() {
  Serial.begin(9600);
  int thisPin;
  // the array elements are numbered from 0 to (pinCount - 1).
  // use a for loop to initialize each pin as an output:
  for (int thisPin = 0; thisPin < barPinCount; thisPin++)  {
    pinMode(barPin[thisPin], OUTPUT);      
  }
}

void loop() {
  int volt = 0;
  for(int i=0; i<10; i++)
  {
    volt += analogRead(sensorPin);
    delay(zeit);
  }
  volt /= 10;

  Serial.println(volt);
  int litCount = 0;
  if (volt <= 82) {
    // >= 80cm
    litCount = 1;
  } else if (volt <= 92) {
    // >= 70cm
    litCount = 2;
  } else if (volt <= 102) {
    // >= 60cm
    litCount = 3;
  } else if (volt <= 123) {
    // >= 50cm
    litCount = 4;
  } else if (volt <= 154) {
    // >= 40cm
    litCount = 5;
  } else if (volt <= 184) {
    // >= 30cm
    litCount = 6;
  } else if (volt <= 266) {
    // >= 20cm
    litCount = 7;
  } else if (volt <= 328) {
    // >= 15cm
    litCount = 8;
  } else if (volt <= 461) {
    // >= 10cm
    litCount = 9;
  } else if (volt > 461) {
    // < 10cm
    litCount = 10;
  }
  
  for(int b=0; b<10; b++)
  {
   if(b<=litCount)
     digitalWrite(barPin[b], HIGH); // Turn the bar on
   else
     digitalWrite(barPin[b], LOW); // Turn the bar off
  }

}

Stillt dont know where the voltmeter is :-/

SJB

if(b<=litCount)

This should be

if(b < litCount)

Sorry about that…

I’m still searching for my voltmeter

Buy a new one. Then, the old one will come out to see the new one. :slight_smile:

I found the voltmeter :D

The 5V from the Arduino are between 4-4.2V measured at the breadboard :-?

The Arduino is USB powered by my PC, which has 4,8 - 4,98V at the USB Port.

SJB

Okay, it's definitive a voltage problem...

I connected 5V direct to the breadboard and the VIN of the arduino and it works now...

I really dont know, why the arduino delivers only 4-4.2V from the USB port (which has 4.8-4.98V)?!

SJB