Superb Garbages 2

千野純一(chinorin)のはてなダイアリーの続きです。

ATtiny13A(MicroCore)でロータリーエンコーダ信号を容易に取り扱うためのスケッチ

  • 僭越ながら。汎用的で独立的な仕組みを作ったら、こういう風に公開するのもいいかなと思った。

 

  • Arduino IDEMicroCoreを導入した環境でATtiny13Aに書き込める、一般的なロータリーエンコーダ(インクリメンタル式)の差動信号を単純なパルスにデコードするスケッチを置いときます。特別なライブラリとかを入れるのが面倒とかで、スケッチ一発で終わらせたい人向け。
  • 例えばISP化したArduino UNOとか(Arduino as ISPってやつ。NanoとかLeonardoとかでも一応できる)を使ってATtiny13Aに書き込むことができます。そのあたりの詳細はぐぐれ。
  • エンコーダを回すとプッシュスイッチとかと同じようなノリで信号が発生しますので、別のメインとなるマイコンで受け取るなり、ロジックIC並べて色々やるなりして遊んでください。これ単体ではロータリーエンコーダの検査ができるくらいでほとんど無意味です。
  • ライセンスはCC0著作権は主張しません。ご自由に使っていただいて構いませんが、このスケッチを使用したことで損害などが発生しても当方は関知せず、補償等は一切行いません。ご利用は自己責任で。
// For ATtiny13A as MicroCore, a sketch of using rotary encoder
// [Encoder] -> 0/1 [ATtiny13A] 3/4 -> (pulse)
// Creative Commons CC0 license. No Rights Reserved.

void setup() {

//	pinMode(0,INPUT);
//	pinMode(1,INPUT);
//	pinMode(3,OUTPUT);
//	pinMode(4,OUTPUT);
	DDRB=0b00011000;

//	digitalWrite(3,LOW);
//	digitalWrite(4,LOW);
	PORTB=0b00000000;

	SREG=0b10000000;
	GIMSK=0b00100000;
	PCMSK=0b00000011;

	sei();
}

ISR(PCINT0_vect){
	static int state;
	boolean d3=bit_is_set(PINB,PINB0),d4=bit_is_set(PINB,PINB1);

	if(d3 && !d4){
		state=3;
	} else if(!d3 && d4){
		state=4;
	} else if(d3 && d4){
		if(state){
			digitalWrite(state,HIGH);
		}
		state=0;
	} else {
		state=0;
		PORTB=0b00000000;
	}
}

void loop() {}
  • けっこう無駄がありそうで、特にif構造をもっと効率的に書けるだろうとは思うのですが、自分が使う用としてはこれで充分いけそうなのでまあいいかという感じで⋯。
  • 動作テストしたパッケージはATtiny13A-PU(DIP-8のやつ。国内だと60円とか85円とかで売ってる)、5V駆動でクロックは内蔵9.6MHz。Arduino IDEのバージョンは1.8.15、MicroCoreのバージョンは2.0.3です。
  • エンコーダは手回し専用という感じだと思います。ゆっっっくり回したりすると一時的に誤動作を起こす場合があります。めちゃめちゃ速く回したときも読み落としが発生する可能性がありますので、精密な角度検知のために使うのは避けた方がいいです。
  • ATtiny13Aだけでなく、おそらくATtiny13や13Vでも動くのではないかと思います。もしかしたらATtiny85/45/25等、8本足AVRなら問題なくいけるかもしれませんが、それらはMicroCoreではないので詳しくはわかりません。


  • ↑接続の例。記号が新旧混じっていてすみません。抵抗とかこの形じゃないと雰囲気出なくない?
  • ロータリーエンコーダからの2つの出力をそれぞれATtiny13Aの0番と1番に入れます。エンコーダをある方向へ回すと3番にパルスが出力されます(一瞬HIGHになり、すぐにLOWになります)。逆方向は4番です。最初は3番4番の先にLED(と抵抗)などを置いてみると信号の出る様子がわかって楽しいかもしれません。
  • ATtiny13AのVccは1.8~5.5Vだそうです。
  • R1/R2はプルダウン抵抗、C1/C2はいわゆるチャタリング対策のためのノイズフィルタの役割をするコンデンサです。それぞれご自分が信じる値のものを配置してください。動作テストでは、抵抗は各10kΩ、コンデンサは各104(0.1μF)のセラミックコンデンサを使いました。(無極性でなくても効果はあります。電解コンデンサとかなら上側が+)
  • C3はノイズ対策および電圧平滑のためのコンデンサです。ご自分が信じる値のものを配置してください。動作テストでは0.47μFの電解コンデンサを使いました。(こちらも無極性でも大丈夫でしょう)
  • これらのコンデンサについては、一般的にはもっと小さな容量のものを使うような気がします。計算とか検証とか面倒なのでとりあえず適当ですが、省くと誤動作を起こす確率が高まる(ように感じる)ので適当でも効果があるんだと思います。
  • ATtiny13Aの2番と5番は使いません。使わないピンって結局どうするのが正しいんだっけ⋯。テスト環境では何も接続しませんでしたが、論理を固定しておくべきなのかもしれません。設定上はINPUTになっています。なお5番は\rm{\overline{RESET}}なのでLOWを入れると再起動がかかるっぽい。
    • 8/4追記:そうだ、入力端子は論理を固定、出力端子はオープン、というのが基本でしたね。このプログラムの場合、2番と5番はINPUTなので論理を固定しておくべきです(2番はどちらでもよい。5番はHIGHに)。プルアップorプルダウン抵抗を忘れずに。
    • あるいは setup() にある DDRB=0b00011000; を DDRB=0b00111100; にすると2番と5番もOUTPUTになるのですが、\rm{\overline{RESET}}の端子をOUTPUTにして果たして大丈夫なのかどうか⋯。
    • ⋯⋯って、ああ、これらって内部プルアップしとけばいいのか。なるほど。気が向いたら改変しまーす。Microcoreのそのへんの仕様を調べるのと、一応テストするべきなのとで腰を落ち着けてやる必要がある。

 

  • 意義としては⋯⋯これをロジックICでやるとすると74HC14(シュミットトリガインバータ)と74HC74(Dフリップフロップ)あたりを使うのが普通みたいだけど、それらを買うよりATtiny13Aの方が安いかも? ということで。
  • そもそも電子工作を始めた当時、ロータリーエンコーダってめんどくせーなー接続するだけでこれをやってくれるICとかねーのかよと思って探したんだけど、これが意外となさそうなんだよね。そんな過去の自分の願いを叶える活動みたいな。
  • そもそもこの仕組みってロータリーエンコーダに内蔵して然るべきだと思うのよ。機械式ならともかく、光学式のエンコーダなんてどうせ電源使うんだからここまでやればいいのに。差動信号がどうしても必要なら(そんなシチュエーションあるの?)それはそれで別に出力すればよろしい。AとB以外に\rm{\overline{A}}\rm{\overline{B}}とかつけてる場合なんだろうか。w プルアップしたいのはわからんでもないが。
  • あっ、そうするとエンコーダという名前は相応しくなくなってしまうんだ。ここはロータリーコーデックということでひとつ⋯。