QRD1114 en Arduino

Hola a todos. Estoy con un pequeño proyecto para obtener las revoluciones por minuto de un coche de radiocontrol. Esta información sería muy útil para carburar bien el coche y obtener su máximo rendimiento en carrera. El caso es que he pensado en ponerle al coche un arduino nano, con un módulo bluetooth para enviar la información de temperatura y revoluciones a un PC y graficar en tiempo real. La parte de temperatura está superada con un LM35 y las comunicaciones inalámbricas también. He pensado en utilizar un QRD1114 para sensar rpm, pero la rueda a sensar puede girar hasta 35000 rpm...y temo que no tenga suficiente velocidad de respuesta. ¿Alguien ha hecho algo parcecido?

hola mira yo hecontre esta pagina no se si te sirbe yo no la entiendo suerte

Bueno...exactamente no porque debe tener el sensor dentro del cuerpo del ventilador y debe estar diseñado para poder alojarlo (a lo mejor es un sensor magnético que incorpora un imán, cosa que yo no puedo poner). Tendría que tener un ventilador de esos (que no lo tengo) e intentar abrirlo a ver si me vale algo... Por cierto, se me olvidó comentar que el coche de rc es de gasolina (no eléctrico) y no puedo poner nada en la rueda que gira (solo una banda negra con cinta aislante por ejemplo) para poder discriminar blanco-negro, por ello utilizo un fototransistor con un led emisor integrado.
Gracias de todas formas.

http://jmnlab.com/encoder/encoder.html

mira las gráficas del osciloscopio que determinan la velocidad máxima que puedes ver: cny70 Es decir durante todo el tiempo que se pone a uno o a cero el sensor debería estar viendo la línea debajo.

Si la rueda va muy rápido con hacer la línea más gruesa la podrías detectar.

Mira el datasheet del QRD1114 a ver si te pone el tiempo máximo en que tarda de pasar de 1 a 0 y al revés que es el dato que necesitas para hacer los cálculos.

¿Y no te seria mas interesante sacar la señal del mismo sitio de donde sale la chispa? Supongo que con una resistencia muy gorda podrás hacer que el voltaje baje lo suficiente para no freír la entrada. De este modo, con el Arduino solo tendrías suficiente. Creo que he visto algún hilo en el que hablaban de contar revoluciones de un coche o moto... me suena de un proyecto para saber qué velocidad tenía engranada una motocicleta...

Hola Profenas. Lo que me propones no es viable. Esos motores van sellados herméticamente para mantener una compresión, de ninguna manera puedo entrar al cilindro con nada. Solo puedo sensar alguna parte externa al motor, y que tenga alguna relación con las revoluciones del mismo. Hay una rueda dentada que gira con las vueltas del motor y desde donde se transmite la fuerza a las ruedas. Es lo más sencillo que he visto. Gracias por tu aporte de todas formas.
Voy a probar con el sensor que tengo y os pondré los resultados (despues de mis vacaciones...).
Saludetes

Yo estoy intentado usar el QRD1114 para desarrollar un anemómetro... si, ni de lejos llegará a las revoluciones por minuto del motor, pero los problemas me parece que son similares.

He estado revisando el datasheet del sensor, y lo único que he encontrado es esto:

Rise TimeVCE = 5 V, RL = 100 " tr — 10 — µs
Fall TimeIC(ON) = 5 mAtf — 50 — µs

lo que no se es a qué se refiere cada uno de esos tiempos...

también hay una distancia mínima (y máxima) a la que puede estar el disco de códigos (el de las líneas blancas y negras) para que lo lea éste sensor... pero no lo veo en el datasheet. En algún sitio de internet he leído que entre 0.5 y 1 cm. En mis pruebas es más bien 0.5 que 1, pero supongo que también depende de las condiciones ambientales.

En cuanto al disco de códigos, he comprobado que en principio es capaz de distinguir ente blanco y negro en un papel. Pero cuando le pongo bajo un disco de cógidos, el asunto ya no funciona tan bien... Me parece que la mejor solución es imprimirlo sobre una transparencia y pegarlo sobre un disco de metacrilato (o de cualquier plástico transparente suficientemente resistente).

también he visto que por la disposición del sensor, las líneas no pueden ser muy finas (yo he probado un disco de 16 espacios -7 y 9-). Y la verdad es que funciona, pero tengo que probar con discos de mayor resolución.

En tu caso ( y puede que en el mío), a lo mejor es preferible un disco con una única barra que indique una revolución completa, aunque tendremos el problema de cual debe ser su grosor para que pueda ser detectada a alta velocidad...

El código (si, muy muy muy básico) que estoy usando en las pruebas es este:

