Malas lecturas - Sensor Infrarrojo Sharp

Buenas! tengo un problema con el sensor Sharp GP2Y0A02YK0F (20 - 150 cm) que me da unas lecturas para nada constantes, varían mucho.
Mi código es bastante simple en cuanto el valor sea mas que 170 encenderá un LED.
El inconveniente surge que cuando las lecturas dan saltos ej: 97,68,104,127 y esto provoca que en un momento determinado el valor sea mas alto del establecido y encienda el led por unos instantes siendo que no hay ningún obstáculo frente al dicho sensor.

#define LED 2 //define el pin del LED
 
int dist = 0; //guarda el valor del sensor
 
void setup()
{
pinMode(LED, OUTPUT);
Serial.begin(9600);
}
 
void loop()
{
dist = analogRead(0); //Lee A0 y almacenamos su valor
Serial.println(dist); //Escribe dist por serial
 
if(dist > 170) digitalWrite(LED, HIGH);
else digitalWrite(LED, LOW);
 
delay(100);
}

Me parece que no es tan facil como lo pones:

jose:
Me parece que no es tan facil como lo pones:
http://www.luisllamas.es/2016/06/arduino-sharp-gp2y0a02yk0f/

Ahora lo acabo de cargar y veo que asi mejora mucho, pero sigue teniendo el problema de las variaciones, probé otro sensor y funciona de igual manera aquí una foto.
Alguna forma de evitar esta lectura o que no cause el error de encender el led?

Ahora lo estoy usando como el de la pag. pero sigue dando ese fallo, como si detectara un objeto durante un instante…

const int sensorPin = A0;
const long referenceMv = 5000;
const int ledPin = 2;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  //lectura de la tensión
  int val = analogRead(sensorPin);
  int mV = (val * referenceMv) / 1023;
  int cm = getDistance(mV);
 
  
  //mostrar valores por pantalla
  Serial.print(mV);
  Serial.print(",");
  Serial.println(cm);

if(cm < 100) digitalWrite(ledPin, HIGH);
else digitalWrite(ledPin, LOW);

 
  delay(100);
}
 
//interpolación de la distancia a intervalos de 250mV
const int TABLE_ENTRIES = 12;
const int INTERVAL  = 250;
static int distance[TABLE_ENTRIES] = {150,140,130,100,60,50,40,35,30,25,20,15};
 
int getDistance(int mV) {
  if (mV > INTERVAL * TABLE_ENTRIES - 1)      return distance[TABLE_ENTRIES - 1];
  else {
    int index = mV / INTERVAL;
    float frac = (mV % 250) / (float)INTERVAL;
    return distance[index] - ((distance[index] - distance[index + 1]) * frac);
  }
}

En el articulo se habla de posibles fallos ante superficies de cristal o brillantes y la incidencia de fuentes de luz.Tambien podrias hacer un promedio de varias lecturas ,respetando el tiempo de refresco del sensor (80 ms segun el articulo).

porque no usas como un tubo que concentre el haz de ida y de vuelta? Algo que elimine interferencias de luz ambiente o artificial que este alterando tus lecturas.

surbyte:
porque no usas como un tubo que concentre el haz de ida y de vuelta? Algo que elimine interferencias de luz ambiente o artificial que este alterando tus lecturas.

Como seria eso esactamente @surbyte? No entiendo como va ese tema...

jose:
En el articulo se habla de posibles fallos ante superficies de cristal o brillantes y la incidencia de fuentes de luz.Tambien podrias hacer un promedio de varias lecturas ,respetando el tiempo de refresco del sensor (80 ms segun el articulo).

Como estaria lo del promedio :confused: Cual seria el codigo a agregar?

raika125:
Como estaria lo del promedio :confused: Cual seria el codigo a agregar?

Bueno un promedio es la suma del valor de varias lecturas dividido entre el numero de lecturas.Defines una variable como acumulador,lees y sumas ,esperas 80ms,lees y añades a la suma,esperas 80ms,lees y añades a la suma .....tantas veces como lecturas quieras hacer.Luego divides lo acumulado entre el numero de lecturas y obtendras una media de los valores.El numero de lecturas dependera del uso que le des al sensor,si por ejemplo es para evitar que un vehiculo choque ,no te puedes tirar 2 segundos tomando medidas para promediarlas porque segun la velocidad se dara contra el obstaculo......

jose:
Bueno un promedio es la suma del valor de varias lecturas dividido entre el numero de lecturas.Defines una variable como acumulador,lees y sumas ,esperas 80ms,lees y añades a la suma,esperas 80ms,lees y añades a la suma .....tantas veces como lecturas quieras hacer.Luego divides lo acumulado entre el numero de lecturas y obtendras una media de los valores.El numero de lecturas dependera del uso que le des al sensor,si por ejemplo es para evitar que un vehiculo choque ,no te puedes tirar 2 segundos tomando medidas para promediarlas porque segun la velocidad se dara contra el obstaculo......

