2015年9月4日金曜日

AVRでロータリーエンコーダーを使う(チャタリング対策)

AVRはPin Change Interruptという割り込みがサポートされていて(「AVRのPin Change Interruptとチャタリング対策」でテストした)ロータリーエンコーダーもこれを使うことを考えてみたが、いざコーディングしてテストしてみると処理がかなり煩雑になったのであきらめた。

Pin Change InterruptはPORTごとに割り込みベクタが分かれているので、ロータリーエンコーダー用のポートとスイッチの列のポートを分けられれば少しは話は簡単になりそうだが、製作中のシーケンス入力用のデバイスは配線の都合で贅沢にポートを分けている余裕がない。

Pin Change Interrupt以外に普通の外部割込み(INT0、INT1)を使うことも一瞬考えたが、これはPD2、PD3に割り当てられていてPORTDはスイッチの列の入力に使う予定なのでこれもやめることにした。

しかたなくポーリングで処理することにした。(どうしても割り込みでというならタイマー・カウンターという手も残されているが・・・)

ブレッドボード図

表記はATMega168になっているがATMega88Vを使用。

ロータリーエンコーダーのABはPB2、PB3に、軸の押し下げのSWはPB1につないだ。
PD0..PD7につないだLEDでロータリーエンコーダーで入力した8bitの値を表示する。PC2、PC3につないだLED(左上あたりの2個)は割り込みごとにトグル表示する等デバッグ用に使った。

PB5につないだ黄色LEDはロータリーエンコーダーの軸の押し下げのSWでトグル表示する。


Atmel StudioのプロジェクトはGithubにあげました。
https://github.com/ryood/Rotary_Encoder_Debounce_Test

ロータリーエンコーダーのプラス・マイナスの読み取り値で、8bitのカウンタの値を増減して赤色LEDx8でそのまま表示している。

ロータリーエンコーダーの軸の押し下げスイッチで黄色LEDがトグル表示される。

PC2、PC3につないだLEDはそれぞれpin change interruptとTimer0オーバー・フロー割り込みでトグル動作するので、2chオシロで位相差を見ればチャタリング防止用のディレイ・タイムが確認できる。


Timer0とTimer2のプリスケーラ-


またいらんことでハマってしまった。Timer0とTimer2のプリスケーラーの値はTCCR0B/TCCR2BのCS20..CS22 bitで設定するが、設定する値が違う。

Timer2では0b111で1/1024になるが、Timer0で0b111を設定するとクロック・ソースを外部から与える設定になる。

最初Timer2でやっていて、Timer0に変更したらTimerが起動しなくなって相当悩んでしまった(^q^;;;

AVRのPin Change Interruptとチャタリング対策」で設定したTimerの遅延時間の設定も間違えてた。忘れなかったら直します。


あとADCを割り込みで処理するテストをしたら、基板を作っていきたいと思う。

回路図

基板図

プリント基板なら2層でおさまりそうだが、手配線する予定なので変な感じの図になっています。

I2Cでの本体側とのやりとりは下記のようなものを想定中。


ロータリーエンコーダーは基本的にトラック切り替え(kick、snare、hihat等)に使う予定だが、軸の押し下げSWの切り替えでロータリーエンコーダーをどういう動作に変更するか考え中。