[SOLUCIONADO] Problema al Leer RPM de automovil. Método de Nick Gammon

Hola a todos y muy agradecido desde ya por la ayuda que puedan brindarme.
Soy Ing. Mecánico desarrollando un proyecto para el cual necesito leer diferentes parámetros de un Automóvil, entre ellos las RPM y estoy teniendo problemas con estas lecturas.
Mi nivel de electrónica es medio-bajo, sin embargo entiendo de programación. Estuve revisando los foros y he visto que en ellos se recomienda mucho el MÉTODO DE NICK GAMMON para bajas frecuencias como las que se desarrollan en un Automóvil. Lo he descargado e instalado tal cual, la única modificación es que yo uso FALLING en lugar de RISSING para las interrupciones. Y las lecturas que muestra son inestables. Oscilan bastante.
Así que deduzco que en mi toma de datos algo está mal, para la toma de datos estoy usando un optoacoplador PC817 (ya que trabaja fácilmente con 20kHz).

Podrían ayudarme con saber que estoy haciendo mal? Me ayudarían muchísimo.
Estoy adjuntando el circuito que estoy usando para la toma de datos (los pulsos eléctricos).
lector_rpm_automovil 2.jpg

Es bueno aclarar que los datos se toman de la Bobina primaria, donde la conexión positiva de la bobina primaria es FIJA y el lado negativo es el pulsante (representado por SW1 en el esquemático).
Otro dato a considerar es que 3 pulsos equivalen a 2 vueltas. (por ser un auto de 3 cilindros). Sin embargo por lo pronto mi interés es tener una lectura confiable y estable de la frecuencia de pulso a pulso, para luego recién hacer la conversión o equivalencia a RPM de Automovil.

El Algoritmo creado por Nick Gammon del que hago mención es:

// Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// here on rising edge
void isr () 
{
  unsigned int counter = TCNT1;  // quickly save it
  
  // wait until we noticed last one
  if (triggered)
    return;

  if (first)
    {
    startTime = (overflowCount << 16) + counter;
    first = false;
    return;  
    }
    
  finishTime = (overflowCount << 16) + counter;
  triggered = true;
  detachInterrupt(0);   
}  // end of isr

// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect) 
{
  overflowCount++;
}  // end of TIMER1_OVF_vect


void prepareForInterrupts ()
  {
  // get ready for next time
  EIFR = _BV (INTF0);  // clear flag for interrupt 0
  first = true;
  triggered = false;  // re-arm for next time
  attachInterrupt(0, isr, FALLING);     
  }  // end of prepareForInterrupts
  

void setup () {
  Serial.begin(19200);       
  Serial.println("Frequency Counter");
  
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  // Timer 1 - interrupt on overflow
  TIMSK1 = _BV (TOIE1);   // enable Timer1 Interrupt
  // zero it
  TCNT1 = 0;     
  // start Timer 1
  TCCR1B =  _BV (CS10);  //  no prescaling

  // set up for interrupts
  prepareForInterrupts ();   
  
} // end of setup

void loop () 
  {  
  if (!triggered)
    return;
    
  unsigned long elapsedTime;
  float freq;
  int rpm;
  elapsedTime = finishTime - startTime;
  freq = 1.0 / ((float (elapsedTime) * 62.5e-9));  // each tick is 62.5 nS
  rpm = freq*60;
  Serial.print ("Took: ");
  Serial.print (elapsedTime);
  Serial.print (" counts.\t");

  Serial.print ("Frequency: ");
  Serial.print (freq);
  Serial.print (" Hz.\t");
  Serial.print ("RPM: ");
  Serial.println (rpm);

  // so we can read it  
  delay (250);

  prepareForInterrupts ();   
}   // end of loop

Quedo atento a sus comentarios y sugerencias.

lector_rpm_automovil 2.jpg

Las lecturas obtenidas (sin pisar acelerador, es decir en apenas Ralentí) son:

Frequency Counter
Took: 1843820 counts.	Frequency: 8.68 Hz.	RPM: 520
Took: 995830 counts.	Frequency: 16.07 Hz.	RPM: 964
Took: 338522 counts.	Frequency: 47.26 Hz.	RPM: 2835
Took: 92705 counts.	Frequency: 172.59 Hz.	RPM: 10355
Took: 97002 counts.	Frequency: 164.95 Hz.	RPM: 9896
Took: 340726 counts.	Frequency: 46.96 Hz.	RPM: 2817
Took: 111605 counts.	Frequency: 143.36 Hz.	RPM: 8601
Took: 457623 counts.	Frequency: 34.96 Hz.	RPM: 2097
Took: 512102 counts.	Frequency: 31.24 Hz.	RPM: 1874
Took: 575741 counts.	Frequency: 27.79 Hz.	RPM: 1667
Took: 606974 counts.	Frequency: 26.36 Hz.	RPM: 1581
Took: 607624 counts.	Frequency: 26.33 Hz.	RPM: 1579
Took: 623334 counts.	Frequency: 25.67 Hz.	RPM: 1540
Took: 609833 counts.	Frequency: 26.24 Hz.	RPM: 1574
Took: 638253 counts.	Frequency: 25.07 Hz.	RPM: 1504
Took: 621188 counts.	Frequency: 25.76 Hz.	RPM: 1545
Took: 634303 counts.	Frequency: 25.22 Hz.	RPM: 1513
Took: 128553 counts.	Frequency: 124.46 Hz.	RPM: 7467
Took: 631144 counts.	Frequency: 25.35 Hz.	RPM: 1521
Took: 127098 counts.	Frequency: 125.89 Hz.	RPM: 7553
Took: 629509 counts.	Frequency: 25.42 Hz.	RPM: 1524
Took: 128072 counts.	Frequency: 124.93 Hz.	RPM: 7495
Took: 633362 counts.	Frequency: 25.26 Hz.	RPM: 1515
Took: 127079 counts.	Frequency: 125.91 Hz.	RPM: 7554
Took: 643795 counts.	Frequency: 24.85 Hz.	RPM: 1491
Took: 129492 counts.	Frequency: 123.56 Hz.	RPM: 7413
Took: 644675 counts.	Frequency: 24.82 Hz.	RPM: 1489
Took: 126851 counts.	Frequency: 126.13 Hz.	RPM: 7567
Took: 647557 counts.	Frequency: 24.71 Hz.	RPM: 1482
Took: 644984 counts.	Frequency: 24.81 Hz.	RPM: 1488
Took: 129777 counts.	Frequency: 123.29 Hz.	RPM: 7397
Took: 126314 counts.	Frequency: 126.67 Hz.	RPM: 7600
Took: 639778 counts.	Frequency: 25.01 Hz.	RPM: 1500
Took: 126688 counts.	Frequency: 126.29 Hz.	RPM: 7577
Took: 639719 counts.	Frequency: 25.01 Hz.	RPM: 1500
Took: 127429 counts.	Frequency: 125.56 Hz.	RPM: 7533
Took: 637472 counts.	Frequency: 25.10 Hz.	RPM: 1505
Took: 127634 counts.	Frequency: 125.36 Hz.	RPM: 7521
Took: 646011 counts.	Frequency: 24.77 Hz.	RPM: 1486
Took: 126289 counts.	Frequency: 126.69 Hz.	RPM: 7601
Took: 639051 counts.	Frequency: 25.04 Hz.	RPM: 1502
Took: 134395 counts.	Frequency: 119.05 Hz.	RPM: 7143
Took: 655041 counts.	Frequency: 24.43 Hz.	RPM: 1465
Took: 128925 counts.	Frequency: 124.10 Hz.	RPM: 7446
Took: 651502 counts.	Frequency: 24.56 Hz.	RPM: 1473
Took: 127451 counts.	Frequency: 125.54 Hz.	RPM: 7532
Took: 630724 counts.	Frequency: 25.37 Hz.	RPM: 1522
Took: 638606 counts.	Frequency: 25.05 Hz.	RPM: 1503
Took: 657697 counts.	Frequency: 24.33 Hz.	RPM: 1459
Took: 657362 counts.	Frequency: 24.34 Hz.	RPM: 1460
Took: 512043 counts.	Frequency: 31.25 Hz.	RPM: 1874
Took: 653195 counts.	Frequency: 24.49 Hz.	RPM: 1469
Took: 134583 counts.	Frequency: 118.89 Hz.	RPM: 7133
Took: 653857 counts.	Frequency: 24.47 Hz.	RPM: 1468
Took: 132997 counts.	Frequency: 120.30 Hz.	RPM: 7218
Took: 649150 counts.	Frequency: 24.65 Hz.	RPM: 1478
Took: 133847 counts.	Frequency: 119.54 Hz.	RPM: 7172
Took: 138460 counts.	Frequency: 115.56 Hz.	RPM: 6933
Took: 661830 counts.	Frequency: 24.18 Hz.	RPM: 1450
Took: 515213 counts.	Frequency: 31.06 Hz.	RPM: 1863
Took: 644441 counts.	Frequency: 24.83 Hz.	RPM: 1489
Took: 655173 counts.	Frequency: 24.42 Hz.	RPM: 1465
Took: 126455 counts.	Frequency: 126.53 Hz.	RPM: 7591
Took: 643049 counts.	Frequency: 24.88 Hz.	RPM: 1492
Took: 126266 counts.	Frequency: 126.72 Hz.	RPM: 7602
Took: 556531 counts.	Frequency: 28.75 Hz.	RPM: 1724
Took: 130490 counts.	Frequency: 122.61 Hz.	RPM: 7356
Took: 134650 counts.	Frequency: 118.83 Hz.	RPM: 7129
Took: 681134 counts.	Frequency: 23.49 Hz.	RPM: 1409
Took: 520273 counts.	Frequency: 30.75 Hz.	RPM: 1845
Took: 523593 counts.	Frequency: 30.56 Hz.	RPM: 1833
Took: 641964 counts.	Frequency: 24.92 Hz.	RPM: 1495
Took: 675006 counts.	Frequency: 23.70 Hz.	RPM: 1422
Took: 126919 counts.	Frequency: 126.06 Hz.	RPM: 7563
Took: 628436 counts.	Frequency: 25.46 Hz.	RPM: 1527
Took: 126172 counts.	Frequency: 126.81 Hz.	RPM: 7608
Took: 628152 counts.	Frequency: 25.47 Hz.	RPM: 1528
Took: 130518 counts.	Frequency: 122.59 Hz.	RPM: 7355
Took: 672833 counts.	Frequency: 23.78 Hz.	RPM: 1426
Took: 129071 counts.	Frequency: 123.96 Hz.	RPM: 7437
Took: 659371 counts.	Frequency: 24.27 Hz.	RPM: 1455
Took: 521030 counts.	Frequency: 30.71 Hz.	RPM: 1842
Took: 652850 counts.	Frequency: 24.51 Hz.	RPM: 1470
Took: 516557 counts.	Frequency: 30.97 Hz.	RPM: 1858
Took: 133140 counts.	Frequency: 120.17 Hz.	RPM: 7210
Took: 132720 counts.	Frequency: 120.55 Hz.	RPM: 7233
Took: 131938 counts.	Frequency: 121.27 Hz.	RPM: 7276
Took: 535446 counts.	Frequency: 29.88 Hz.	RPM: 1792
Took: 132572 counts.	Frequency: 120.69 Hz.	RPM: 7241
Took: 132728 counts.	Frequency: 120.55 Hz.	RPM: 7232
Took: 668890 counts.	Frequency: 23.92 Hz.	RPM: 1435
Took: 666391 counts.	Frequency: 24.01 Hz.	RPM: 1440
Took: 533398 counts.	Frequency: 30.00 Hz.	RPM: 1799
Took: 515067 counts.	Frequency: 31.06 Hz.	RPM: 1863
Took: 524110 counts.	Frequency: 30.53 Hz.	RPM: 1831
Took: 128812 counts.	Frequency: 124.21 Hz.	RPM: 7452
Took: 126657 counts.	Frequency: 126.33 Hz.	RPM: 7579

