#norelated
#contents
* PWMサンプル [#z3543dfc]

PWM(パルス幅変調)というAVRに内蔵されている機能を使って、LEDを明滅させてみる。~
要は、細かいON/OFFを繰り返して、そのON時間を調整することにより、時間あたりの流れる電流量を調整する技術なのかな。~

** 回路図 [#ne97aa60]

#ref(PWMTest.png,left,nowrap,PWMサンプル)

基本の回路から増えているのは、PB3から出ている、抵抗とLEDのみ。~
8bitタイマ0を使ってPWMの出力をする場合には、OC0AかOC0Bのピンを使用し、これはそれぞれPD6とPD5の兼用機能になるんだけど、PDには前回やったLCDがついてて、はずすのも面倒。~
なので、8bitタイマ2を使ってOC2AからPWM出力するようにし、これは空いてるPB3の兼用機能なので、PB3に繋いだ。~
上の回路図には、ちゃんと書かれてないけど、データシートには、PD3は(MOSI/OC2A/PCINT3)と書いてある。~
後で直しておくか……。~

あと、今回追加した抵抗を使用せず、LEDのみを繋げてしまうと、ISPのMOSIがそのままGNDに落ちてしまうせいか、プログラムの書き込みに失敗した。~
ちゃんと抵抗はつけるべきですね……。~

実際の動作はこのムービーのような感じ。~

#u2b(V3PKjTetWa8,w=480,h=385)

** ソースコード [#seb357a6]

 #include <avr/io.h>
 #include <util/delay.h>
 
 void delay_ms( int time )
 {
 	// 指定ms分ループ
 	while( time-- ){
 		_delay_ms( 1 );
 	}
 }
 
 int main( void )
 {
 	uint8_t	duty	= 0;	// Duty比 duty/256
 	int8_t	dir		= 1;	// 増減量
 
 	DDRB	= 0x08;	// PB3を出力に設定
 	PORTB	= 0x00;	// ポートBをLowに初期化
 
 	OCR2A	= duty;	// Duty比初期化
 
 	TCCR2A	= 0b10000011;	// 8bit高速PWM動作 比較A出力選択でOC2Aへの非反転動作
 	TCCR2B	= 0b00000001;	// タイマ/カウンタ2入力クロック前置分周なし
 
 	while(1){
 		// 0〜255〜0で、512msを1周期とした明滅を繰り返す
 		delay_ms(1);
 		if( 0x00 == duty ) dir = 1;		// 正方向に増やす(明るくする)
 		if( 0xFF == duty ) dir = -1;	// 負方向に増やす(暗くする)
 		duty += dir;
 		OCR2A	= duty;	// Duty比更新
 	}
 
 	return 0;
 }

*** 基本動作 [#pb12880e]

今回使用するのは、高速PWM動作という、タイマ/カウンタの機能。~
0〜255までを繰り返すのこぎり波に、閾値を与えてやって、閾値未満だったらHigh、以上だったらLowを、決まったピンに出力させる。~
この辺りは、図がないと、なかなかわかりにくい。~

#ref(Timing.png,left,nowrap,タイミング)

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS