日々の記録

ほどよく書いてきます。

電圧制御MPPT (太陽電池)

2014年01月05日 14時28分15秒 | AVR MPPT

※直射日光が当たらない条件の場合、コンデンサへの充電時間がかなり長くなるため、ADC変換の前の待機時間が10msでは不足します。
ADC変換を何回か実行して値が安定したらコンデンサへの充電完了と判断するアルゴリズムに変更しました。→新しい記事

太陽電池から最大限の電力を取り出すためのプログラムを作ってうまく動いたのでその経過をまとめてみる。
太陽電池は秋月電子の2Wのタイプhttp://akizukidenshi.com/catalog/g/gM-05358/です。お正月に窓ガラス越しで1.3Wほど電力が取り出せたのでいいでしょう。

制御に使うアルゴリズムはかなり簡単なもので、太陽電池の開放電圧の76%くらいに最大電力点が来るというもの。計算の都合で開放電圧の80%を目標に太陽電池を動かしてみる。
電圧制御の件はWikipediaにも記載有り(ただし英語)。http://en.wikipedia.org/wiki/Maximum_power_point_tracking#Constant_voltage

簡単なアルゴリズムと回路図。

電圧制御は1msごとに行い、1000回行ったところで、PWM停止し、太陽電池の開放電圧を測定する。
実際に回放電圧の測定とPWM測定を行っているところは、こんな感じになります。赤はPWM信号で、黄色が太陽電池電圧。10ms休止して開放電圧測定しているのが分かります。日射量が十分にあれば数msで十分でしょうが、日射量が少ないときは10msでは不十分でした。アルゴリズムを変更する必要がありそうです。

スイッチングしている時の0.33Ωにかかる電圧は次のような感じ。平均86mVなので260mAほど流れています。上記オシロの5.04Vとあわせて1.3Wほどの電力が取り出せています。

 

1秒につき10msは電力を取り出せませんが1%なのでいいでしょう。この1%のために電流計やら山登りのアルゴリズム考えるのは大変ですから。

 

 

#define F_CPU 4800000UL //PWMを20kHzくらいにしたかったので4.8MHzで動作させる
#include <avr/io.h>
#include 
#include <util/delay.h>
 
#define PWM_Pause 10 //PWM停止時間[ms]
#define Duty_Upper_Limit 200 //DUTY比の上限決定
 
void Start_ADC(void)	/*ADC変換を開始する。自動トリガでADC1の値を読み込み続ける。プログラムからはADCを読めばよい*/
{
	//10bit分解能用ルーチン ADCは連続で動作させる
	//デジタル入出力からの切り離し
	DIDR0
	= (0<<ADC0D)	//ADC0ピンの切り離し。しかし、ADC0はリセット端子になってるから設定しちゃダメ
	| (1<<ADC1D)	//同ADC1, PB2
	| (0<<ADC2D)	//同ADC2, PB4
	| (0<<ADC3D);	//同ADC3, PB3
 
	ADMUX
	= (0<<REFS0)	//Reference: 0でVCC参照, 1で1.1V内部電圧源
	| (0<<ADLAR)	//ADC Left Adjust Result: 1にセットすると左詰で結果を出してくる 
	| (1);			//ADMUX1, ADMUX0で入力チャンネルを選べる 00から11までADC0からADC3まで対応 今はADC1を使う
 
	ADCSRA
	= (1<<ADEN)		//ADC enable
	| (1<<ADSC)		//ADC Start Conversion 1にすると変換開始
	| (1<<ADATE)	//ADC Auto Trigger Enable (for Continuous Conversion)
	| (0<<ADIF)		//ADC Interrupt Flag 変換完了すると1になるらしい
	| (0<<ADIE)		//ADC Interrupt Enable 変換完了したときに割り込み許可
	| (0b101);		//Clock Division: ADコンバータはクロック50-200kHzで性能がよい
 
	DIDR0
	= (0<<ADC0D)	//ADC0ピンの切り離し。しかし、ADC0はリセット端子になってるから設定しちゃダメ
	| (0<<ADC1D)	//同ADC1を接続(1設定で切り離し実行、0設定で接続)
	| (0<<ADC2D)	//同ADC2
	| (0<<ADC3D);	//同ADC3
}
void Start_PWM(void)	/*PWM動作を開始する。CPUクロックと同じ速度で動く*/
{
	TCCR0A
	= (1<<COM0A1)	//OC0A端子をターゲットに、COM0A1:A0は高速PWM設定で以下の動作(高速PWMで使うモードのみセット)
	| (0<<COM0A0)	//10;BottomでHigh, 比較一致でLow、11;BottomでLow、比較一致でHigh、00でPWMから切断!
	| (0<<COM0B1)	//COM0B1:B0は出力がOC0Bになるだけで、同じ設定
	| (0<<COM0B0)	//
	| (1<<WGM01)	//WGMレジスタはTCCR0BのWGM02とあわせて設定
	| (1<<WGM00);	//WGM2:0が 011で8bit高速PWM動作
 
	TCCR0B
	= (0<<FOC0A)	//非PWM動作のときのみ有効。今回は0設定
	| (0<<FOC0B)	//同上
	| (0<<WGM02)	//TCCR0AのWGMビット参照
	| (0<<CS02)		//CS0xでプリスケーラ設定
	| (0<<CS01)		//000停止、001=1分周、010=8分周、011=64分周、100=256分周、101=1024分周 、110=T0ピン下降端(外部クロック)、111=T0ピン上昇端(外部クロック)
	| (1<<CS00);	
 
}
void Pause_PWM(void)		/*PWM動作の停止 */
{
	TCCR0A
	= (0<<COM0A1)	//OC0A端子をターゲットに、COM0A1:A0は高速PWM設定で以下の動作(高速PWMで使うモードのみセット)
	| (0<<COM0A0)	//10;BottomでHigh, 比較一致でLow、11;BottomでLow、比較一致でHigh、00でPWMから切断!
	| (0<<COM0B1)	//COM0B1:B0は出力がOC0Bになるだけで、同じ設定
	| (0<<COM0B0)	//
	| (1<<WGM01)	//WGMレジスタはTCCR0BのWGM02とあわせて設定
	| (1<<WGM00);	//WGM2:0が 011で8bit高速PWM動作 
 
	TCCR0B
	= (0<<FOC0A)	//
	| (0<<FOC0B)	//
	| (0<<WGM02)	//
	| (0<<CS02)		//CS0xでプリスケーラ設定
	| (0<<CS01)		//000停止、001=1分周、010=8分周、011=64分周、100=256分周、101=1024分周
	| (0<<CS00);	
}
 
