ATtiny13を可変周波数とパルス幅を持つオーディオ発振器としてプログラムします


8

555で行うのと同じような単純な方形波発振器を作成したいのですが、割り込みベースのPWMサポートを使用して、パルス幅と周波数を制御したいと考えています。

私はデータシート、AVR API、および見つけることができるあらゆるPWMの例を研究してきましたが、それらをすべてまとめることはできませんでした。

AVR PWM機能が組み込まれたこのような発振器を作成することは可能ですか?私の友人は、8ピンPICで同様のことを行いました。

私の推論は、パルス幅を変更することで興味深いサウンドが得られるため、特定の周波数での波形になります。アタリパンクコンソールの動作に似ていますが、うまくいけば、より安定した方法で、つまりパルス幅を変更し、周波数を一定のままにするか、その逆を行います。


2
あなたの質問が何であるかを明確にしていただけませんか?
Jason S

彼らがどれほど面白いかはわかりませんが、簡単に試すことができます。パルスが狭くなると、高調波の振幅が増加します。パルスを狭め続けると、ホワイトノイズが発生します。数値制御発振器を実行するより興味深いオプションがあると思います。ウェーブテーブルにロードされた波形を変更できます。
jluciani 2009

回答:


5

これらはあなたをかなり遠くに連れて行き、残りはデータシートでできるはずです。点滅から波形、時間の経過とともにトーンに変化する波形へと、1つずつ構築していきます。一部のソースは、オーディオ出力のフィルタリングと駆動に役立ちます(アクティブなLPFは両方とも適切に機能します)。

より具体的な質問で戻ることをお勧めします。


4

PWMの周期は、タイマーのオーバーフロー率によって決まります。Modes of Operationセクションには、考慮すべき多くの設定があります。デューティサイクルが可変の一定周期の方形波を生成するだけの場合は、CTC(比較タイマーのクリアタイマー)モードを使用したいと思うでしょう。基本的な考え方は、次にピンをトグルするまでOCR0Aをタイマーティックの数に設定し、比較一致割り込みを使用して次回のその値を変更することです。したがって、avr-gccでは次のようになります。

#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;
  }
}

警告、これはテストされていないコードですが、アイデアは正しいと思います。これが唯一の方法でもありません。

ところで、ATTiny13について知っておくべきことが1つあります。内部RCオシレータは、工場フロアから10%以内の精度でのみ保証されています。ATTiny13の精度を2%にするユーザーキャリブレーションプロセス(atmel appnoteで説明)があります。あなたがそれよりももっとうまくやりたいなら、おそらく外部の水晶に対応するチップを使う必要があるでしょう...


1
あなたの答えは、私が問題を抱えていた同様のものを明確にするのに役立ちました-ありがとう。ちょうどポイント(元のスレッドの後でこれを長く読んでいる人にとって):WGM0 [2,1,0]に0b100を選択しても、CTCモードは設定されません。(実際には、Atmelによって予約されているモードが設定されます。)ATtiny13データシートでは、CTCモードには 2 が必要であると述べています。代わりに誤ってbit_number 2(つまり、値4)を指定しました。そのため、TCCR0BのWGM02を変更(クリア)するだけでなく、ビットWGM01とWGM00をそれぞれ1と0に設定する必要もあります。これらのビットはTCCR0Aにあるため、TCCRを設定するだけでは不十分です

3

あなたの質問への直接の回答ではありませんが、これは適切であり、いくつかのヒントを提供するかもしれません-

ATmega uCとDACを使用して数値制御発振器(NCO)を作成しました。整数の配列は、波形(ウェーブテーブル)の1サイクルを格納するために使用されます。位相アキュムレータ(long int)は、ウェーブテーブル内の出力データのアドレスを決定するために使用されます。各タイマー割り込みは、固定値で位相アキュムレータをインクリメントします。位相の増分により周波数が決まります。

私のアプリケーションでは、正弦波の1サイクルを含む64バイトのウェーブテーブルを使用しました。ウェーブテーブルを拡張し、サンプルに解像度を追加するのは簡単です。私のアプリケーションノートはhttp://wiblocks.com/docs/app-notes/nb1a-nco.htmlにあります


1

基本的に、PWMは周波数を変更しません。PWMは主に信号の「強度」を制御するために使用されます。

異なる周波数の割り込みを生成するには、CTCモードでタイマーを使用することをお勧めします。

それはあなたの比較値まで実行され、割り込みを切り替え、それ自身をクリアして再起動します-再びあなたの比較値まで実行されるまで...

割り込みが発生するたびに、1つ以上のポートを切り替えることができ、残りの時間(タイマーは引き続き自動的に実行されます)は、あらゆる種類の入力を監視できます...

PWMで方形波を「変調」して「ゲイン」を制御することもできます。ただし、ATtiny13にはハードウェアタイマーが1つしかないため、そのうちの1つは「手動」で行う必要があります...


1
ほとんどのハードウェアPWM周辺機器では、周波数を選択できます。デューティサイクルを一定に保つ場合、PWMは可変周波数制御を提供できます
Jason S

1
パルス幅を変更しても基本周波数は変わりませんが、高調波は変わります。
jluciani 2009
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.