Como dije son lecturas demasiado inestables y si acelero todo empeora.

Así que deduzco que en mi toma de datos algo está mal, para la toma de datos estoy usando un optoacoplador PC817 (ya que trabaja fácilmente con 20kHz).

Comparto tu opinión de que el circuito de entrada no esta actuando debidamente.

Mi consejo es que pongas un osciloscopio a ver esa salida y verifiques la calidad de los pulsos.
Te garantizo que con una entrada limpia el sistema funciona bien porque lo he usado y Gammon no propone cosas que no son.
Simplemente hay que hay separar las cosas, código y captura de datos de circuito electrónico conformador de la señal de entrada.

Hi,
Primero aqui creo yo haria un cambio y es de bajar la resistencia 1K que controla la corriente del optocoupler a una de 600 ohmios. La corriente del optocoupler diodo es de max 50 ma. Normalmente tu quires saturar la corriente de base del transistor para que no se abra/cierre al tener una corriente muy baja. Yo trataria una corriente de por lo menos 20ma. Asi estas seguro de que la base del transistor esta saturada. Segundo bajaria la resistencia del colector de 4K7 a una de 1K. La corriente tambien esta muy baja. Solamente sugerencias para tu consideracion. Por ultimo no se si esta instalado pero necesitas un condesador en paralelo con el switche. Este te va a eliminar los ruidos electricos que se generan al abrir/cerrar el contacto o lo que se conoce "bouncing".

