Entender este código control RPM motor

En segundo lugar, en la fórmula debes multiplicar el número de ticks por 600; no por 60, ya que estamos contando los ticks que se producen en una décima de segundo (delay 100 ms), no en un segundo.

... Lo que me lleva a pensar que con este sistema la variación va a ser sobre múltiplos de 600, con lo que la precisión no va a ser muy buena.

Por aquí se ha dicho varias veces, ahora que me acuerdo, que para bajas frecuencias es más efectivo calcular la frecuencia midiendo el tiempo entre ticks (periodo), y para altas contando ticks.

Echa un vistazo a este código de Nick Gammon.

Es deicr, si pongo el delay a 100, el de 60 tengo que ponerlo a 600. ¿Es lo que te refieres?

No se si le falta precisión, pero si funciona.

Por cierto, si el código anterior de arriba de delay a 1000 y el calc a 60 tiene más precisión, pues dejaré ese. ¿Cómo sabemos cuando tiene mñas precisión uno que el otro?

volatile long NbTopsFan; // contador de impulsos.
const long fandiv = 2; // dos pulsos por vuelta
const int hallsensor = 2; // pin 2, que está unido a interrupción 0.

void rpm ()     // se llamará cada vez que se pruduce la interrupción
{
 NbTopsFan++;
}

 
void setup()
{
 //pinMode(hallsensor, INPUT);
 pinMode(hallsensor, INPUT_PULLUP);
 Serial.begin(115200); // 115200
 attachInterrupt(0, rpm, RISING);
}
void loop ()
{
   NbTopsFan = 0;
   sei();   
   delay (100); 
   cli();
   long Calc = ((NbTopsFan * 600)/fandiv);
   Serial.print (Calc, DEC);
   Serial.print (" rpm\r\n");
}

voy a husmear el código del enlace que me dejaste.

Exactamente. Si en lugar de tomar muestra durante un segundo la tomas durante una décima, para calcular lo que corresponde a un minuto deberás multiplicar por 600 en lugar de 60.
Por lo tanto, un solo tick de más (o de menos) medido en esa décima de segundo, traspasado a minuto (rpm) se convierte en 600 pulsos, por lo que las rpm subirán en múltiplos de 300 (600/2 ticks por vuelta).
No he mirado el código de Nick, pero te garantizo que sacará partido al máximo de las capacidades del timer del arduino.

Me matan, gente, ustedes son increibles, hasta lo entendi casi todo con su explicacion, por que antes......... no entendia nada, gracias por compartir su sabiduria.
Saludos.

Por eso cuando mides frecuencias bajas el método no es el qeu usas, sino a la inversa, se mide período y luego se determina la frecuencia como la inversa.
Porque período, commo la lectura de un flanco de subida y otro de bajada. Porque usando un timer puedes hacerlo con mucha precisión, tanto como 62.5nseg por tick de medicion o 1/16Mhz = 62.5nseg
en 100 mseg entran 100 mseg/62.5nseg = 1.600.000 cuentas.
Que te parece Metanconta, algo preciso no? Claro que el Timer rebalsará o dará overflow pero por cada overflow incrementas otro contador y no pierdes nada.

No recuerdo bien donde estaba el limite entre medir por periódo y medir por ventana de tiempo (frecuencia), no estoy seguro si era 1Khz o 10kHz. De todos modos supongamos que fuera 1Khz.
Para una rueda dentada estamos lejos de ese limite y siempre debe leerse por periódo o bien incrementar la cantidad de dientes para poder medir por frecuenca pero con menor error.

Por ello insisto en el código de Nick Gammon, Ricardo. Mide el periodo de forma muy precisa y por lo que dicen en el hilo a frecuencias de 1kh es "super exacto", y llega hasta 99khz (aunque ahí ya hay algo de error), pero supongo que para frecuencias de 20 khz siga siendo muy aceptable.
Saludos.

Es exactamente por lo que expliqué.
Bajas frecuencias medir período.
Altas frecuencias medir frecuencia.

Hola:

Voy a probar el código de Nick.

/ 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, RISING);     
  }  // end of prepareForInterrupts
 

void setup () {
  Serial.begin(115200);       
  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 (CS20);  //  no prescaling

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

void loop ()
  {

  if (!triggered)
    return;

  unsigned long elapsedTime = finishTime - startTime;
  float freq = 1.0 / ((float (elapsedTime) * 62.5e-9));  // each tick is 62.5 nS
 
  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

Saludos.

Devuelve la frecuencia en Hercios, pero pasar a RPM supongo que no supondrá un hándicap insalvable. :grin: :grin: :grin:

¿Se puede mostrar Hz y RPM?

¿Cómo se hace?

Hz son ciclos x segundo
Rpm son revoluciones x minuto o vulgarme serian Hz expresados x minuto.

X rpm = revoluciones/min = revoluciones/60 seg = 1/60 Hz

Entonces un par de ejemplos:
120 rpm = 120/60 Hz = 2 Hz
600 rpm = 600/60 Hz = 10 Hz

En resumen, multiplica hercios por 60 y tienes rpm. Divides rpm por 60 y tienes hercios.

Buenas:

Hz es la unidad de medida de la frecuencia. Haré esos cálculos, que no solo se muestre en el seria, sino en una LCD 20x4 que haré más adelante.

Saludos.

Pero no nos dejes en ascuas. ¿Probaste ya con el código de Gammon?

JAjaa ajajaja, tankis, lo probaré y comentaré, no te preocupes. Vamos a ver como se comporta y les diré dicho comportamiento. Cada vez que pruebo un código creyendo firmemente lo que dice el creador, me encuntro sorpresas, por eso la experiencia es un grado.

Las cosas funcionan en el contexto de quien las crea.
TU crees repetir la situación pero nunca es la misma, por eso siempre estamos hablando en este foro.

Sino todos leeríamos las cosas en INTERNET y las podriamos repetir sin problemas.

¿? :o :o :o

Tan complicado no hablo Metaconta.

Las cosas funcionan en el contexto de quien las crea.
TU crees repetir la situación pero nunca es la misma, por eso siempre estamos hablando en este foro.

Sino todos leeríamos las cosas en INTERNET y las podriamos repetir sin problema.

Cada vez que vez algo en internet, intentas reproducirlo no? pero no siempre puedes. Porqué? Por que, no siempre reproduces el ambiente exacto de quien creó el tutorial. O te falta algo, que pasaste por alto, o no considerarte un detalle que luego se vuelve crucial.
Entonces, por eso digo: "Las cosas funcionan en el contexto (ambiente) de quien las crea". En el proceso de reproducirlas muchas veces cometemos errores.
Ejemplo: tu estas con esto y yo no puedo hacer funcionar un pequeño ESP8266, hasta que leí a gepd/maxid/jopapa quienes dijeron en alguna respuesta que hay que cambiar el firmware. Entonces ahi tienes. Mi contexto mi entorno no es el mismo de quien hizo el tutorial del ESP8266 y a mi no me funciona.
Se comprende ahora?