int main(void)
{	
	OCR0A = 1; //とりあえずPWMの初期値設定
	Start_PWM();
	Start_ADC();
	DDRB = 0b00000001;	//PORTB0はPWMの出力になる
    while(1)
    {
		/*■開放電圧の測定■*/
		uint16_t V_aim=0;		//電圧目標値を入れる。ADCが10bit整数、変数そのものは16bitなので、ADCの値を64倍するとオーバーフロー
		Pause_PWM();			//PWM出力の停止
		_delay_ms(50);	//50ms待つ(コンデンサへの充電を待つ)
		V_aim=ADC*4/5;			//電圧を0.8倍する。※整数演算のほうが速いから4倍して5で割っている。(78%なら39/50の演算でも可)
		Start_PWM();			//PWMの開始(PWMは開放電圧測定前のDuty比で回る)
		_delay_ms(PWM_Pause);	//コンデンサ電圧が安定するのを目的にしばらく待つ
 
		/*■PWM制御■*/
		for(uint16_t i=0;i<4000;i++)
		{
			_delay_us(500);			//delay 1ms
			if (ADC < V_aim)		//ADCが値目標電圧より小さい場合は、Dutyを一つ小さく(負荷を軽く)。
			{
				(OCR0A > 1) ? (OCR0A--) : (OCR0A=0);
			}
			else
			{
				(OCR0A < Duty_Upper_Limit) ? (OCR0A++) : (OCR0A=Duty_Upper_Limit); 
			}			
		}
    }
}
コメント (2)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« MPPT動作点を探す | トップ | MPPT回路出力開放検出 »

2 コメント

コメント日が  古い順  |   新しい順
Unknown (いち)
2014-01-05 22:41:07
入射光が弱い時には、やはり100μFのコンデンサが邪魔ですね。
チョッパ平滑最小限までに容量を小さくしても下限値がどうしてもできてしまう。
でも太陽電池にFETスイッチを追加するのもなんかもったいないし、うーん、うまい方法は無いものか・・・。

やっぱ、入力電流も測って最大電力点を追従する方法のが、休止時間が不要だし現実的なのかなぁ・・・?
おまけに電力表示もできるし。

開放電圧方式は簡単なようで、問題も残るみたいですね。

マコチがこの方式でとりあえず動作したんで、私はMPPTで作ってみようかなぁ。(^^;)
返信する
Unknown (まこち)
2014-01-06 20:28:18
入射光が弱いときはもう発電しなくていいかと思ってます。
直射日光が当たっているときはイイですが、日陰に入ると全然ダメですね。
曇りの時などの試験は全然してませんが、なんとかなると思います(部屋の電灯でいろいろやる限りの見込みですが)

あと、開放電圧測定は結局測定を繰り返して二回測定した値がある程度以下の場合に測定完了というルーチンにしました。発電量が多い時はすぐ測定が終わって、発電量が少ないときはそれなりに時間かかる感じです。

やはり電流測定してやるのが一番でしょうね。大型のシステムだとやっぱり効率をちょっとでも上げた方がいいでしょうね。

私のはオモチャみたいなもんですからw
返信する

コメントを投稿

AVR MPPT」カテゴリの最新記事