[SOLUCIONADO] Leer RPM de motor de Coche

que interesante.. me apunto a ver que resulta.!!
yo no se nada de programacion.. y algo poco en la parte elec..

lo que si te puedo decir es que existen muchos tipo distintos de encendido en los automoviles.. ya sea si es el sistema mas antiguo de encendido con platinos, luego los que llevan un sensor hall en el distribuidor (ambos dan un pulso por cilindro cada dos vueltas) o los un poco mas sofisticados que dicho sensor va al volante de inercia y mide alrededor de 32-60 impulsos por vuelta, ademas de ser miltipunto o de chispa perdida.. en este caso lo mejor es sacar la señal del OBDII

si el vehiculo es de encendido por platinos se pueden tener picos altos en la entrada del primario de la bobina cuando se abre el platino.. por eso hay que saber para que tipo de encendido es tu Shift Light..

a mi me gustaria hacer uno para una moto de un cilindro pero 2T

Saludos

westay, este es mi coche. El tipo de motor es un F4R que de origen da 182cv.
El modelo exacto es Clio II Sport, la última fase que salió, las primeras tenían 172cv.
Los sistemas de encendido y demás deben ser idénticos en todos los Clio II Sport asi que es cuestión de investigar el tipo de encendido de cualquiera de ellos.

Ya tengo la protoboard montada.
He intentado probarlo conectando otro arduino que pone el pin5 en HIGH de manera intermitente (como un "blink").
¿Debería funcionarme esa prueba? o ¿estoy haciendo una tontería? o ¿Tiene lógica pero lo he montado mal?
No he conseguido resultado satisfactorio por el momento, siempre obtengo "0 RPM".

Edito tras hacer unas pruebas. Si conecto directamente el pin del otro arduino despues de R2 funciona!!! algo es algo. Me lee las "RPM" (pulsos que emite el otro arduino) perfectamente.

Si lo conecto en cualquier otra parte, no llega al final del camino (supongo que no llega despues del octoacoplador).

He probado con un tester y mi poco conocimiento y veo que despues del segundo diodo, no sigue la corriente. Eso es lo primero que detecto. En C1 no mido nada de corriente.
Sin tener ni idea, veo que los diodos están "enfrentados", y la función del diodo es que la corriente fluya en una sola dirección (creo), por lo que no continua hacia delante. ¿puede ser?

Aun asi, tambien he detectado que si le pongo 5v directamente en la entrada del optoacoplador, al otro lado no veo resultados. Creo que algo me falta en esa parte tambien. Quizá algún positivo.

Bueno, vamos por partes, como jack el destripador! Que gracias a vosotros voy poco a poco avanzando.

Un saludo!

deberias colgar los codigos.. el que tienes en el uno y el del nano..
Mediste si los 5V provenientes del nano logran encender el optoacoplador y enviar la señal al uno??

westay:
deberias colgar los codigos.. el que tienes en el uno y el del nano..
Mediste si los 5V provenientes del nano logran encender el optoacoplador y enviar la señal al uno??

Hola westay, acabo de editar el post con unas pruebas, un saludo!

Si como dice el amable jack por partes.

Mikel1985:
He probado con un tester y mi poco conocimiento y veo que despues del segundo diodo, no sigue la corriente. Eso es lo primero que detecto. En C1 no mido nada de corriente.
Sin tener ni idea, veo que los diodos están "enfrentados", y la función del diodo es que la corriente fluya en una sola dirección (creo), por lo que no continua hacia delante. ¿puede ser?

Los diodos se encuentran enfrentados porque no son el mismo tipo de diodos el primero que va en la direccion correcta es un diodo rectificador que cumple la función que decís dejar pasar en un solo sentido la corriente (en este caso en la dirección de nuestro opto acoplador que es lo que queremos), sin embargo el otro diodo como lo ves se encuentra en sentido inverso en teoría según lo que sabes evitaría que fluya la corriente, sin embargo este no es un tipo cualquiera de diodo sino que es un diodo zener de 4.7V por lo tanto te explico asi de manera basica lo que hace.

Ese tipo de diodo es como un diodito normal evita el flujo o lo permite sin embargo si se polariza inversamente es decir esta evitando el flujo y ese voltaje de polarización inversa supera su voltaje umbral que para este diodo es un poquito mas arriba de 4.7V pues en ese caso el diodo empieza a conducir dejando entre sus bornes ese voltaje, por ende la prueba que estas haciendo no debería de funcionar recuerda que se diseño para 12V así 5 quedan en el zener otro poquito en la resistencia y el resto prende el optoacoplador para hacer pruebas intenta quitar el zener y nos comentas como te fue, espero que en tus pruebas no hayas colocado los 5v del micro en la patica que lleva el cable blanco del capacitor c1 porque si es asi lo mas probable es que hayas quemado el diodo del optoacoplador.