Gracias por la explicacion! La verdad que quiero que haga el promedio lo mas rapido posible porque quiero que detecte obstaculos que estan en movimiento, y como dices no puede estar mucho tiempo calculando ya que no me funcionaria para lo antes mencionado, como seria en codigo todo eso?
Gracias

raika125:
Gracias por la explicacion! La verdad que quiero que haga el promedio lo mas rapido posible porque quiero que detecte obstaculos que estan en movimiento, y como dices no puede estar mucho tiempo calculando ya que no me funcionaria para lo antes mencionado, como seria en codigo todo eso?
Gracias

Te lo he explicado para que trates de hacerlo tu,que si no no vas a aprender nada…

jose:
Te lo he explicado para que trates de hacerlo tu,que si no no vas a aprender nada....

Bueno, pondre manos a la obra aver como se comporta ;D

raika125:
Bueno, pondre manos a la obra aver como se comporta ;D

Como pista ,para repetir algo un numero conocido de veces usa un bucle for:
https://www.arduino.cc/en/Reference/For

Amigo, nunca has estudio como promediar 10 valores.
Sumas los 10 valores y divides la suma por 10. a 82 mseg por lectura eso insumirá 820 mseg.

El promedio es una alternativa pero lo del tubo requiere explicación? Vaya que me sorprende el nivel de tus preguntas y disculpa porque no estoy en ningún altar pero es muy básico.
Tienes tu sensor y le agregas un cilindro de 1 o 2 cmt para limitar la exposición de la luz a solo la que va y viene o sea solo la que corresponde al sensor.
Mira, si usaras un LDR que no es tu caso asi se vería con el tubo



Como tu sensor tiene un emisor y un receptor lado a lado, busca una caja plastica pequeña le quitas una tapa suponiendo que la otra ya este libre y eso podria servir. Espero me hay explicado.

Y para el tema promedio te voy a aconsejar una herramienta mas apropiada que se llama promedio movil.
El promedio móvil permite usar mas mas muestras pero siempre descarta la primera y agrega la nueva.
Ventajas. es mas rápido ya que puedes por solo trabajas con una sola lectura mas las operaciones nuevas, de modo que hablamos de estar en el tiempo de lectura del sensor mas pocos microsegundos para las operaciones matemáticas.
Y otra ventaja es que tu muestra de valores promediados puede ser mayor.
Si con 10 estabas en 820 mseg con 100 tardarías 8.20 seg pero con promedio movil puedes usar 100 muestras y demorar 85 mseg por ejemplo

Busco el código y te lo paso.

surbyte:
Amigo, nunca has estudio como promediar 10 valores.
Sumas los 10 valores y divides la suma por 10. a 82 mseg por lectura eso insumirá 820 mseg.

El promedio es una alternativa pero lo del tubo requiere explicación? Vaya que me sorprende el nivel de tus preguntas y disculpa porque no estoy en ningún altar pero es muy básico.
Tienes tu sensor y le agregas un cilindro de 1 o 2 cmt para limitar la exposición de la luz a solo la que va y viene o sea solo la que corresponde al sensor.
Mira, si usaras un LDR que no es tu caso asi se vería con el tubo



Como tu sensor tiene un emisor y un receptor lado a lado, busca una caja plastica pequeña le quitas una tapa suponiendo que la otra ya este libre y eso podria servir. Espero me hay explicado.

Y para el tema promedio te voy a aconsejar una herramienta mas apropiada que se llama promedio movil.
El promedio móvil permite usar mas mas muestras pero siempre descarta la primera y agrega la nueva.
Ventajas. es mas rápido ya que puedes por solo trabajas con una sola lectura mas las operaciones nuevas, de modo que hablamos de estar en el tiempo de lectura del sensor mas pocos microsegundos para las operaciones matemáticas.
Y otra ventaja es que tu muestra de valores promediados puede ser mayor.
Si con 10 estabas en 820 mseg con 100 tardarías 8.20 seg pero con promedio movil puedes usar 100 muestras y demorar 85 mseg por ejemplo

Busco el código y te lo paso.

Mi querido @surbyte disculpa por la preguntas tan tontas, en este mundo de la programación y arduino soy muy novato, voy aprendiendo de apoco,
Segui tu recomendación para evitar la interferencia de luz ambiente pero conseguí el mismo resultado.
Pero investigando el problema de las variaciones del sensor me di cuenta que es un inconveniente típico, el mismo fabricante recomienda el uso de capacitores para mejorar la estabilidad...
Algunos artículos que hablan sobre el problema
http://www.robotroom.com/DistanceSensor3.html

conseguiré los elementos necesarios y voy a probar de vuelta ya que tambien tengo ese problema y creo que son la causa de las mediciones erráticas...

Pero cuando tengas el código del "promedio móvil" me lo puedes facilitar, estoy interesado ya que no estaría de mas probar antes antes de usar los capacitores y porque no también después, para ver la diferencia. gracias

