AVR 超入門 NO.12

[Previous] [Next] [Index]
ATtiny15L の PWM 動作
 いよいよ ATtiny15L の最大の特徴である PWM 出力について勉強する。今まで使ってきた 8 ピンの PIC ではこの PWM 出力がサポートされていないので、苦労して PWM 出力ルーチンをプログラムの中に記述した。そのために常にプログラムの中でループしなければならず、プログラムのどの経路を通ってもステップ数を同じにしなければならなかった。このようなプログラムの記述には大変な労力を要する。その苦労から解放されるとあればなんとしてでもこの PWM 出力を理解したい。

 この PWM 出力を使うと、例えばある入力待ちループを実行中でも、全くそのこととは関係なく PWM 出力を実行し続ける。受信機に組み込めば常にモータをコントロールをしながらほかの仕事ができるのだ。 PWM 出力を変更したい場合は、 PWM 出力ルーチンに変更したいデータを送るだけで即 PWM 出力に反映される。なんとすばらしいことだろう。

 便利そうだということはわかったが、実際に組み込んでみようとすると、データシートを見てもよくわからない。少々覚悟して取り組む必要がありそうだ。

 PWM 出力として PB1 が割り当てられているが、 PWM 出力として使うには設定が必要になる。ただ設定しただけでは何がどのように働くのか全くわからない。繰り返し繰り返しデータシートを眺めて何とか関連するレジスタなどを拾い出してみた。

 PWM 動作がどのように行われるのかを理解しないと実際に使えないので図で説明しよう。

 この図はデータシートに掲載されていたもので、のこぎり波はゼロから頂点までカウントアップしていく様子を示している。のこぎり波の頂点まで達するとゼロから再度カウントアップをすることになる。このカウントアップの頂点の値をあらかじめ決めてあげる。また、のこぎり波を横切る水平レベルラインは PWM 出力の High と Low を切り替える分岐点となる。このラインを上下させることで PWM 出力のデューティ比が変わる。

 三角形のゼロから頂点までの値を保存するレジスタが、タイマ/カウンタ1 比較 B レジスタ(Timer/Counter1 Output Compare Register B) といって OCR1B で表す。 8 ビットのレジスタなので 0-255 までの値をセットすることができる。

 水平レベルを表すレジスタが、タイマ/カウンタ 1 比較 A レジスタ(Timer/Counter1 Output Compare Register A) といって OCR1A で表す。このレジスタも 8 ビットレジスタなので 0-255 までの値をセットすることができる。

 あとは設定した水平レベルラインを超したら出力を High にするか Low にするかを設定するレジスタのタイマ/カウンタ 1 制御レジスタ(Timer/Counter1 Control Register) である TCCR1 がある。このレジスタには PWM 動作許可ビットも含まれている。また、このレジスタの下位 4 ビットでクロックの選択ができるようになっている。

 以上の三つのレジスタ値の設定で PWM 出力を実装することができる。わかってしまえば簡単だが、ここにたどり着くまでにかなりの試行錯誤があった。

 では簡単な PWM 出力プログラムを紹介しよう。

	ldi	temp,0b00000100      	;PWM出力ポートがPB1なので
	out	DDRB,temp              	;PB1を出力に設定

	ldi	temp,50      		;水平レベルラインの値をセットする
	out	OCR1A,temp		;タイマ/カウンタ1と比較される
	ldi	temp,100      		;のこぎり波の頂点の値(上限値)をセットする
	out	OCR1B,temp		;設定したクロックに合わせてゼロから順次加算され
					;上限値に達するとゼロから順次加算を繰り返す
	ldi	temp,0b01100101
;	      	       ||||||||____________CS10 現在の設定はシステムクロックを使用
;		       |||||||_____________CS11 設定によってシステムクロックの16倍から
;		       ||||||______________CS12 システムクロックの1024分の1まで設定できる
;		       |||||_______________CS13 またクロックの停止も選択できる
;		       ||||________________COM1A0 現在の設定は非反転出力
;		       |||_________________COM1A1 つまりのこぎり波の水平ラインより上でLow出力
;		       ||__________________PWM1 このビットがセットされるとPWM動作が許可される
;		       |___________________CTC1 このビットをセットするとのこぎり波が水平ラインと
					;    一致したところでのこぎり波がゼロリセットされる
					;    今回はそれではまずいのでこのビットはセットしない
	out	TCCR1,temp		;ここでPWM出力を開始する
					
 上の設定例では OCR1A に 50 をセットし、OCR1B に 100 をセットしてあるので、 OCR1B がゼロから 100 まで変化するが、真ん中の 50 までは非反転出力に設定されているので High が出力され、敷居値の 50 を超えて 100 までは Low が出力される。つまり 50% のデューティ比で PWM 出力動作が行われることになる。またこのときの分解能は 100 ステップあることになる。

 AVRstudio のシミュレーション画面でみてみよう。

 プログラムカーソルは OCR1A に 50 をセットしたあとを示し、 I/O ウィンドウの Compair Register 1A に 16進で 0x32 とセットされたのがわかる。

 つぎにカーソルは OCR1B に 100 をセットしたあとを示し、I/O ウィンドウの Compair Register 1B に 0x64 とセットされたのがわかる。

 プログラムステップが進むと I/O ウィンドウの Timer/Counter 1 がインクリメントされる。今回はシステムクロックをそのまま使っているのでプログラムの 1 ステップで Timer/Counter 1 の値は 1 増加する。現在の表示は 0x10 となっているが Compair Register 1A の値より少ないので PORTB の出力は Low のまま。

 プログラムステップがさらに進み I/O ウィンドウの Timer/Counter 1 の値が 0x34 と Compair Register 1A の示す 0x32 を超えた。ここで PORTB の Input Pins の PB1 にチェックが入っているのが確認できる。この時点で PORTB の PB1 は High となる。なぜかシミュレータでは出力を示す BORTB Data にはチェックが入らない。これで相当の時間悩んだが、実際にこのプログラムを ATtiny15L に書き込んでその出力をオシロで確認した。

 さらにプログラムステップが進み I/O ウィンドウの Timer/Counter 1 の値が Compair Register 1B の値を超えて Timer/Counter 1 の値がリセットされて再度カウントアップした状態を示している。このリセットにより PORTB の Input Pins の PB1 のチェックが消え、 PB1 の出力は Low となる。

 以上を繰り返して PWM 出力動作が行われることになる。ここで OCR1A の変化をスロットルスティックによるパルス幅の変化に置き換えれば、その動作がとてもよくわかる。すなわちスロットルスティックを最スローにしたときの値をゼロとし、フルスロットルのときの値を 100 とすれば PWM 出力のデューティ比をゼロから 100 まで変化させられることが理解できる。

 一番上の図で Compair Value と書かれている点線がスロットルスティックの位置によって上下すると考えればいい。のこぎり波の最下端が最スローで、のこぎり波の頂点がフルスロットルとなる。下段の PWM Output OC1A とある PWM 出力波形は今回のプログラムでは上下が逆さまになる。

 PWM 動作の仕組みがわかったので、スピードコントローラ機能を組み込むのもそう難しくはなさそうである。


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