Make: AVR Programming pt.04

squeuei.hatenablog.com

Chapter 10

タイマを使うときのチェックリスト

  1. どのタイマを使うか決める。8bitでよければTimer 0か2、16bitが必要ならTimer 1。
  2. どのモードが必要なのかを決める。TCCRnAのWGMn0とWGMn1、TCCRnBのWGMn2をセットする。
    1. 数えたかったりタイミングを作りたいのならNormalモード(設定の必要なし)
    2. 時間の基準や周波数を作りたいのならCTCモードを使う。WGMn1をセットする。
    3. PWMを使いたいならfast PWMモード。WGMn0とWGMn1をセットする。PWM周波数を変えなくてもいいならWGMn2もセットする。
  3. 直接出力するならTCCRnAのCOMxAとCOMxBをセットする。
  4. 分周を決めたらTCCRnBのCSnxビットをセットする。
  5. 比較する数値を使うならOCRnAやOCRnBにデフォルトの値を設定する。PWMを使うならDDRの出力設定も忘れないこと。
  6. タイマで割り込みを使う?
    1. Normalモードならカウンタオーバフロー割り込みを有効にするため、TIMSKnのTOIEnをセットする。
    2. PWMやCTCモードなら比較での割り込みを有効にするため、TIMSKnのOCIEnAとOCIEnBをセットする。
    3. sei()するのを忘れないように。

Chapter 11

サーボのようなデバイスとAVRの電源はなるべく分けた方がいい。AVRの動作が不安定になる恐れがあるから。

Chapter 12

高い電圧を高分解能で取得したいときは、分圧とオーバーサンプリングを使う。 また、AVRの場合はADC以外のクロックを停止することでノイズを低減するADCノイズリダクションスリープモードがあるので、活用すると良い。

オーバーサンプリング

オーバーサンプリングは中心極限定理に基づいていて、たとえば10ビットADCで16個のサンプルを取得した後、4で割る(=2ビットシフトする)ことで12ビットの結果が得られる。 nビット余計に欲しいときは、{2^{2^n}}回のサンプリングと{2^n}回の割り算(=n回のビットシフト)が必要。

オーバーサンプリングは、サンプリング周波数よりもゆっくり変化する信号に対して適用する。 速度、精度、コストはトリレンマだ。 16回のオーバーサンプリングは16倍遅くなるけど2ビット分の精度をただで手に入れられる。 高速で正確なADCが欲しいなら良いADCを買えばいいけど、それにはお金がかかるのだ。

0~5V以外の信号を計りたいときは

1V以下のものを計りたいときはAREFを内蔵の1.1Vリファレンス電源にすればよい。 1V~5Vのものを計りたいときはAREFを内蔵の1.1Vリファレンス電源にして、その上で信号を分圧すればよい。 5V以上のものを計りたいときは信号を分圧すればよい。

スリープ

avr/sleep.hをインクルードして、set_sleep_mode(SLEED_MODE_ADC);(実はSMCR |= (1 << SM0);するのと同じ)と、ADCSRA |= (1 << ADIE);(ADC割り込み有効化)、sei()をすればよい。ただし、sleepが終わるときにISRが呼ばれるので、EMPTY_INTERRUPT(ADC_vect);なりしておく必要がある。

EWMA(Exponentially Weighted Moving Averages)

ふつうの移動平均では移動平均する数だけメモリを消費する。 また、C言語の除算では切り捨ての問題があるから、なるべく除算の階数を減らしたい。 EWMAなら2つの変数、現在の値{x_t}と過去の平均値{y_{t-1}}だけでいい。

{\displaystyle y_t=\frac{1}{16}x_t+\frac{15}{16}y_{t-1}}

また、EWMAは最後に一回だけ除算をすればいいので、除算の問題が少ない。 除算するときの一つのテクニックは、割る数の半分を事前に足してから除算を行うこと。

(16+4)/8 = 2
(20+4)/8 = 3

これらを考慮したときのEWMAの式は下記の通り。

{\displaystyle 16y_t=x_t+16y_{t-1} -\frac{(16y_{t-1}-\frac{16}{2})}{16}}