surbyte:
Mi consejo es que pongas un osciloscopio a ver esa salida y verifiques la calidad de los pulsos.

Gracias Surbyte, lo tendré en cuenta. Analizaré la entrada de pulsos con un osciloscopio. Definitivamente es en la captura de pulsos del automóvil donde está el problema.

Creo que todos estamos de acuerdo que el problema es tu circuito, ademas de lo que te dijo @tauro, veo un error al conectar la entrada en el arduino, no entiendo porque conectas pull-up y pull-down al mismo tiempo, con esa configuración de resistencias, tienes aproximadamente 3 volts en el pin del arduino, quedando cerca de una zona indeterminada con lo que puedes obtener estados erróneos en la entrada, yo quitaría las resistencias de 10k que está conectada a gnd y la de 300 que va al pin digital, ademas de cambiar la de 4k7 por una de 10k.
Ahora una pregunta: ¿que tipo de sistema de encendido tiene ese motor? ¿es a platino y condensador o es electrónico?
Si es electrónico y tienes distribuidor con efecto hall, es mejor tomar la señal de ahí en lugar de la bobina de ignición

RIG, buena observación!!

tauro0221:
Primero aqui creo yo haria un cambio y es de bajar la resistencia 1K que controla la corriente del optocoupler a una de 600 ohmios. La corriente del optocoupler diodo es de max 50 ma. Normalmente tu quires saturar la corriente de base del transistor para que no se abra/cierre al tener una corriente muy baja. Yo trataria una corriente de por lo menos 20ma. Asi estas seguro de que la base del transistor esta saturada.

Interesante observación @Tauro0221, gracias! haré las pruebas con esas modificaciones.

tauro0221:
Por ultimo no se si esta instalado pero necesitas un condesador en paralelo con el switche.

Los autos ya tienen ese condensador instalado.

RIG:
no entiendo porque conectas pull-up y pull-down al mismo tiempo, con esa configuración de resistencias, tienes aproximadamente 3 volts en el pin del arduino, quedando cerca de una zona indeterminada con lo que puedes obtener estados erróneos en la entrada, yo quitaría las resistencias de 10k que está conectada a gnd y la de 300 que va al pin digital, ademas de cambiar la de 4k7 por una de 10k.

Hola RIG, gracias por responder! entiendo lo de la zona indeterminada, pero tengo una duda: Te refieres a que quite la resistencia 10k que va al gnd y el pin D2 este conectado directamente al gnd o que el pin D2 ya no tenga ningún contacto con gnd?
Yo la puse para garantizar que cuando no estén llegando los 5v del vcc el Pin D2 esté en LOW.

La de 300 ohmios la puse para que cuando conduzca el transistor del opto.. la corriente del vcc vaya directamente a gnd y no al pin d2. Está errónea mi lógica?

Otra duda. La de 4k7 por una de 10k?, nuestro compañero @Tauro acaba de sugierme que la disminuya más bien a 1k.

RIG:
¿que tipo de sistema de encendido tiene ese motor? ¿es a platino y condensador o es electrónico?

Es con encendido a modulo (transistorizado).

Hi,
La resistencia de 10K al pin de entrada de arduino se usa para descargar el voltaje rapidamente cuando el transistor del opto coupler se energiza y lleva la senal a ground. Esto ayuda al pulso bajar rapidamente cuando va de 5 voltios a ground. Esto no afecta en nada la senal de entrada al pin.
Otra sugerencia es de cambiar el opto coupler por uno que sea Schmitt trigger como H11L1MS. Esto te va a limpiar la senal de ruido. Adjunto foto de como trabaja el smichtt.

Una de las mejores alternativas y mas limpias es un acople inductivo.
Se trata de una bobina que enrollas alrededor del cable de la bobina haciendo que actue como antena.
Te pondré el dato del sitio donde lo encontré pero recuerdo haberlo intentado en época de secundaria y funcionaba bien. Si me preguntas cuantas vueltas... no recuerdo.

