Programe um ATtiny13 como um oscilador de áudio com frequência variável e largura de pulso


8

Quero criar um oscilador de onda quadrada simples, semelhante ao que seria feito com um 555, mas quero usar o suporte PWM baseado em interrupção para controlar a largura e a frequência do pulso.

Estudei a folha de dados, as APIs do AVR e quaisquer exemplos de PWM que encontrei, mas ainda não consegui reunir tudo.

É possível criar um oscilador com a funcionalidade integrada do AVR PWM e, em caso afirmativo, como? Meu amigo fez algo semelhante com um PIC de 8 pinos.

Meu raciocínio é que vou obter sons interessantes alterando a largura de pulso e, portanto, a forma de onda em uma determinada frequência. Semelhante à maneira como o Atari Punk Console funciona, mas esperançosamente, de uma maneira mais estável, ou seja, alterando a largura do pulso, mas deixando a frequência constante ou vice-versa.


2
você poderia esclarecer qual é a sua pergunta?
— Jason S

Não tenho certeza de quão interessantes serão, mas é fácil tentar e você pode julgar. À medida que o pulso se estreita, as amplitudes dos harmônicos aumentam. Continue estreitando o pulso e você terá ruído branco. Eu acho que você teria opções mais interessantes fazendo um oscilador controlado numericamente. Você pode alterar as formas de onda carregadas na tabela de ondas.
— jluciani

Respostas:


5

Isso deve levar você muito longe e o resto você pode fazer com a folha de dados. Comece a construir peça por peça, de intermitente a forma de onda e forma de onda que muda ao longo do tempo para tons. Alguma fonte pode ajudar a filtrar e direcionar as saídas de áudio (o LPF ativo pode funcionar perfeitamente).

Sugiro voltar com perguntas mais específicas.


4

O período do PWM é determinado pela taxa de transbordamento do seu timer. Existem muitas configurações na seção Modos de Operação para pensar. Se tudo o que você quer fazer é gerar uma onda quadrada de período constante, com ciclo de trabalho variável, acho que você desejará usar o modo CTC (Clear Timer on Compare Match). A idéia básica é definir OCR0A para o número de marcações do timer até que você queira que o pino alterne a seguir e use a interrupção Compare Match para alterar esse valor pela próxima vez. Portanto, no avr-gcc, seria algo 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;
  }
}

Aviso, este é um código não testado, mas acho que a idéia está correta. De maneira alguma é também a única maneira de fazê-lo.

Há uma coisa que você deve saber sobre o ATTiny13, a propósito. O oscilador RC interno é garantido apenas com precisão de 10% do chão de fábrica. Há um processo de calibração do usuário pelo qual você pode passar (descrito por um appmelote da atmel ) que fornecerá uma precisão de 2% para o ATTiny13. Se você quer fazer melhor do que isso, provavelmente precisará usar um chip que acomoda um cristal externo ...


1
Sua resposta ajudou a esclarecer algo semelhante com o qual eu estava tendo problemas - obrigado. Apenas um ponto (para quem lê isso muito tempo após o thread original): sua escolha de 0b100 para WGM0 [2,1,0] não definirá o modo CTC. (De fato, ele definirá um modo reservado pela Atmel.) A folha de dados ATtiny13 diz que o modo CTC precisa do valor 2; você acidentalmente forneceu o bit_number 2 em vez disso (ou seja, o valor 4). Por isso, também é necessário não apenas alterar (por exemplo, limpar) WGM02 em TCCR0B, mas também definir os bits WGM01 e WGM00 para 1 e 0, respectivamente. Esses bits estão no TCCR0A, portanto, não é suficiente definir o TCCR

3

Não é uma resposta direta à sua pergunta, mas isso pode ser apropriado e fornecer algumas dicas -

Acabei de criar um oscilador controlado numericamente (NCO) usando um ATmega uC e um DAC. Uma matriz de números inteiros é usada para armazenar um ciclo de uma forma de onda (tabela de ondas). Um acumulador de fase (int longo) é usado para determinar o endereço dos dados de saída na tabela de ondas. Cada interrupção do temporizador incrementa o acumulador de fase por um valor fixo. O incremento de fase determina a frequência.

No meu aplicativo, usei uma tabela de ondas de 64 bytes que continha um ciclo de uma onda senoidal. É fácil estender a tabela de ondas e adicionar mais resolução às amostras. Minha nota de inscrição está em http://wiblocks.com/docs/app-notes/nb1a-nco.html


1

Basicamente, um PWM não altera a frequência. O PWM é usado principalmente para controlar a "intensidade" de um sinal.

Para gerar uma interrupção para diferentes frequências, sugiro que você use o timer no modo CTC.

Ele será executado no seu valor de comparação, alternará uma interrupção, cancelará e será reiniciado - até que seja executado novamente no seu valor de comparação ...

A cada interrupção, você pode alternar uma ou mais portas e o resto do tempo (o temporizador ainda funciona automaticamente), você pode assistir suas entradas de qualquer tipo ...

Você ainda pode "modular" sua onda quadrada com um PWM para controlar o "ganho". Mas um deles deve ser feito "manualmente", porque o ATtiny13 possui apenas um temporizador de hardware ...


1
a maioria dos periféricos PWM de hardware permite selecionar a frequência; se você mantiver o ciclo de funcionamento constante, o PWM ainda poderá fornecer controle de frequência variável
— Jason S

1
Alterar a largura do pulso não altera a frequência fundamental, mas altera os harmônicos.
— jluciani
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.