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.
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.
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.
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.
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.
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
}
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.