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.