¿Método para determinar el valor de prescaler con error mínimo y los valores más altos para el timer1 de Arduino?

1

Si esta pregunta debería estar en StackExchange en lugar de aquí, puedo eliminar aquí y publicar allí.

Utilizando un Arduino Duemilanove (Atmega328) Estoy intentando generar una onda cuadrada (50% de ciclo de trabajo) de frecuencia en algún lugar entre 500 Hz y 200 KHz, tal como lo ingresó un usuario. No necesito ningún ciclo de trabajo de PWM variable, solo una simple onda cuadrada. Además, no puedo usar Timer0 ya que la modificación de eso afecta el retraso () y otras funciones relacionadas con el tiempo del Arduino.

Los cálculos del temporizador para el prescaler y el contador superior me confunden mucho. ¿Puede alguien indicarme un algoritmo para identificar qué combinación de prescaler y valores superiores dará la frecuencia de salida más cercana a la especificada? En muchos casos, dos o más combinaciones de prescaler y top dan resultados de frecuencia de salida similares pero ninguno es exacto.

Por ejemplo, el usuario ingresa un valor de 98350 Hz. ¿Cómo sabría mi código Arduino qué valor de prescaler y de contador superior para establecer los registros del temporizador 2, para la coincidencia más cercana a esa frecuencia?

    
pregunta ExcitingProjects

2 respuestas

2

El Arduino Playground biblioteca Timer1 hace lo que usted describe: configure Timer1 en cualquier período (es decir, 1 / f) está especificado. Puede examinar el código que se encuentra en GitHub para crear su propia versión o usar la biblioteca directamente.

Si usa Timer1 directamente, estas líneas generarán la onda cuadrada requerida del ciclo de trabajo del 50%:

#include <TimerOne.h>

setup() {
    pinMode(squareOut, OUTPUT);    // squareOut can be either 9 or 10 on Duemilanove
    Timer1.initialize();
    // Other set-up code
}

setFrequency(frequency) {
    Timer1.pwm(squareout, 512, (long) 1000000L / frequency); // Duty cycle = 0-1023
}

La biblioteca utiliza el método descrito por @JimParis en la respuesta anterior , para determinar los valores de prescaler y Top dentro de TimerOne :: setPeriod .

Si genera una versión más optimizada de ese bit de código de la biblioteca, compártala, ya que me gustaría usarla.

    
respondido por el Anindo Ghosh
2

Obtendrá el resultado más preciso utilizando el preescalador más pequeño que pueda. La única razón por la que no siempre puede usar el preescalador más pequeño es porque entonces el valor TOP no encajará en su registro de destino de 16 bits (como OCR1A). Así que el algoritmo general es:

  • Para cada valor de prescaler N (1, 8, 64, 256, 1024):
    • Calcular TOP = (f_clk / (N * f_pwm)) - 1
    • Si TOP < = 0xFFFF, has terminado.

(También querrá considerar los extremos; TOP = 0 o TOP = 1 probablemente no funcione para generar PWM, por ejemplo).

    
respondido por el Jim Paris

Lea otras preguntas en las etiquetas