Programe un ATtiny13 como un oscilador de audio con frecuencia variable y ancho de pulso

7

Quiero crear un oscilador de onda cuadrada simple similar a lo que uno haría con un 555, pero quiero usar el soporte de PWM basado en interrupciones para controlar el ancho y la frecuencia del pulso.

He estado estudiando la hoja de datos, las API de AVR y los ejemplos de PWM que puedo encontrar, pero no he podido reunirlos todos.

¿Es posible crear un oscilador de este tipo con la funcionalidad AVR PWM incorporada y, de ser así, cómo? Un amigo mío hizo algo similar con un PIC de 8 pin.

Mi razonamiento es que obtendré sonidos interesantes al cambiar el ancho del pulso y, por lo tanto, la forma de onda a una frecuencia determinada. Similar a la forma en que funciona la Consola Atari Punk pero es de esperar de una manera más estable, es decir, cambiando el ancho del pulso, pero dejando la frecuencia constante o viceversa.

    
pregunta noise

4 respuestas

5

Esto debería llevarte bastante lejos y el resto lo puedes hacer con la hoja de datos. Comience a construir pieza por pieza, de blinky a forma de onda a forma de onda que cambia con el tiempo a tonos. Algunas fuentes pueden ayudar a filtrar y controlar las salidas de audio (LPF activo puede hacer ambas cosas perfectamente).

Sugiero volver con preguntas más específicas.

    
respondido por el tissit
3

El período de PWM está determinado por la velocidad de desbordamiento de su temporizador. Hay muchos ajustes en la sección de Modos de Operación para pensar. Si todo lo que desea hacer es generar una onda cuadrada de período constante, con un ciclo de trabajo variable, creo que querrá usar el modo CTC (Borrar temporizador en comparación). La idea básica es establecer OCR0A en el número de tics del temporizador hasta que desee que el pin cambie a continuación, y usar la interrupción Comparar coincidencia para cambiar ese valor para la próxima vez. Así que en avr-gcc se vería algo así como:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0; 


void setup_timer(double p_ms, double duty){
  TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
  TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100

  // ... do some stuff based on your CPU frequency
  // to define the csxx_bits of TCCR0B when the timer is running
  // and consequently, to set on_time_ticks and off_time_ticks
  OCR0A = on_time_ticks;
  TCCR0B |= your_settings_here;
}


void start_timer(){
  //start the timer running at the desired rate
  TCCR0B |= csxx_bits; 
}


int main(int argc, char **argv){
  double period_ms, duty_cycle;
  setup_timer(period_ms, duty cycle);
  start_timer();  
  for(;;){
    //spin or sleep or whatever
  }
}


ISR(TIM0_COMPA_vect){
  if(OCR0A == on_time_ticks){
    OCR0A = off_time_ticks;
  }
  else{
    OCR0A = on_time_ticks;
  }
}

Advertencia, este es un código no probado, pero creo que la idea es correcta. De ninguna manera es esta la manera única de hacerlo tampoco.

Por cierto, hay una cosa que debes saber sobre el ATTiny13. Solo se garantiza que el oscilador RC interno sea preciso dentro del 10% del piso de fábrica. Hay un proceso de calibración de usuario que puede seguir (descrito por una atmel appnote ) que se obtendrá Tienes un 2% de precisión para el ATTiny13. Si quieres hacerlo mejor, probablemente debas usar un chip que se adapte a un cristal externo ...

    
respondido por el vicatcu
3

No es una respuesta directa a su pregunta, pero esto puede ser apropiado y ofrecer algunas sugerencias -

Acabo de crear un oscilador controlado numéricamente (NCO) usando un ATmega uC y un DAC. Se utiliza una matriz de enteros para almacenar un ciclo de una forma de onda (tabla de ondas). Una fase acumulador (int largo) se utiliza para determinar la dirección de los datos de salida en el wavetable Cada interrupción del temporizador incrementa el acumulador de fase en un valor fijo. El incremento de fase determina la frecuencia.

En mi aplicación utilicé una tabla de ondas de 64 bytes que contenía un ciclo de una onda sinusoidal. Es fácil extender la tabla de ondas y agregar más resolución a las muestras. Mi nota de solicitud se encuentra en enlace

    
respondido por el jluciani
1

Básicamente, un PWM no cambia la frecuencia. Los PWM se utilizan principalmente para controlar la "intensidad" de una señal.

Para generar una interrupción para diferentes frecuencias, te sugiero que uses el temporizador en modo CTC.

Se ejecutará a su valor de comparación, alternará una interrupción, se borrará y se reiniciará, hasta que vuelva a ejecutarse a su valor de comparación ...

Tras cada interrupción, puede cambiar uno o más puertos y el resto del tiempo (el temporizador sigue funcionando automáticamente) puede ver sus entradas de cualquier tipo ...

Aún puede "modular" su onda cuadrada con un PWM para controlar la "ganancia". Pero uno de ellos debe hacerse "a mano" porque el ATtiny13 tiene un solo temporizador de hardware ...

    
respondido por el Nuischia

Lea otras preguntas en las etiquetas