int val; 

# define IR 3

void setup()
{
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);
  Serial.begin(9600);      // sets the serial port to 9600
}

void loop() 
{
val = digitalRead(3);
Serial.println(val);
delay(10);
}

Bueno, estos son algunas ideas/problemas que me estoy encontrando yo y que puede que te resulten interesantes.

ACTUALIZADO:

Pues parece ser que sí, que si hay una distancia establecida en el datasheet (Figura 5). Parece que la distancia a la que es más sensible es entre 20 y 30 milesimas de pulgada (o algo así) que, según he leído por ahi viene a ser entre 0.7 y 1 mm... Habrá que confirmarlo...

Se refiere a los tiempos en que tarda en pasar a uno ó a cero el trt.

Vosotros lo que váis a ver va a ser algo similar a ésto, siendo la señal azul la salida del sensor:

El primero Rise TimeVCE = 5 V, RL = 100 " tr — 10 — µs

Se refiere que de pasar de 0 a 5 V tarda 10 us con una resistencia en el de carga de 100 Ohmios, cuanto mayor sea la resistencia mayor será el tiempo que tarde.

Es decir se refiere a este tiempo:

El segundo: Fall TimeIC(ON) = 5 mAtf — 50 — µs se refiere al tiempo que tarda el transistor en apagarse, es decir que la salida pase a 0 V cuando por el transistor circula inicialmente una corriente de 5 mA, cuanta más corriente circula mayor será el tiempo, si entramos en saturación óptica pues aún mayor.

Sería este tiempo:

El problema es que si la línea es muy pequeña y va muy rápido, t = s/v podemos llegar a tener el problema de que al transistor no le da tiempo a conmutar, y veremos una señal de este tipo en lugar de la primera imagen:

Es decir, un valor no válido para realizar una cuenta de pulsos en digital.

Por lo que tenéis que elegir el ancho de línea en función de la velocidad y la resistencia de carga que pongáis.

Las imagenes del osciloscopio son de un CNY70 que es otro sensor similar al que váis a usar con una resistencia de carga de 15k, la señal amarilla es una onda cuadrada que alimenta al diodo del sensor y la azul la salida del transistor, es decir lo que sería la entrada a vuestro arduino.

Resumiendo el tiempo = ancho de línea/velocidad a la que se mueva, no puede ser menor que los tiempos de subida y bajada para la resistencia de carga elegida. Influyen muchas más cosas (como la distancia, la orientación, el ruido, ancho mínimo de línea..), pero si no lo véis poned la resistencia lo más pequeña posible e id haciendo la línea más gorda.

Muchísimas gracias JMN por esta clase magistral!!!

La verdad es que te has explicado fenomenal y has dejado muy claro el asunto. Pues lo tendré en cuenta para ver como hago el diseño del circuito y de la rueda de códigos...

Muchísimas gracias!

de nada, me alegro que se me haya entendido xD

Para cualquier cosa en la que sepa ayudarte por aquí estoy, saludos.

JMN, explicación fantástica (clara y concisa). Hoy he estado en la tienda de electrónica y no tenían el QRD1114, me han dado en su lugar el CNY70. Como comenté voy a estar varios días fuera por lo que no pondré nada por aquí, pero cuando vuelva leeré todo lo que proponeis y me pondré manos a la obra. Saludetes

Por cierto, se me olvidó comentar una cosilla, viendo los gráficos propuestos por JMN, para conseguir que no se "triangule" la señal, supongo que lo más sensato es poner media rueda de blanco y la otra mitad de negro. De esta manera conseguiremos tener el máximo tiempo para que el sensor pueda reaccionar a los cambios.
Incluso, si rizamos el rizo, colocar más banda de un color en el tiempo que más penaliza (es decir, el más lento) ya sea de subida o de bajada, y menos en el que menos tarda. De esta manera conseguiremos hacer que lea las máximas RPM (optimizarlo a las características del sensor).

Tiene su gracia:

http://complubot.educa.madrid.org/sensores/anemometro/anemometro_index.php

Esto es del 2006

Gracias Complubot!

No conocía este proyecto vuestro. Mi idea es hacer algo parecido, pero lo más reducido posible, de menor coste y lo más resistente posible.

Ya he visto que usásteis una rueda de dos sectores... mi idea era que tuviera al menos 8 sectores para que sea capaz detectar vientos flojos también. Sin embargo he visto que una velocidad de 1 km/h requiere 40 vueltas de mi anemómetro en un minuto, así que a lo mejor puedo usar una rueda tan simple como la tuya y no liarme con tiempos de rotación, anchuras de sectores,...

Gracias por el link y las ideas!

Bueno, al final, he dejado un disco con un sector en blanco y otro en negro (en realidad el negro no existe, ya que lo he montado sobre un disco de metacrilato y parece que el transparente funciona como blanco al no reflejar el IR, y el medio círculo blanco funciona como negro al reflejar el IR... Puede ser porque lo he puesto demasiado cerca del sensor). Me funciona bastante bien. Ahora voy a ver si averiguo la velocidad máxima que es capaz de detectar( o al menos, a ver si es capaz de detectar la velocidad de 100 km/h, que es el máximo que me interesa...).

Gracias chicos por las ideas que me habéis aportado en este foro y con las que he podido desarrollar mi anemómetro, que llevaba tiempo teniendo en mente:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282599142

Espero que encontréis interesante el código y el hardware para vuestras aplicaciones (como la de medir las RPM de motor con la que empezó este hilo).

Muchas gracias de nuevo y suerte!

Hola a todos.
He estado liado y no he tenido tiempo de retomar el tema hasta ahora. Os comento.
Acabo de montar el sensor CNY70 con el siguiente programa:

volatile long tachCount = 0;
long time;
long rpm = 0;

void setup()
{
Serial.begin(115200);
attachInterrupt(0, tachPulse, RISING);
time = millis();
}

void loop()
{
//Runs every 1/4 second
//if (millis() - time >= 250)
if (millis() - time >= 1000)
{
// rpm = numero de vueltas en 250ms
// *4 se multiplica por cuatro para llevarlo a segundos
// *60 se multiplica por 60 para llevarlo a minuto
// /2 se divide en 2 porque son dos pulsos por cada rotacion (4 cilindros)
// /10 (Depende de la aplicacion)

//NOTA: YO OCUPE ESTA RUTINA PARA UN TACOMETRO Y NO FUE NECESARIO DIVIDIR
//EN 10 PRUEBEN USTEDES PERO YO LES RECOMIENDO NO DIVIDIR EN 10

//rpm = (((tachCount*4)*60)/2)/10;
detachInterrupt(0);
rpm = tachCount;

//aqui hacemos lo que queramos (mostramos en lcd, puerto serial, etc)
//
Serial.println(rpm);
tachCount = 0;
time = millis();
attachInterrupt(0, tachPulse, RISING);
}
}

void tachPulse()
{
++tachCount;
}

Como vereis he hecho varias pruebas hasta que al final lo único que quería ver es el número de interrupciones generadas al pasar de blanco a negro...el caso es que al leerlas en el COM, me sale un número elevadísimo y aunque genere los pulsos a la misma velocidad, cada lectura me salen datos muy distintos....parece como si se tratase de rebotes en un pulsador pero claro...en este caso no hay pulsador...¿alguna sugerencia?

Hola de nuevo.
Después de ver durante la noche algunas webs y andar masticándolo en la cama, he llegado a la solución.
El problema SI eran los rebotes que se producen en la entrada de interrupción del micro (pensaba yo que no....). se ha solucionado poniendo un inversor Schmitt-trigger a la salida del fototransistor junto con un condensador de 100nF. La señal que ataca al micro la tomo directamente de la salida del Schmitt-trigger. Todo esto lo he visto por ahí en webs por lo que no me voy a liar a poner fotos. El programa finalmente es el siguiente:

volatile long tachCount = 0;
long time;
long rpm = 0;

void setup()
{
Serial.begin(115200);
attachInterrupt(0, tachPulse, RISING);
time = millis();
}

void loop()
{
//Runs every 1/4 second
if (millis() - time >= 125)
{
// rpm = numero de vueltas en 125ms
// *8 se multiplica por cuatro para llevarlo a segundos
// *60 se multiplica por 60 para llevarlo a minuto
// Es un flanco de subida por cada rotación

rpm = tachCount860;

//aqui hacemos lo que queramos (mostramos en lcd, puerto serial, etc)
Serial.println(rpm);
tachCount = 0;
time = millis();
}
}

void tachPulse()
{
++tachCount;
}

Como veis, actualizo la cuenta cada 1/8 de segundo para que sea mas rápido...aunque no se si luego al montarlo le va a dar tiempo a la pantalla a refrescar a esa velocidad...será cuestión de probar.

El microcontrolador lleva un trigger schmitt en cada pin, por lo que no hace falta ponerlo externo, a lo mejor lo que te ayuda es el condensador que has puesto, que actúe como un filtro paso bajo, haz la prueba y quita el trigger a ver si con el condensador sólo se soluciona, puede ser que tengas mucho ruido, o la colocación del sensor, material que has usado para el negro, etc..