Problemas para mantener estable la lectura utilizando los Perifericos del arduino

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

He trasladado su tema de una categoría de idioma inglés del foro a la categoría International > Español @brailymarg.

En adelante por favor usar la categoría apropiada a la lengua en que queráis publicar. Esto es importante para el uso responsable del foro, y esta explicado aquí la guía "How to get the best out of this forum".
Este guía contiene mucha información útil. Por favor leer.

De antemano, muchas gracias por cooperar.

La variable conv debes declararla volatile porque se modifica tanto en la isr como fuera de ella.

// Declaración de variables
volatile unsigned int conv = 0;

¿Qué valor tiene la variable f?

    if (frecuencia != maxPWM) {
      float f;
      
      maxPWM = (16e6 / (2 * frecuencia)) - 1;
      ICR1 = maxPWM;
      frecuencia = f;
    }

Rta: 0

Ya tienes para ir corrigiendo... :wink:

Vale, coloqué la corrección que me recomendaste y me estoy fijando que el valor de la variable potValue que se supone me almacena el valor de entrada de A0 está variando infinitamente, a pesar de que el voltaje es constante.

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

En cuanto a la variable f , tiene el valor de la fórmula que se calcula en la función activarProceso()

Si, ese fragmento que te mostré es de activarProceso() y no veo donde f cambia de valor.
Además esa variable es local en el ámbito del if() y sería distinta a cualquier otra f declarada fuera de ese ámbito.
Revisa lo que te he mostrado en #3

[color=green]
Moderador:
Por favor, lee las Normas del foro y edita tu post#4 código/error usando etiquetas de código.

Ve a edición, luego selecciona todo el código que has publicado, lo cortas y click en (<CODE/>)


[/color]

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.