Hola gente como va? Me canse de leer foros y foros y no encuentro solucion. El codigo que mejor me funciona para leer rpm es el de Nick pero hasta 2500 rpm, luego se vuelve loco pega saltos a 22.000 RPM, no le encuentro explicacion, el codigo que use para las RPM es el Nick. Alguna sugerencia? La comunicacion serie esta a 115200, probe bajarla a 9600 y hace lo mismo, uso una pantalla nextion de 7 pulgadas. Alguna otra manera de leer RPM? Maxima frecuencia de los pulsos 200hz. Saludos
Y el código que estas utilizando cual es, también comparte las conexiones de lo que tengas montado porque yo lo utilizo en un motor de combustión de un corolla y lee correctamente hasta 6000 RPM que e probado, en teoría podría superar eso.Este es el que yo utilizo según lee correctamente hasta 200 kHz con el timer 4 de un Arduino mega.
// Frequency timer using input capture unit
// Author: Nick Gammon
// Date: 31 August 2013
// Input: Pin D8
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;
// if just missed an overflow
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;
// wait until we noticed last one
if (triggered)
return;
if (first)
{
startTime = (overflowCopy << 16) + timer1CounterValue;
first = false;
return;
}
finishTime = (overflowCopy << 16) + timer1CounterValue;
triggered = true;
TIMSK1 = 0; // no more interrupts for now
} // end of TIMER1_CAPT_vect
void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don't get a bogus interrupt
TCNT1 = 0; // Counter to zero
overflowCount = 0; // Therefore no overflows yet
// Timer 1 - counts clock pulses
TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select (rising on D8)
interrupts ();
} // end of prepareForInterrupts
void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
// wait till we have a reading
if (!triggered)
return;
// period is elapsed time
unsigned long elapsedTime = finishTime - startTime;
// frequency is inverse of period, adjusted for clock period
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 ns at 16 MHz
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop
Tal vez el problema este en la interfaz que este recortando los pulsos y no pueda seguir la frecuencia de 200Hz.
Gracias por responder, le saco el delay para que me muestre con fluidez las RPM pero aunque le agregue delay funciona mal igual (Pasando las 2500 rpm funciona mal).. Mañana voy a probar con PulseIn sino alguna otra forma, hara falta preescalarlo? Porque las rpm maximas no superan las 8000. el codigo es el siguiente:
// Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012
// Input: Pin D2
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 = bit (INTF0); // clear flag for interrupt 0
first = true;
triggered = false; // re-arm for next time
attachInterrupt(0, isr, RISING);
} // end of prepareForInterrupts
void setup ()
{
Serial.begin(115200);
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
// Timer 1 - interrupt on overflow
TIMSK1 = bit (TOIE1); // enable Timer1 Interrupt
// zero it
TCNT1 = 0;
overflowCount = 0;
// start Timer 1
TCCR1B = bit (CS10); // no prescaling
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
if (!triggered)
return;
unsigned long elapsedTime = finishTime - startTime;
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 ns at 16 MHz
int rpm = freq * 60;
n3.setValue(rpm);
prepareForInterrupts ();
} // end of loop
Por favor, no pierdas el tiempo con pulsein, no tiene nada que hacer para medir RPM, o en todo caso no es comparable con la precisión de la rutina de Nick Gammon.
No has puesto el esquema electrónico de como lees las RPM.
Usa etiquetas por favor.
Gracias!!
Creo que una R de 4k7 es demasiado alta. Baja a 470 ohms para tener un pulso mas fuerte y lograr una buena transferencia de LED a fototransistor.
La corriente nominal es de 50mA y tu estas en solo 2mA. Con 470 estarás en 20mA.
Ok, gracias. Sera por eso que funciona bien hasta ciertas RPM?
tienes el pulso muy debil y si miraras en un osciloscopio verías muy recortado los flancos de la salida del fototransistor, obviamente eso se traduce en una baja respuesta en frecuencia.
o traducido por eso lees mal a 200hz
Ok, en realidad leia mal a partir de 45hz!!!
Bueno ya nos contarás.
Hola surbyte, ya cambie la resistencia y hace lo mismo. A partir de 42hz anda mal!
Probe agregarle delay y sigue haciendo lo mismo.. Con el codigo que mas o menos funciona con saltos de 200 a 300rpm es con este:
volatile byte rpmcontador;
unsigned int rpm;
unsigned long tiempoanterior;
void rpm_contador()
{
rpmcontador++;
}
void setup()
{
attachInterrupt(0, rpm_contador, FALLING);
rpmcontador= 0;
rpm = 0;
tiempoanterior = 0;
}
void loop()
{
detachInterrupt(0);
rpm = 30*1000/(millis() - timeold)*rpmcount; // dos pulsos por revolucion.
tiempoanterior = millis();
rpmcontador = 0;
attachInterrupt(0, rpm_contador, FALLING);
}
Intenta con este tienes que conectar lo que quieres leer al pin D8 = 8
// Frequency timer using input capture unit
// Author: Nick Gammon
// Date: 31 August 2013
// Input: Pin D8
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;
// if just missed an overflow
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;
// wait until we noticed last one
if (triggered)
return;
if (first)
{
startTime = (overflowCopy << 16) + timer1CounterValue;
first = false;
return;
}
finishTime = (overflowCopy << 16) + timer1CounterValue;
triggered = true;
TIMSK1 = 0; // no more interrupts for now
} // end of TIMER1_CAPT_vect
void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don't get a bogus interrupt
TCNT1 = 0; // Counter to zero
overflowCount = 0; // Therefore no overflows yet
// Timer 1 - counts clock pulses
TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select (rising on D8)
interrupts ();
} // end of prepareForInterrupts
void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
// wait till we have a reading
if (!triggered)
return;
// period is elapsed time
unsigned long elapsedTime = finishTime - startTime;
// frequency is inverse of period, adjusted for clock period
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 ns at 16 MHz
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop
Ok, gracias. Ya te digo en un rato si funciona o no.
Podes revisar el codigo que no funciona? No muestra nada. Tendra algo que ver que tengo la comunicacion serie con la nextion y eso afecte en algo el muestreo?
Porque no pruebas el tema RPM y luego agregas la Nextion?
Ok, pruebo leer rpm con arduino solamente y te aviso
Hola Surbyte, te mande un mensaje privado por si podes ayudarme, leyendo solamente rpm funciona bien con la nextion, cuando pongo el codigo completo con los demas sensores falla.
No respondo preguntas técnicas por privado.