■ATtiny85 タップテンポ付LFO その2

14_229_1atLFO2.png
前回のLFOをさらに発展させました。主な変更点は下記の通りです。考え方は前回と同じで、一定間隔でPWMのデューティ比を変更します。
・1周期126分割→510分割(PWMの分解能8ビット分をフルに生かせる)
・PWM周波数31.25kHz→250kHz(出力ピンPB0→PB1)
・タイマー割り込みを使ってPWMデューティ比を変更、タップ時間計測

タイマー・割り込みに関する詳細説明は省きます。ATtiny85(日本語データシートpdf)は2つのタイマーがあり、Timer0でデューティ比変更時間の管理とタップテンポの時間計測をし、Timer1でPWMを使います。該当レジスタを変更することにより様々な設定を行うわけですが、見慣れないビット演算が出てくるので最初は戸惑うかもしれません。
参考ページ→C言語入門::付録 ビット演算びんずめ堂)・AVRでのタイマとPWMの使い方うしこlog)・AVRでの割り込みの使い方うしこlog

今回のスケッチでは三角波を生成しています。ATtiny85のPWMを最高速で動作させるため、Arduino IDEのツールメニューから「Timer1 Clock: "64MHz"」を選択し「ブートローダを書き込む」という操作を行っておく必要があります。

▽Arduinoスケッチ
表示/非表示切替(94行)



<タップ時間計測について>
Timer0に比較A割り込みを設定している関係で、millis関数で時刻を取得しようとしてもうまくいきません。タップ時間の測定は割り込み回数をカウントすることにより行います。Timer0はクロック8MHz、8分周なので最小時間単位は1usです。OCR0Aを200にすると200usごとに割り込みが発生します。

【例】0.2msごとに割り込みが発生(OCR0A=200)→割り込みが50回発生(timeCount=50)→経過時間10ms(0.2ms×50)

OCR0Aを更新する時に、更新前の時間(timeTemp)を計算しておく必要があります(スケッチ最下部)。TCNT0も加味した方がより正確ですが、そこまでの精度は必要ないでしょう。タップについては1回目と2回目の区別はなく、毎回前回タップからの経過時間を計算します。経過時間が設定可能なLFO周期内であるときだけ、実際に周期を変更することになります。



<デューティ比変更間隔時間の計算処理について>
OCR0Aを200とし、割り込みが発生する度にデューティ比を変更すると、周期は102ms(0.2ms×510)です。OCR0Aは255まで(8ビット)なので、このままでは周期を長く設定できません。分周比を変えることも考えましたが時間分解能が悪くなります。そこで長い周期を得るために、何回か割り込みが発生した時にデューティ比を変更するようにします。

【例】0.2msごとに割り込みが発生(OCR0A=200)→割り込みが10回発生(rateCountNum=10)するごとにデューティ比変更→周期1020ms(0.2ms×10×510)

次は逆に周期から割り込み間隔と回数を計算します(上記スケッチのrateCalc関数)。ちょっと無理やり感がありますが、100~255usの割り込み間隔で割った商(=割り込み回数)と余り(=誤差)を全て計算し、余りが最小になる時を採用します。割り込み間隔はあまりに狭いと問題がありそうなので、100us以上としました。

【例】最適値計算:周期1030ms(1030000us)→デューティ比変更間隔時間2019us(1030000÷510切捨)→224us(割り込み間隔)×9(回数)+3us(誤差)
計算値設定後:0.224msごとに割り込みが発生(OCR0A=224)→割り込みが9回発生(rateCountNum=9)するごとにデューティ比変更→周期1028ms(0.224ms×9×510)


ほとんどの場合で周期の誤差は2ms以内に収まります。実は上記例では2019usを+1usして再計算したほうが誤差が減るのですが、そこまでの計算はしないことにします。

■タグ : マイコン

■コメント

■コメントの投稿

管理者にだけ表示を許可する

 

管理人

ブログ内検索

メールフォーム

当ブログに関するお問い合わせはこちらからお願いします。 ※FAQ(よくある質問)もお読みください。

お名前
メールアドレス
件名
本文

アクセスカウンター