Malas lecturas - Sensor Infrarrojo Sharp

Coincido con ambos que algo se escapa o se está cometiendo el mismo error sistemático una y otra vez.
El tema del capacitor me parece que debe respetarse como dice el fabricante.
Ahora veamos como hacer que funcione correctamente.
He consultado la hoja de datos del GP2Y0A02YK0F y me sorprenden varias cosas.
Primero dice que el consumo medio es de 50 mA asi que espero no lo esten alimentando con la salida de un Arduino.
Pero la salida de 5V debiera ser suficiente y parece que no es el caso.
En la página 4 de la hoja de datos dice que luego de 5 mseg las lecturas deberían ser estables

otra cosa que leo en Sparkfun es que hay que usar un polinomio de aproximación porque de lo contrario tendras lecturas muy variables.
Veamos si esto sirve
Distance = 16.2537 * x4 - 129.893 * x3 + 382.268 * x2 - 512.611 * x + 306.439
Donde x => Tensión leída del ADC y Distance en cm

la expresión correcta sería

unsigned int x = analogRead(A0);
unsigned long x2 = x*x;    // esto es mas rápido computacionalmente que hacer x^2
unsigned long x3 = x2*x;   // esto es mas rápido computacionalmente que hacer x^3
unsigned long x4 = x3*x;   // esto es mas rápido computacionalmente que hacer x^4

float Distance = 16.2537 * x4 - 129.893 * x3 + 382.268 * x2 - 512.611 * x + 306.439;

Veamos que resulta.
Lean ambos los comentarios (en inglés) de Sparkfun, creo que son valiosos si no lo han hecho ya.

Otro código

/*
Calibration of Infrared Proximity Sensor Long Range - Sharp GP2Y0A02YK0F
SparkFun Part#: SEN-08958 https://www.sparkfun.com/products/8958

By Robert Hazlehurst, Castle View High School robert.hazlehurst@dcsdk12.org

for use on RedBot Robot SparkFun Part#: ROB-12032 https://www.sparkfun.com/products/12032
with RN42-XV Bluetooth Module - PCB Antenna installed in the Xbee port SparkFun Part#: WRL-11601 https://www.sparkfun.com/products/11601

Equation:
Distance (in inches) = 6202.3*SensorReading^-1.056 fit with an R² = 0.9914

Raw Data: 
Sensor          Distance (In)
502         8
434         10
379         12
329         14
283         16
257         18
229         20
213         22
199         24
139         36
91          48

*/

#include <RedBot.h>
RedBotSoftwareSerial bluetooth;

float sensor;
double distance;

void setup() 
{
  Serial.begin(9600);  // Begin the serial monitor at 9600bps
  bluetooth.begin(115200);  // The Bluetooth Mate defaults to 115200bps
  bluetooth.print("$");  // Print three times individually
  bluetooth.print("$");
  bluetooth.print("$");  // Enter command mode
  delay(100);  // Short delay, wait for the Mate to send back CMD
  bluetooth.println("U,9600,N");  // Temporarily Change the baudrate to 9600, no parity
  // 115200 can be too fast at times for NewSoftSerial to relay the data reliably
  bluetooth.begin(9600);  // Start bluetooth serial at 9600
}

void loop() 
{
  sensor = analogRead(A3); //read the sensor
  distance = 6202.3*pow(sensor,-1.056); //apply cal curve to convert to inches
  bluetooth.print("distance = "); //print distance to cell phone screen
  bluetooth.println(distance);
}

Para terminar, si van a promediar valores, háganlo sobre las lecturas del ADC no hace falta pasarlo a cmts para luego promediar. Es un gasto de tiempo del Arduino inútil.
toman N lecturas del ADC y las promedian. usen una variable tipo unsigned long si superan 64 muestras.

@surbyte gracias por la amabilidad, te comento que acabo de soltar el condensador al sharp y noto que no mejorar nada el tema de la inestabilidad hasta diría que lo empeora, yo lo alimento con los 5v del arduino ya que no debería dar inconvenientes como lo mencionas.

Probé con el segundo código que me facilitaste pero como que se queda midiendo en una sola distancia (no se porque),

trate de hacer funcionar el 1º código sin lograr resultados ya que soy muy principiante en esto ya te debiste de dar cuenta :confused:

También estuve probando con este código pero es siempre lo mismo

El primer código pruebalo asi

double distance1;
unsigned int x;
void setup() {
  Serial.begin(9600);  // Begin the serial monitor at 9600bps
}

void loop() 
{
  x = analogRead(A3); //read the sensor
  distance1 = 6202.3*pow((float) x,-1.056); //apply cal curve to convert to inches

  Serial.print("Dist Met 1        Dist Met 2"); //print distance to cell phone screen

  unsigned long x2 = x*x;    // esto es mas rápido computacionalmente que hacer x^2
  unsigned long x3 = x2*x;   // esto es mas rápido computacionalmente que hacer x^3
  unsigned long x4 = x3*x;   // esto es mas rápido computacionalmente que hacer x^4
  double distance2 = 16.2537 * x4 - 129.893 * x3 + 382.268 * x2 - 512.611 * x + 306.439;
  Serial.print(distance1);
  Serial.pirnt("      ");   // ajustar para que se vean encolumnados.
  Serial.println(distance2);
  delay(100);
}