Hola “raika125”, mira yo también estuve probando con ese sensor tratando de que me tomara 3 lecturas diferentes a 3 rangos determinados que yo fijaba. El primer inconveniente que me topé con este antojadizo sensor, es que demora varios segundos en “estabilizarse” un poco, luego que la superficie a la que apunta ojalá debe ser perpendicular al haz que emite el sensor, si no como que se marea en la lectura. Una vez revisado esto, me centré en la librería adecuada y aún así, pega saltos en la lectura (no es número cerrado nunca). te adjunto mi código para ver si te da alguna idea y si juntos podemos solucionar estos problemas, ya que haaartos dolores de cabeza me ha dado.
Algo que también mejora el desempeño del sensor es alimentarlo aparte del Arduino directamente para que lo tengas presente.

Te adjunto el link a mi post para que te hagas referencia donde está el código que he armado, ojalá postees aunque sea un OK ahí para mantener contacto ya que como ambos somos novatos, como no vamos a llegar a alguna parte entre 2 o no?

No me resulta poder armar una cadena de datos con lecturas de un sensor IR

(Si no es la forma de postear me disculpo, pero me cuesta aún el tema de los adjuntos y etc de este foro y estoy en proceso de aprender).

#include <SharpIR.h>

#define ir A0
#define model 20150

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

int ledrojo=13;
int lednaranja=12;
int ledverde=11;
int led;
int irState = LOW;


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){
    Serial.print("C=");
    Serial.println(contador3++);
    irState = HIGH;
    digitalWrite(ledverde,LOW);
    digitalWrite(lednaranja,LOW);
    digitalWrite(ledrojo,HIGH);
}
  if (dis<140&&dis>60){
Serial.print("B=");
Serial.print(contador2++);
    irState = HIGH;
    digitalWrite(ledverde,LOW);
    digitalWrite(lednaranja,HIGH);
    digitalWrite(ledrojo,LOW);
}
if (dis<50&&dis>30){
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;
  }
}

Ojo que yo probé con los capacitores y no tuve mucha variación, buscando en varias webs pude entender que el comportamiento "errático" y de respingo de mediciones es completamente normal (mi no enterder), entonces probé las mil y una formas y solo me quedó:

  • Alimentar por separado el sensor (y bajó un poco el error)
  • Mantener la misma luminosidad ambiental entre mediciones (no cambió nada)
  • Modifiqué el ángulo de la superficie de fondo que refleja la señal dejándo el sensor perpendicular a ella y mejoró bastante.

Después de varios intentos llegué a la conclusión de que además se demora unos buenos segundos en calibrarse (al rededor de 30 segundos después del encendido), pero lo curioso es que el rango es variable cada vez que lo enciendo... (mi nuevamente no entender)

@Litto veo que también tienes problemas con el "salto" que da en las lecturas. Si te fijas, hable del tema de los capacitores que el mismo fabricante recomienda soldar al sensor para así evitar ruidos que puedan crear malas mediciones e interpretarse como información.

Lee esta nota, así entenderás mejor el porque de las variaciones bruscas:

Litto:
Ojo que yo probé con los capacitores y no tuve mucha variación, buscando en varias webs pude entender que el comportamiento "errático" y de respingo de mediciones es completamente normal (mi no enterder), entonces probé las mil y una formas y solo me quedó:

  • Alimentar por separado el sensor (y bajó un poco el error)
  • Mantener la misma luminosidad ambiental entre mediciones (no cambió nada)
  • Modifiqué el ángulo de la superficie de fondo que refleja la señal dejándo el sensor perpendicular a ella y mejoró bastante.

Después de varios intentos llegué a la conclusión de que además se demora unos buenos segundos en calibrarse (al rededor de 30 segundos después del encendido), pero lo curioso es que el rango es variable cada vez que lo enciendo... (mi nuevamente no entender)

Ah ya probaste! pues segun entiendo lo que hace es solo "suavizar" no elimina por completo las variaciones...
según el comentario de @surbyte tienes que realizar promedios de los valores para asi tener medidas mas exactas o así entendí yo

Osea de suavizar... es de verdad insignificante el cambio, prácticamente no notñe que hubiese sucedido algo. Lo que pasa es que el rango de oscilación es muy inestable, por ejemplo supongamos que el rango es entre 30cms y 130cms, pero cada ciertos milisegundos salta bajo los 27cms y sobre los 142cms, y así diferentes variaciones, por lo que promediar es simplemente muy difícil ya que el rango del respingo es muy amplio y nunca conseguirás un valor certero màximo o mínimo por lo que ¿como promedias? siempre te dará un valor diferente.
Lo curioso es que se indica como un sensor de muy buena precisión sobre los ultrasonidos, y al menos esos sensores dan números mucho más cerrados. Si le pongo un muro a 30cms marca los 30cms, el Sharp marca 35... 27... 31... 33... y así variando cada vez aunque el objetivo esté fijo.
Es por este tema que insisto en creer que hay algo mal, no es posible que sea tan sucia la lectura ¿o no piensas tu lo mismo?

Dudo que seamos los únicos 2 trabajando con este sensor, o los únicos que lo notamos.