#include <Relay.h> // Incluir biblioteca de control de relés
                    // https://github.com/rafaelnsantos/Relay/tree/master

const int relay1Pin = 8; // Reemplace con el número de pin real del relé
const int relay2Pin = 9; // Reemplace con el número de pin real del relé

// Crear objetos de relé
Relay relay1(relay1Pin, true);
Relay relay2(relay2Pin, true);

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

// temporizador desbordamientos (cada 65536 conteos)
ISR (TIMER1_OVF_vect)
{
  overflowCount++;
}

ISR (TIMER1_CAPT_vect)
{
  // obtener valor del contador antes de que cambie más
  unsigned int timer1CounterValue;
  timer1CounterValue = ICR1; // ver hoja de datos, página 117 (acceso a registros de 16 bits)
  unsigned long overflowCopy = overflowCount;

  // si se perdió un desbordamiento
  if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
    overflowCopy++;

  // esperar hasta que notemos el último
  if (triggered)
    return;

  if (first)
  {
    startTime = (overflowCopy << 16) + timer1CounterValue;
    first = false;
    return;
  }

  finishTime = (overflowCopy << 16) + timer1CounterValue;
  triggered = true;
  TIMSK1 = 0; // no más interrupciones por ahora
}

void prepareForInterrupts ()
{
  noInterrupts (); // código protegido
  first = true;
  triggered = false; // rearmar para la próxima vez
  // restablecer temporizador 1
  TCCR1A = 0;
  TCCR1B = 0;

  TIFR1 = bit (ICF1) | bit (TOV1); // borrar banderas para que no obtengamos una interrupción falsa
  TCNT1 = 0;      // Contador a cero
  overflowCount = 0; // Por lo tanto, todavía no hay desbordamientos

  // Temporizador 1 - cuenta los pulsos del reloj
  TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrumpir en el desbordamiento del temporizador 1 y la captura de entrada
  // iniciar el temporizador 1, sin prescaler
  TCCR1B = bit (CS10) | bit (ICES1); // más Selección de borde de captura de entrada (ascendente en D8)
  interrupts ();
}

void setup ()
{
  Serial.begin(115200);
  Serial.println("Control de ventilador de dos velocidades");

  // configurar para interrupciones
  prepareForInterrupts ();
}

void loop ()
{
  // esperar hasta que tengamos una lectura
  if (!triggered)
    return;

  // el período es el tiempo transcurrido
  unsigned long elapsedTime = finishTime - startTime;
  // la frecuencia es inversa del período, ajustada por el período del reloj
  float freq = F_CPU / float (elapsedTime); // cada tic es de 62.5 ns a 16 MHz

  Serial.print ("Tomó: ");
  Serial.print (elapsedTime);
  Serial.print (" conteos. ");

  Serial.print ("Frecuencia: ");
  Serial.print (freq);
  Serial.println (" Hz. ");

  // para que podamos leerlo
  delay (500);

  // controlar los relés en función de la frecuencia
  if (freq >= 10000 && freq <= 20000) {
    relay1.turnOn(); // Activar el relé 1 para la velocidad 1 del ventilador
    relay2.turnOff(); // Desactivar el relé 2
  } else if (freq >= 21000 && freq <= 30000) {
    relay1.turnOff(); // Desactivar el relé 1
    relay2.turnOn(); // Activar el relé 2 para la velocidad 2 del ventilador
  } else {
    relay1.turnOff(); // Desactivar ambos relés si la frecuencia está fuera de rango
    relay2.turnOff();
  }

  prepareForInterrupts ();
}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module