surbyte:
El primer código pruebalo asi

double distance1;

unsigned int x;
void setup() {
  Serial.begin(9600);  // Begin the serial monitor at 9600bps
}

void loop()
{
  x = analogRead(A3); //read the sensor
  distance1 = 6202.3*pow((float) x,-1.056); //apply cal curve to convert to inches

Serial.print("Dist Met 1        Dist Met 2"); //print distance to cell phone screen

unsigned long x2 = xx;    // esto es mas rápido computacionalmente que hacer x^2
  unsigned long x3 = x2
x;  // esto es mas rápido computacionalmente que hacer x^3
  unsigned long x4 = x3*x;  // esto es mas rápido computacionalmente que hacer x^4
  double distance2 = 16.2537 * x4 - 129.893 * x3 + 382.268 * x2 - 512.611 * x + 306.439;
  Serial.print(distance1);
  Serial.pirnt("      ");  // ajustar para que se vean encolumnados.
  Serial.println(distance2);
  delay(100);
}

Ahora lo probé y me da estas lecturas...

Mi objetivo es que cuando detecte objetos que están a menos de 100 cm haga encender un led...
si probamos un código sencillo para ello? utilizando el promedio móvil? o tu que opinas @surbyte

Mira este código que realiza el clásico promedio tomando 20 tomas algo así me estaba refiriendo :), lo estuve probando y funciona bastante bien estando el sensor quieto. pero cuando lo empiezo a mover de un lado a otro empieza nuevamente las tomas falsas encendiendo el led en algunos momentos

void setup() {
  // Comunicación seria a 9600 baudios
  Serial.begin(9600);
  pinMode(2, OUTPUT);
}


void loop() {
  // Leemos el promedio de la entrada analógica 0 :
  int ADC_SHARP=ADC0_promedio(20);
  if(ADC_SHARP>195)
  {
    digitalWrite(2, HIGH);
    Serial.print("Objeto Detectado:");
  }
  else
  {
    digitalWrite(2, LOW);
    Serial.print("Objeto ausente:");
  }
  
  Serial.println(ADC_SHARP);
  delay(10);
}

int ADC0_promedio(int n)
{
  long suma=0;
  for(int i=0;i<n;i++)
  {
    suma=suma+analogRead(A0);
  }  
  return(suma/n);
}

Hola raika125, te contesto por acá para que todos tengamos aceso a la info y si a alguien más le cuesta como a nosotros (newbies) pueda apoyarse para resolver.

Mira, yo agregué los siguientes componentes:

  • 1 Capacitor Electrolítico de 10uf
  • 1 Capacitor Cerámico de 0,1uf (tipo lenteja)

Ambos se conectan en paralelo y con una pata al + y otra al - del sensor como muestra la imágen (en el caso del electrolítico hay que respetar la polaridad) tal como muestra esta imágen.

Además encontré otros post donde explican que claro se baja el ruido pero no se elimina.

Aclarando el tema, el ruido se produce por la alimentación de 5v ya que no es completamente estable, y el sensor al ser tan lamentablemente sensible muestra estas variaciones o respingos. Ahora se puede reducir harto, pero no eliminar. Yo probé con los capacitores y con voltaje directo no proveniente del Arduino y se estabilizó considerablemente desde el primer intento, pero insisto no eliminé el problema.

Te dejo un link donde hay más info al respecto que explica y le agrega capacitor sobre capacitor demostrando como se reduce el ruido.

LetsMakeRobots - Filtering Sharp IR sensor’s noise on power rail

Acá hay un post en este mismo foro pero en inglés donde hablan de una librería que ayuda a solucionar los problemas con este sensor, esta solución no la he probado y si te sirve por favor avísame.

Forum Arduino CC - Library for Distance Sensors

Acá está el link de la librería (y adjunto la misma porque siempre se caen estos links).

Github - Arduino GP2Y0A21YK library

Y acá de otra librería para sensores más genérica.

Github - Arduino distance sensor library

Además te dejo el DataSheet del Sensor para que revises info del hardware de ser necesario.

Si progresas, postea tus resultados, ya que es interesante para toda la comunidad cada pequeño progreso.

GP2Y0A02YK0F.pdf (686 KB)

Arduino-GP2Y0A21YK-library-master.zip (199 KB)

raika125, lo que buscas hacer de que t encienda un led y que te detecte en un rango yo ya lo tengo resuelto, me molesta el tema del respingo de lecturas, pero voy a probar promediar tal como tu comentaste a ver que me resulta, te comparto mi codigo para que pruebes el tema. En mi caso armé 3 rangos con 3 LED y anda relativamente decente dejando el sensor quieto claramente… creo que ya nos falta poco jejejeje

Te dejo además la librería “oficial” de Sharp que yo usé.

#include <SharpIR.h>

#define ir A0
#define model 20150 // Es importante ya que define exactamente que modelo de Sharp es

SharpIR sharp(ir, 15, 93, model);