Y otra cosita Mikel como dice Westay cuelga los codigos que tienes corriendo asi podemos verificar otras cosas yo por ejemplo quiero ver si prendiste las resistencias de pull up del micro como te recomende

Eres un crack,
por un lado quemé el LED que lleva el optoacoplador (o eso creo jeje) ya que conecté directamente 5v a esa patita para probar. Leyendo por internet aprendí que hay que pasar por resistencia si o si o te cargas el LED interno.
He cambiado el optoacoplador por otro nuevo y poniendo una resistencia... funciona desde ahí!
He ido yendo hacia atras y efectivamente el "tapón" se produce en ese punto que comentas. Muchisimas gracias por la explicación, no se si eres consciente pero me estas haciendo aprender un montón de cosas!

Aplicando tu teoría le he dado la vuelta al diodo zener, y efectivamente así si que funciona dejando todo lo demás igual.
Por tanto, ahora la cuestión es probar así con mis 5V (supongo que no hay problema... verdad?) y una vez que tenga el programa perfecto darle la vuelta al zener y enchufarle los 12V.

Si estoy haciendo alguna chapuza me lo dices!

Ahora el problema, sin revisar aún el código, es que me da algunas lecturas "falsas":

  • El valor correcto para los pulsos que le estoy metiendo es exactamente 600 RPM

600 RPM
600 RPM
600 RPM
600 RPM
600 RPM
600 RPM
1200 RPM
1800 RPM
2400 RPM
....
..
600 RPM
600 RPM
600 RPM
600 RPM
600 RPM
600 RPM

Toca liarme con el código o puede ser debido a otra cosa?

volatile unsigned long timePointsOpen, timePointsClosed, lastChange;
volatile unsigned int numBangs;

void pointsOpening(){
    unsigned long t;
    t = millis();
    if (lastChange > 0){
        timePointsClosed += (t - lastChange);
    }
    lastChange = t;
    ++numBangs;
}

void setup(){
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);
  Serial.begin(9600);
  Serial.print("Inicializado ");
}

void loop(){
  // Number of coil pulses
  numBangs = 0;
  attachInterrupt(0, pointsOpening, RISING);
  delay(50);
  detachInterrupt(0);
  numBangs = ((60000/50)*numBangs)/2;
  Serial.print("RPM: ");
  Serial.println(numBangs);
}

La sentencia digitalWrite(3, HIGH) no activa el Pull up? No sé si en el otro pin hay que hacerle algo tambien (el 2 de las interrupciones)

:slight_smile:

Es con gusto y que bien que estes aprendiendo algo de electronica, listo me alegra que haya funcionado por ahora volteando el zener, en efecto la idea seria que cuando hagas la prueba vuelvas y lo dejes como es de lo contrario te vuelves a cargar el optoacoplador.

Mi recomendación seria que antes de hacer la prueba con la bobina del carro, convirtieras los 5v que te salen del arduino en 12V y se lo entraras a este esquema con el zener en la pocision que es, asi si no funciona toca revisar los valores de las resistencias y si funciona asi pero no en el carro sabremos que la bobina no trabajaba de la manera bonita como creiamos ahora si funciona en ambos jejeje hacemos fiesta.

Con respecto al problema que mencionas creo que ya es de software, le pegare una mirada y si detecto algo te comento XD.

Otra cosita pon el codigo que tienes cargado en el otro arduino porfa, y me podes explicar como funciona eso de las RPM es decir que indica cada pulso y de donde sale esa formula que tenes ahi:

 numBangs = ((60000/50)*numBangs)/2;

Así me hago a una idea de si el código corre bien o esta mal diseñado.

El delay que le meto es 50, para que se muestre el mensaj cada X tiempo. , en ese lapso de tiempo se suceden pulsaciones detectadas por las interrupciones. Se van contando y luego hago esa maravillosa operación para calcular cuantas pulsaciones se sucederian en un minuto.

Seguro que hay mil formas mejores!

El código del otro arduino es el Blink que viene de ejemplo, luego pongo el código no obstante.

Lo de maravilloso código era sarcasmo jeje

Edito añadiendo el código del otro arduino:

void setup() {
  // Pin que enviará los pulsos
  pinMode(5, OUTPUT);
}


void loop() {
  digitalWrite(5, HIGH);   // ON
  delay(30);              
  digitalWrite(5, LOW);    // OFF
  delay(20);             
}

Un par de puntualizaciones.

Tu fórmula se podría simplificar bastante: numBangs = ((60000/50)numBangs)/2 = (1200numBangs) /2 = 600*numBangs. A partir de la fórmula reducida, podemos darnos cuenta de lo que explico a continuación.

A bajas revoluciones, es más preciso medir el tiempo entre dos pulsos. A altas revoluciones contar el número de pulsos en un determinado tiempo. En tu ejemplo, la diferencia entre recibir un pulso o dos en el periodo de 50 milisegundos, equivale a 600 o 1200 rpm. No hay término medio. Además, activas y desactivas la interrupción en cada loop. No sería raro que al reactivar la interrupción salte ésta inmediatamente, y no porque se produzca en ese momento una transición del pin, sino porque algún registro de estado esté alterado previamente. Por ello considero más apropiado activar la interrupción en el setup y dejarla activada; a la par que utilizar millis() o micros() en lugar de delay para la temporización.

Acá tenes un buen circuito, simple y efectivo
la bobina representa el primario de la bobina de ignición.

espero sirva.
Nunca voy a entender un circuito presentado en el protoboard como uds lo hacen. Pero es una cuestión de adaptación porque cada vez lo veo mas común.

Amplio el comentario apropiado de Noter.
Tiene mucha razón. Pero esto extendido a la electrónica en general.
Cuando estudias mediciones te explican porque cuando se miden señales lentas se debe leer el período de la señal y cuando son rápidas se mide la frecuencia de la señal.
Aun cuando un auto desarrolle 10.000 rpm sigue siendo lento porque son apenas 10000/60 = 166Hz o sea solo 6 mseg
entonces siempre siempre medir intervalo entre flancos. O sea una interrupción, y la siguiente.

Si buscan rpm Nick Gammon tiene una buena forma de hacerlo usando los 62.5nSeg del reloj del Arduino que corre a 16Mhz, asi que una buena lectura con un reloj a 62.5nseg dará para digamos

usaré valores que dan enteros
600 rpm = 600/60 Hz = 10 Hz => 100mseg
100mseg/62.5nseg = 1.600.000 pulsos
O sea.. si cuento pulsos o ticks del timer al máximo reloj, tendré 1600000 pulsos. PRECISO NO

ahora si fueran 6000 rpm o 1000 Hz = 1mseg entonces tendré 16000 pulsos

tambien puedo contar varios pulsos RPM y promediar la lectura lo que disminuye el error.
Bien, ya saben o creo que saben como encararlo para leer como se debe.

Busquen en google: RPM Nick Gammon para usar la libreria/sketch que les comenté.

Esta vacano el circuito que comentas surbyte, sin embargo preferiría el que puso el dado el aislamiento galvanico que posee, solo por cuestiones de seguridad por otro lado yo tambien estoy mas acostumbrado a los diagramas pero mikel lo necesitaba en protoboard así que no hubo de otra, coincido en que no es recomendable estar activando y desactivando la interrupción en el arduino y que en ves de contar la cantidad de pulsos en un intervalo de tiempo es preferible contar el lapso entre los flancos sin embargo con el código que el esta usando, esta haciendo ambas cosas contando el numero de pulsos en el intervalo de 50 ms y contando el lapso de tiempo entre flanco y flanco solo que esta ultima funcionalidad no la está utilizando sin embargo no es duro que la implemente ya que solo tendria que enviar en ves de numbangs, (30/timePointsClosed) y listo que tal si lo pruebas y nos comentas mikel.

noter:
Un par de puntualizaciones.

Tu fórmula se podría simplificar bastante: numBangs = ((60000/50)numBangs)/2 = (1200numBangs) /2 = 600*numBangs. A partir de la fórmula reducida, podemos darnos cuenta de lo que explico a continuación.

A bajas revoluciones, es más preciso medir el tiempo entre dos pulsos. A altas revoluciones contar el número de pulsos en un determinado tiempo. En tu ejemplo, la diferencia entre recibir un pulso o dos en el periodo de 50 milisegundos, equivale a 600 o 1200 rpm. No hay término medio. Además, activas y desactivas la interrupción en cada loop. No sería raro que al reactivar la interrupción salte ésta inmediatamente, y no porque se produzca en ese momento una transición del pin, sino porque algún registro de estado esté alterado previamente. Por ello considero más apropiado activar la interrupción en el setup y dejarla activada; a la par que utilizar millis() o micros() en lugar de delay para la temporización.

Efectivamente la fórmula debería estar simplificada como bien dices, y el cálculo es el mismo. El problema de 600 a 1200 y todo esto está relacionado con los 50 ms, he probado a quitar el delay y me dá todo el rato, sin oscilar. Bueno, realmente me da 600rpm 0 rpm 600rpm 0 rpm...
Me interesa mucho la última parte que dices, si puedes echarme un cable inserto el código necesario y lo pruebo!

surbyte:
Acá tenes un buen circuito, simple y efectivo
la bobina representa el primario de la bobina de ignición....
...
....

No dudes que insestigaré todo lo que has expuesto, ya he buscado en google los códigos de nick gamon.

firius2010:
Esta vacano el circuito que comentas surbyte, sin embargo preferiría el que puso el dado el aislamiento galvanico que posee, solo por cuestiones de seguridad por otro lado yo tambien estoy mas acostumbrado a los diagramas pero mikel lo necesitaba en protoboard así que no hubo de otra, coincido en que no es recomendable estar activando y desactivando la interrupción en el arduino y que en ves de contar la cantidad de pulsos en un intervalo de tiempo es preferible contar el lapso entre los flancos sin embargo con el código que el esta usando, esta haciendo ambas cosas contando el numero de pulsos en el intervalo de 50 ms y contando el lapso de tiempo entre flanco y flanco solo que esta ultima funcionalidad no la está utilizando sin embargo no es duro que la implemente ya que solo tendria que enviar en ves de numbangs, (30/timePointsClosed) y listo que tal si lo pruebas y nos comentas mikel.

Efectivamente, en este topic andan bailando protoboards arriba y protoboards abajo por mi poco conocimiento de electrónica... y menos mal que me echaste un cable!
En cualquier caso creo que está bien que consten esos dibujos de protoboard por si alguien con mis mismos conocimientos se pasa por aquí.

Si te refieres a mostrar 30/timePoinstsClosed como valor final de RPM, muestra siempre 0.

Y ahora lo mas importante en este momento... no me funciona!
Me he dado cuenta de que me funcionaba porque le hice una chapucilla.

Plan original:

  • No lee nada:

chapuza:

  • Al menos leía (y me servía a mi al principio para ver el led parpadear a cada pulso):
    *Notesé que moví tambien la última resistencia de pin, que igual no se ve a primera vista

Este es el dibujo del optoacoplador:

Un saludo!

En cualquier caso actualizo con un nuevo código, que me ha funcionado mejor. Siguiendo un poco consejos que me habéis dado, o eso he intentado, a ver si lo veis mejor... o peor!

float revs;
float rpm;
volatile byte rpmcount;
long previousmicros = 0;
long interval = 100000;


void setup() 
{
  // setup serial 
  Serial.begin(9600);
  // setup pins
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);
  
  // setup interrupt
  attachInterrupt(0, RPM, RISING);

}

void RPM()
{
  rpmcount++;
} 

void loop() 
{
  unsigned long currentmicros = micros();
  if (currentmicros - previousmicros >= interval)  {
    previousmicros = currentmicros;
    detachInterrupt(0);
    rpm = 600*rpmcount;
    Serial.print("pulsos\t");
    Serial.print(rpmcount);
    Serial.print(" rpm\t");
    Serial.println(rpm);
    rpmcount=0;
    attachInterrupt(0, RPM, RISING);
  }
}

Y pongo un nuevo "esquema" con el que he conseguido que funcione todo y no de lecturas falsas. C2 puesto da lecturas falsas, C2 quitado va casi perfecto! Lo que supongo es que estaba por algo y yo la estaré liando... ¿verdad?

He programado un display para ver los resultados cuando lo conecte al coche. En breve os lo enseño!

No te preocupes, no hay ningún problema con que hayas quitado a C2. Que bien que te este dando, te comento que probe el circuito usando 12V con el zener puesto y funciona ojala ya conectado al carro en la bobina y con el display todo ande.

firius2010:
No te preocupes, no hay ningún problema con que hayas quitado a C2. Que bien que te este dando, te comento que probe el circuito usando 12V con el zener puesto y funciona ojala ya conectado al carro en la bobina y con el display todo ande.

Probado y funcionando :slight_smile:
Luego hago mas pruebas!

Que bien, felicidades :slight_smile: no olvides cambiar el asunto del post a solucionado.

Oki, voy a intentar poner el tema como solucionado.
Dejo un último video, si sabéis como dejarlo incrustado para que se vea directamente... en otros foros suele ser .. .
Ya le puse unos leds, que es el objetivo real.

Ahora lo haré con un arduino nano. Cuando esté finalizado y montado en el interior, subiré un video en marcha.

Muchisimas gracias por todo firius, sin tí no hubiese sido posible, si puedo hacer algo no dudes nunca en enviarme un privado ¿ok?

Saludos!

PD: Gracias también a todos los que han participado en este post, todo lo que habéis puesto me ha servido de mucho.

firius2010:
Que bien, felicidades :slight_smile: no olvides cambiar el asunto del post a solucionado.

Aquí el resultado final:

Vídeo
Shift Light: https://youtu.be/Cgg11_2mKxs

Tablero para configurar varias opciones.(la parte izquierda es lo que le he hecho yo).

1 Like