AVR 超入門 NO.7

[Previous] [Next] [Index]
ATtiny15L を使った最も簡単な 3 チャンネルデコーダプログラム
 いよいよ受信機の基本ともいうべきデコーダプログラムを ATtiny15L で組んでみる。赤外線受光素子と組み合わせれば立派な 3 チャンネル受信機になる。スピードコントローラとサーボをつなげばそのまま受信機として飛行機に搭載することも可能だ。 AVR でインドアエアプレーンを飛ばすのも夢ではない。

 送信機からのシリアルパルスを赤外線受光素子で受け、その出力を AVR に入力してそれぞれのチャンネルに分離する。それにはシリアルパルスの先頭をきちんと判別するルーチンを作る必要がある。

 PIC Learning にも出てきたが、一般に送信機のシリアルパルスは 20msec から 24msec ほどの周期で繰り返されている。各チャンネルのとりうるパルス幅は 1msec から 2msec ほど。送信機によってチャンネル数に違いがあるが、すべてのパルス幅が最大幅になったとしてもチャンネル最後のパルスから次のシリアルパルスの先頭までに少なくとも 3msec 以上のギャップがある。このギャップを検出できれば各パルスの振り分けがきちんとできる。

 ATtiny15L の 1.6MHz 内蔵発振回路で 3msec の時間をカウントするには 1600x3=4800 ステップを必要とする。一方 8 ビットのカウンターでは 28 = 256 までしかカウントできない。 8 ビット 2 桁なら 65536 までカウントできる。ギャップの検出ループのステップ数にもよるが、 3msec のギャップをカウントするには 8 ビットのカウンタが 2 桁必要になる。今回は 2 桁のカウンタを使って新たにギャップを検出するプログラムを考えてみた。

 2 桁のギャップカウンタを用意して 1 桁目がオーバーフローしたら 2 桁目をカウントアップするプログラムも組まなくてはならない。レジスタがオーバーフローするとステータスレジスタ(SREG)の bit1 の Z フラグがセットされるので、このフラグがセットされたら 2 桁目のカウンタをインクリメントするようにプログラムしている。今回のギャップ検出ループは 8 ステップなので、1桁目のカウンタがオーバーフローするのに 2048 ステップを必要とする。 1.6MHz クロックなので 1.28msec の時間経過となる。 1 桁目のカウンタが 3 回オーバーフローすると( 2 桁目のカウンタが 3 になると) 3.84msec となるので、これ以上をギャップと判断している。

3 チャンネルデコーダプログラム(テキスト形式)

 ではギャップの検出プログラムを見てみよう。

;-- ギャップ検出 ---------------
loop:	in	temp, PINB	;PORTBから入力					(1step)
	sbrc	temp, 2		;入力がゼロなら次をスキップ  			(1step/2steps)
	rjmp	out_h		;入力が1ならout_hへ				(2steps)
	cpi	gapcnt2, 3	;今回のギャップ検出ループでは3.84msecとなる    	(1step)
	clr	gapcnt1								(1step)
	clr	gapcnt2
	brlo	loop		;ギャップが検出されなかったらloopへ  		(1step/2steps)
	rjmp	output		;ギャップを検出したらoutput処理へ
out_h:	inc	gapcnt1		;gapcnt1が0xFF(255)を超えるとゼロになるが     	(1step)
				;そのときにSREGのbit1のZフラグがセットされる
	brbs	1, lp1		;Branch if Bit in SREG is Set			(1step/2steps)
				;Zフラグがセット(1)されたら次をスキップして
	rjmp	loop
lp1:	inc	gapcnt2		;2桁目のgapcnt2に1をインクリメントする
	rjmp	loop
 今回の AVR への入力は負論理なので、パルスの立ち下がりで処理を開始するが、次の立ち下がりパルスまでに途中立ち上がりパルスを通過する。 ATtiny15L の PB2 を入力とし、PB3 をチャンネル 1 の出力、 PB4 をチャンネル 2 の出力、 PB1 をチャンネル 3 の出力としてみた。

 AVR では命令数が多いので覚えるのは大変だが、その場その場で最適な命令を使えばステップ数も短くなる。ギャップが検出された時点でチャンネル 1 の立ち下がりパルスを検出したことになるので、すぐにチャンネル 1 に割り当てられた PB3 を ON にする。あとは立ち下がりパルスを検出した都度、現在 ON になっているチャンネルを OFF にして次のチャンネルを ON にするという操作を必要チャンネル数だけ繰り返せばいい。

 では出力プログラムを見てみよう。

;-- 出力 -----------------------
output:
;-- ch1 --
	sbi	PORTB, 3  	;チャンネル1のPB3をON				(2steps)
o1:	in	temp, PINB	;パルスの立ち下がりを検出したあと、パルスの立ち上がりが	
				;あるのでその立ち上がりを検出する
	sbrs	temp, 2		;立ち上がりを検出したら次をスキップして次の立ち下がりパルス
				;検出ルーチンへいく
	rjmp	o1		;立ち上がりが検出されない間ループして待つ
o2:	in	temp, PINB	;ここでパルスの立ち下がりを検出する
	sbrc	temp, 2		;立ち下がりが検出されたら次をスキップ
	rjmp	o2		;立ち下がりが検出されない間ループして待つ
	cbi	PORTB, 3  	;チャンネル1のパルスが終了したのでPB3をOFF    	(2steps)
;-- ch2 --
	sbi	PORTB, 4  	;チャンネル2のPB4をON
o3:	in	temp, PINB
	sbrs	temp, 2
	rjmp	o3
o4:	in	temp, PINB
	sbrc	temp, 2
	rjmp	o4
	cbi	PORTB, 4  	;PB4 OFF
;-- ch3 --
	sbi	PORTB, 1  	;PB1 ON
o5:	in	temp, PINB
	sbrs	temp, 2
	rjmp	o5
o6:	in	temp, PINB
	sbrc	temp, 2
	rjmp	o6
	cbi	PORTB, 1  	;PB1 OFF
	rjmp	loop		;ここでloopに戻り、これ以降のパルスはギャップ検出ルーチンで消化
 今回は 3 チャンネルのデコーダをプログラミングしたが、使用する送信機が 3 チャンネル以上でも、それ以降のパルスは、ギャップ検出ルーチンに戻してその中で消化する。 ATtiny15L ではあと PB0 が余っているので、必要なら簡単に 4 チャンネル目を追加することができる。

 画像は実際に ATtiny15L にプログラムを書き込んで、リチウム電池を電源にして 5 チャンネル赤外線送信機からの信号を赤外線受光素子で受信し、その出力波形を PB2 に入力(画像上)して ch3 の PB1 出力波形(画像下)を確認したもの。シリアルパルスの先頭から 3 番目の立ち下がりパルスで出力を開始し、 4 番目の立ち下がりパルスで出力を停止している。オシロの横一目盛りが 1msec なので出力パルス幅は約 1.6msec ほどになっている。今回は Futaba の送信機を使っているのでこの出力パルスはスロットルコントロールに割り当てられている。

  PIC12F629 入門 NO.4 で同じデコーダプログラムを PIC12F629 で組んでいる。 ATtiny15L では 1.6MHz での動作だが、 PIC12F629 では 4MHz 内蔵発信回路で動作している。同じ働きをするプログラムの両者を比較してみるのもおもしろい。


[Previous] [Next] [Index]
2003/09/16