int ledrojo=13; //primer rango de distancia cercana (LED conectado a PIN 13)
int lednaranja=12; //segundo rango de distancia a media distancia(LED conectado a PIN 12)
int ledverde=11; //tercer rango de distancia lejana (LED conectado a PIN 11)
int led;
int irState = LOW; //LED comienza apagado


const int LEDpir = 10;
const int PIRPin = 2;
int pirState = LOW;
int val = 0;

int contador1=0;
int contador2=0;
int contador3=0;
int estadoAnterior = 0;

void setup() {
    Serial.begin(9600);
  pinMode (ir, INPUT);
  pinMode(ledrojo, OUTPUT); 
  pinMode(lednaranja, OUTPUT); 
  pinMode(ledverde, OUTPUT);

  pinMode(PIRPin, INPUT);
  pinMode(LEDpir, OUTPUT);
}

void loop() {
irSharp_detection();
pir_detection();
}

void irSharp_detection()
{
int dis=sharp.distance();

if (dis>150){ //rango lejano sobre 150cms
    Serial.print("C=");
    Serial.println(contador3++);
    irState = HIGH;
    digitalWrite(ledverde,LOW);
    digitalWrite(lednaranja,LOW);
    digitalWrite(ledrojo,HIGH);
}
  if (dis<140&&dis>60){ //rango intermedio entre 60 y 140cms
Serial.print("B=");
Serial.print(contador2++);
    irState = HIGH;
    digitalWrite(ledverde,LOW);
    digitalWrite(lednaranja,HIGH);
    digitalWrite(ledrojo,LOW);
}
if (dis<50&&dis>30){ //rango cercano entre 30 a 50cms (debemos recordar que este sensor no detecta bajo los 20cms y si pones cifras desde "0" va a marcar erroneamente sin que exista deteccion por la variacion de voltaje)
Serial.print("A=");
Serial.print(contador1++);
    irState = HIGH;
    digitalWrite(ledverde,HIGH);
    digitalWrite(lednaranja,LOW);
    digitalWrite(ledrojo,LOW);
}
else
  {
    digitalWrite(ledverde, LOW);
    digitalWrite(lednaranja, LOW);
    digitalWrite(ledrojo, LOW);
    if (irState == HIGH)
    {
      //Serial.println("Stop Sensor");
      irState = LOW;
      //contador=0;//Reset Counter
    }
  }
 switch(led){
    case 1:
    digitalWrite(ledverde,HIGH);
    break;
    case 2:
    digitalWrite(lednaranja,HIGH);
    break;
    case 3:
    digitalWrite(ledrojo,HIGH);
    break;
  }
}

SharpIR.zip (17.3 KB)

Bueno, Quisiera compartir con ustedes el código que fue realizado por @surbyte que en mi caso era encender un led si un objeto estuviera a menos de 100cm, el código funciona bastante bien evitando las variaciones de lectura que el arduino interpretaba como informacion que proporcionaba el sensor sin moverse apuntando a una dirección.

Cabe destacar que el código solo me funciona si el sensor se encuentra fijo en una determinada posición, ya que con ligeros movimientos da saltos en las lecturas 120 - 86 - 112 - 63 - 90
Informándome un poco y hablando con @Litoto llegamos a la conclusión que el sensor IR Sharp estando en movimiento por el modo que reflejar la señal infrarroja produce malas lecturas como que se descalibra si se lo mueve. Aunque viendo por ahí me tope con proyectos que usan el sensor con un servo motor moviendolo de un lado al otro sin tener el error :frowning:

Ahora estoy en busca de un sensor que no tenga ese punto negativo…
Hace tiempo que probé el sensor por ultrasonido dándome problemas que no detectaba objetos ya sea por el material que estaba compuesto o por la textura, tamaño y posición a la que se hallaba, decidí apostar por este sensor infrarrojo…
Si alguien me recomienda otro sensor que tenga las características que busco? (capacidad de detectar objetos pequeños sin importar el materia estando el sensor en movimiento)

Gracias totales de nuevo a @surbyte que sin el no se hubiera llegado hasta este punto.

/*
Autor:@surbyte
*/
#define LED 2 //define el pin del LED
float distAnt = 0.0;
float medida;

void setup(){
 Serial.begin(9600);
 pinMode(LED, OUTPUT);
 Serial.println("Inciando.");
 
}

void loop(){

distAnt = medida;
medida = IR_Sensor(3);

if (abs(medida-distAnt) < 2.0) {
      Serial.print("  Distancia: ");
      Serial.print(medida);
      Serial.println(" cm");
    
      if (medida < 100.0) 
        digitalWrite(LED, HIGH);
      else 
        digitalWrite(LED, LOW);
  }

delay(100);
}

Y en otra tabla…

float IR_Sensor(int pin_ir){

int ADC;
float Tension,distancia;


ADC=analogRead(pin_ir);//Leemos en el canal pin
Tension=ADC_to_Volt(ADC);//Conversion a Voltios

distancia=60.374*pow(Tension,-1.16);// Funcion obtenida con el excel

return distancia;
}


float ADC_to_Volt(int ADC_value){
float Volt=0;

Volt=(ADC*5.0)/1023;


return Volt;
}