Control de un ventilador de dos velocidades con PWM

Hola.

Estoy en proyecto para crear con Arduino un modulo de control para el encendido de un ventilador de dos velocidades.

La placa Arduino recibe la señal PWM en un rango de frecuencia X

La pregunta en concreto es cual es la frecuencia máxima que puede Recibir una placa Arduino, probablemente estoy trabajando entre KHz y MHz,

Ejemplo, al recibir una señal de 50 a 100 envía una señal high al relee n°1 para activar la velocidad 1 del ventilador, al recibir una señal de 101 a 150 envia una señal high al relee n°2 para activar la velociadad 2 del ventilador.

¿Cuál placa Arduino, qué modelo?

Cuando el prescaler está en 1:

fclk​ = 16 MHz.

La mínima separación entre dos capturas consecutivas sería un ciclo de reloj (1/fclk​), lo que significa que el temporizador puede capturar un cambio en cada nuevo ciclo de reloj.
Así que, la frecuencia máxima de la señal que se puede medir será la frecuencia del reloj del sistema dividida por dos

Para un reloj de 16 MHz:
Frecuencia máxima ≈ 16 MHz / 2 = 8 MHz.

elegoo uno r3

En concreto lo que necesito hacer es controlar un ventilador de 2 velocidades para enfriar un motor, tengo una señal PWM que varia la frecuencia dependiendo de la temperatura de un motor, mientras mas caliente la frecuencia es mas alta.

El ventilador se debe activar cuando la señal es de 10khz hasta 30khz, pero la velocidad 1 debe activarse entre 10khz y 20khz y la velocidad 2 entre 21khz a 30khz. fuera de ese rango el ventilador esta apagado.

tendrás alguna idea

Probablemente me puede servir, estoy esperando poder estar seguro con el rango de frecuencia con la que debo trabajar...

En concreto lo que necesito hacer es controlar un ventilador de 2 velocidades para enfriar un motor, tengo una señal PWM que varia la frecuencia dependiendo de la temperatura de un motor, mientras mas caliente la frecuencia es mas alta.

El ventilador se debe activar cuando la señal es de por ejemplo 10khz hasta 30khz, pero la velocidad 1 debe activarse entre 10khz y 20khz y la velocidad 2 entre 21khz a 30khz. fuera de ese rango el ventilador esta apagado.

tendrás alguna idea?

Porque das la misma respuesta?
Comienzas diciendo cual es la máxima frecuencia y luego te contentas con 20kHz?
Lee las normas del foro por favor, cuando preguntes hazlo aportando toda la información.
Los que aquí contestamos te aseguro que tenemos miles de respuestas, no hemos visto todo pero casi todo.
Con buena información obtienes la mejor respuesta. Te lo garantizo.

Busca Arduino INPUT CAPTURE de Nick Gammon y ahi tienes lo que necesitas, o sea como se mide una señal cuadrada de frecuencia desconocida.

Acabo de reescribir el código que me recomendaste... puedes echarle un ojo? aun no lo pruebo... mas tarde te cuento como me fue.

#include <Relay.h> // Incluir biblioteca de control de relés

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é

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 ();

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

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.on(); // Activar el relé 1 para la velocidad 1 del ventilador
    relay2.off(); // Desactivar el relé 2
  } else if (freq >= 21000 && freq <= 30000) {
    relay1.off(); // Desactivar el relé 1
    relay2.on(); // Activar el relé 2 para la velocidad 2 del ventilador
  } else {
    relay1.off(); // Desactivar ambos relés si la frecuencia está fuera de rango
    relay2.off();
  }

  prepareForInterrupts ();

Yo he usado la rutina y funciona perfecta. simple, le pones una frecuencia y la mides.
Te iba a hacer un comentario respecto de la activación o desactivación pero viendo la librería comprobé que no reenvía el comando cada vez que lo haces, sino solo cuando hay cambio de estado.
Tu código debería funcionar bien.

saludos como estas? tenia dias sin continuar con el proyecto hasta hoy.

el codigo que te pase me da el siguiente error; exit status 1

Compilation error: no matching function for call to 'Relay::Relay(const int&)'

justo en esta arte del codigo

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

no se que pudiera estar pasando.. realmente estoy experimentando con arduino...

El problema que tienes es que estas declarando los objetos dentro del void setup() y estos tienen que ser declarados de forma global, como no específicas que librería estas usando ni de donde la sacaste, voy a tomar la que encontré primero para mostrarte un ejemplo, esta es la que primero encontre Arduino Relay

#include "Relay.h"

Relay light(2, false); // constructor receives (pin, isNormallyOpen) true = Normally Open, false = Normally Closed

void setup() {
	light.begin(); // inicializes the pin
}

void loop() {
	light.turnOff(); //turns relay off
	light.turnOn();  //turns relay on
	bool isLightOn = light.getState(); //returns a bool, true = on, false = off
}

Acá te dejo un código que funciona pero repitiendo la solución de @Swift que no ví de lo contrario no hubiera hecho esto

Lo puedes simular, asi que ve por tu cuenta si se ajusta o no.Solo he hecho que funcione, nada ma.

Hola @ajavi3r

Como detectas la temperatura del motor y activas la frecuencia adecuada ???

Un saludo !!!... :cocktail:... :cocktail:

por medio de un sensor de temperatura, esa señal va a un modulo que genera la señal pwm que activa el ventilador y determina la velocidad

1 Like

gracias.... les comento como fue

Creo que hay un problema con lo que quieres hacer, la señal por lo general si es por PWM, pero la frecuencia es siempre fija, no varía, lo que cambia es el ancho del pulso o el Duty Cycle , por lo que necesitas medir el ancho del pulso necesitas modificarlo, si tienes capturas de la señal en el rango que está trabajando ayudaría bastante.