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

8

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

He estado estudiando la hoja de datos, las API de AVR y cualquier ejemplo de PWM que pueda encontrar, pero no he podido reunirlo todo.

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

Mi razonamiento es que obtendré sonidos interesantes al cambiar el ancho del pulso y, por lo tanto, la forma de onda a una frecuencia dada. Similar a cómo funciona la consola Atari Punk, pero con suerte de una manera más estable, es decir, cambiando el ancho del pulso, pero dejando la frecuencia constante o viceversa.

ruido
fuente
2
¿podría aclarar cuál es su pregunta?
Jason S
No estoy seguro de lo interesantes que serán, pero es fácil de probar y puedes juzgar. A medida que el pulso se estrecha, las amplitudes de los armónicos aumentan. Siga reduciendo el pulso y obtendrá un ruido blanco. Creo que tendrías opciones más interesantes haciendo un oscilador controlado numéricamente. Puede cambiar las formas de onda cargadas en la tabla de ondas.
jluciani

Respuestas:

5

Estos deberían llevarte bastante lejos y el resto lo puedes hacer con la hoja de datos. Comience a construir pieza por pieza, desde parpadeante 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.

Tissit
fuente
4

El período de PWM está determinado por la tasa de desbordamiento de su temporizador. Hay muchas configuraciones en la sección 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 Comparar coincidencia). La idea básica es establecer OCR0A en el número de tics del temporizador hasta que desee que el pin se active a continuación, y use la interrupción Comparar coincidencia para cambiar ese valor la próxima vez. Entonces, 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 única forma de hacerlo tampoco.

Hay una cosa que debes saber sobre el ATTiny13, por cierto. El oscilador RC interno solo garantiza una precisión dentro del 10% del piso de fábrica. Hay un proceso de calibración del usuario que puede seguir (descrito por una nota de aplicación de atmel ) que lo llevará a una precisión del 2% para el ATTiny13. Si quieres hacerlo mejor que eso, probablemente necesites usar un chip que acomode un cristal externo ...

vicatcu
fuente
1
Su respuesta ayudó a aclarar algo similar con lo que estaba teniendo problemas, gracias. Solo un punto (para cualquiera que lea esto mucho después del hilo original): su elección de 0b100 para WGM0 [2,1,0] no establecerá el modo CTC. (De hecho, establecerá un modo reservado por Atmel). La hoja de datos ATtiny13 dice que el modo CTC necesita el valor 2; accidentalmente le has dado bit_number 2 en su lugar (es decir, valor 4). Debido a eso, también es necesario no solo cambiar (es decir, borrar) WGM02 en TCCR0B sino también establecer los bits WGM01 y WGM00 en 1 y 0 respectivamente. Esos bits están en TCCR0A, por lo que no es suficiente establecer TCCR
3

No es una respuesta directa a su pregunta, pero esto puede ser apropiado y proporcionar algunas pistas:

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). Se utiliza un acumulador de fase (int largo) para determinar la dirección de los datos de salida en la tabla de ondas. 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 aplicación está en http://wiblocks.com/docs/app-notes/nb1a-nco.html

jluciani
fuente
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 ...

En cada interrupción, puede cambiar uno o más puertos y el resto del tiempo (el temporizador aún se ejecuta 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 solo tiene un temporizador de hardware ...

Greenonline
fuente
1
la mayoría de los periféricos PWM de hardware le permiten seleccionar la frecuencia; si mantiene el ciclo de trabajo constante, PWM aún puede darle control de frecuencia variable
Jason S
1
Cambiar el ancho del pulso no cambia la frecuencia fundamental, pero sí cambia los armónicos.
jluciani