Hola! Estoy realizando un proyecto utilizando los perifericos del arduino Nano para generar un PWM con una frecuencia variable según el valor de voltaje de la entrada anlógica A0, la frecuencia se calcula según una fórmula que está realizando correctamente el arduino, coloqué un led en la salida 9 para verificar la salida de la frecuencia y estoy variando la entrada con el uso de un potencioemtro. La entrada es de 5V, tengo una resistencia Pull Down para la entrada digital del pin 7.
Les dejo el código a continuación, a ver si me pueden ayudar con el problema de porque la lectura no se mantiene, por ejemplo, la entrada cuando es de 2,5V debería haber una frecuencia de 3600Hz aproximadamente, entrega los 3600Hz pero de repente empieza a oscilar y baja a 2500Hz o 280Hz o sube a 3800Hz, ya intenté colocarle un filtro a la señal de entrada pero me sigue presentando la misma falla.
Gracias!!
// Declaración de variables
unsigned int conv = 0; // 16 bits
unsigned int maxPWM = 0; // 16 bits para el valor máximo de PWM
float frecuencia = 0; // Frecuencia
const int entradaPin = A0; // Pin de entrada analógica del potenciometro
const int salidaPin = 9; // Pin de salida para la frecuencia
const int arranquePin = 7; // Pin de entrada digital para la señal de arranque
void setup() {
// Inicialización del PWM y otros ajustes
inicializarPWM();
// Configuración de pines
pinMode(arranquePin, INPUT);
pinMode(salidaPin, OUTPUT);
}
void loop() {
// Lectura del estado del arranque
int estadoArranque = digitalRead(arranquePin); //Verifico el estado del pin de arranque para inicializar el código
if (estadoArranque == LOW) {
// Reseteo de valores y desactivación del PWM
resetearValores();
desactivarPWM();
} else {
// Volver a activar el proceso si el estado cambia a 0
inicializarPWM();
activarProceso();
}
delay(300);
}
// Función para inicializar el PWM y otros ajustes
void inicializarPWM() {
float f;
// Inicialización
TCCR1A = 0B10000000; //Cofiguración del IMER 1 como PWM con fase y frecuencia corregida
TCCR1B = 0B00010001; //Reloj del timer 16MHz, este prescalador permite la variación para mejorar la resolución
maxPWM = (16e6 / (2*f)) - 1; //Definiendo la frecuencia de la PWM
ICR1 = maxPWM; //Registro que permite establecer el valor máximo
OCR1A = maxPWM >> 1; //Dividiendo el valor máximo para 2
TIMSK1 = 0B00100000; //Interrupción cuando el Timer llegue a igualar al máximo, es decir a la mitad del periodo
sei();
}
// Función para resetear valores y marcar frecuencia en 0
void resetearValores() {
conv = 0;
maxPWM = 0;
frecuencia = 0;
}
// Función para desactivar el PWM
void desactivarPWM() {
conv = 0;
maxPWM = 0;
frecuencia = 0;
int f = 0;
int entradaPin = 0;
TCCR1A = 0; //Cofiguración del IMER 1 como PWM con fase y frecuencia corregida
}
// Función para volver a activar el proceso
void activarProceso() {
// Código para volver a activar el proceso
float potValue = analogRead(entradaPin) / 1023.0 * 5.0; // Lee el valor de la entrada analógica y conviértelo a voltaje
// Calcula RPM basado en el valor de la entrada analógica
float RPM = (potValue / 2.5) * 1800;
// Calcula la frecuencia
frecuencia = (RPM * 129) / 60;
// Actualiza la frecuencia si ha cambiado
if (frecuencia != maxPWM) {
float f;
maxPWM = (16e6 / (2 * frecuencia)) - 1;
ICR1 = maxPWM;
frecuencia = f;
}
}
ISR(TIMER1_CAPT_vect){
// Esta rutina de interrupción se ejecuta cuando el Timer 1 llega a igualar al máximo
conv = analogRead(entradaPin);
conv = map(conv, 0, 1023, 0, maxPWM);
OCR1A = conv;
}