La bobina de la izquierda no es la bobina ignitora sino el arrollamiento sobre el cable de bobina. Es un acoplamientod inductivo.

Sigue el relato (fuente) y verás como el interesado va haciendo modificaciones para poder visualizar los cambios en un LED que luego reemplazaría por un optoacoplador. O sea tu enfoque.

tauro0221:
Esto ayuda al pulso bajar rapidamente cuando va de 5 voltios a ground. Esto no afecta en nada la senal de entrada al pin.

Así es. Pienso lo mismo.

He realizado los cambios que sugeriste Tauro y también quite la resistencia de 300 que entra al pin d2 (como sugirió RIG), pero manteniendo la resistencia de 10k tipo pull down . Y las lecturas se tornaron muy muy estables y con resultados coherentes.

No quiero apresurarme a confirmar que está resuelto el problema, sin antes realizar más pruebas con un tacometro (Ya que el auto de pruebas no lo tiene).
Hoy estaré haciendo esas pruebas y comento los resultados.

tauro0221:
Otra sugerencia es de cambiar el opto coupler por uno que sea Schmitt trigger como H11L1MS.

Que buen dato. Lo probaré también.

surbyte:
Una de las mejores alternativas y mas limpias es un acople inductivo.

La bobina de la izquierda no es la bobina ignitora sino el arrollamiento sobre el cable de bobina. Es un acoplamiento inductivo.

Acople inductivo! No se me había ocurrido, que ingenioso!
Ese circuito lo vi en otros foros, pero asumí que la bobina era la bobina ignitora y lo descarte porque no funciona cuando polo pulsante es el negativo. Si el pulsante fuera el positivo funcionaria bien!
En el caso de tomarlo como acople inductivo me parece muy buena opción.

Te refieres a que quite la resistencia 10k que va al gnd y el pin D2 este conectado directamente al gnd

Claro que no!! estarías provocando un corto circuito, me referia a eliminar por completo esa conexion

quite la resistencia de 300 que entra al pin d2 (como sugirió RIG), pero manteniendo la resistencia de 10k tipo pull down

Yo te sugerí quitar las 2 resistencias (no solo la de 300) y cambiar la de 4k7 por 10k, para lograr un buen PULL-UP... sigues teniendo un divisor de voltaje, por lo que no tienes ni PULL_UP ni un PULL_DW, si no algo a medias

La resistencia de 10K al pin de entrada de arduino se usa para descargar el voltaje rápidamente cuando el transistor del opto coupler se energiza y lleva la senal a ground

Vamos sacando calculos; digamos que el motor alcanza 10,000 R.P.M. (aunque lo dudo), si pasamos esto a revoluciones por segundo tenemos 166.6 R.P.S, bien, el distribuidor da media vuelta cada vuelta del cigueñal, entonces en el distribuidor tenemos 83.33 R.P.S, y por cada vuelta del distribuidor tenemos 3 pulsos, con esto tenemos como resultado un total de 250 pulsos por segundo a 10,000RPM.
Entonces:

¿descargar rápidamente descargar el voltaje rapidamente

para medir 250Hz?

Pones unas cuantas vueltas sobre el cable de ignición, un osciloscopio conectado a las puntas de esas vueltas. Mides la tensión inducida, estableces el nivel de la señal, le pones un AO, un smitch trigger y asunto resuelto.

Pero ese esquema tambien debería funcionar.

Hola a todos y muchas gracias por su ayuda. He conseguido resolver el problema.
Hice las modificaciones a mi circuito sugeridas por RIG y TAURO, es decir quedó así:
lector_rpm_conmodulo.jpg
Luego de hacer varias pruebas descubrí que con las correcciones mi circuito funciona perfecto para autos que trabajan con módulo (transistorizados), pero no funciona para autos con encendido a platinos y condensador.

Para autos con sistema de encendido a platino yo sugiero el método de Surbyte,

surbyte:
Pones unas cuantas vueltas sobre el cable de ignición, un osciloscopio conectado a las puntas de esas vueltas. Mides la tensión inducida, estableces el nivel de la señal, le pones un AO, un smitch trigger y asunto resuelto.

Un abrazo.

lector_rpm_conmodulo.jpg

1 Like