16f877 kullanarak mppt

Başlatan kinghenry, 24 Mayıs 2012, 23:02:24

kinghenry

Merhabalar, bitirme projesi olarak mppt yapıyorum. Ancak algoritmamda hata var sanırım. Yardımcı olursanız sevinirim. Giriş ve çıkış güçlerini hesaplayıp karşılaştırıp ona göre bir pwm sinyal üretmem gerekiyor ancak ben çıkış gerilimini belirli bir değerde tutup o değere göre güç çekiyorum panelden sanırım.

#include <htc.h>
#include <math.h>
#include <stdio.h>

#define _XTAL_FREQ 20000000

__CONFIG(WDTDIS&HS&UNPROTECT&LVPDIS&BORDIS&PWRTDIS);

#define V_PV					do{ CHS2=0; CHS1=0; CHS0=0; }while(0)	//AN0
#define I_PV					do{ CHS2=0; CHS1=0; CHS0=1; }while(0)	//AN1
#define V_OUT					do{ CHS2=0; CHS1=1; CHS0=1; }while(0)	//AN3

#define vSetDutyCycle(dc) 		do{ CCPR1L=(dc>>2); CCP1CON=0b00001100|((dc&0x03)<<4); }while(0)

#define SET_VALUE				819	//4V   //675 //3.3V
#define MAX_DUTY				127
#define MIN_DUTY				1


enum{PV_VOLTAGE, PV_CURRENT, OUTPUT_VOLTAGE};
unsigned char bADCChannel=PV_VOLTAGE;

unsigned short wPVVoltage, wPVCurrent, wOutputVoltage;


#define GAIN_P					1		//1
#define GAIN_I					12		//12
#define MAX_INTEGRAL_ERROR		500		//500
#define MAX_PROPORTIONAL_ERROR	100		//100
signed short sProportional, sIntegral, sCurrentError, sMppt;

unsigned short wDuty;
unsigned short wPower, wLastPower;

enum{OFF, ON};
bit bitMppt;
				

void main(void)
{
//==========================================================================
//
//==========================================================================
	PORTA=PORTB=PORTC=PORTD=PORTE=0x00;
	TRISB=TRISC=TRISD=TRISE=0x00;
	TRISC|=0x01;
//==========================================================================
//
//==========================================================================
	T2CON=0b00000100; 
	PR2=0xFF;
	CCPR1L=0x00;
	CCP1CON=0b00001100;
	TMR2IE=1;
//==========================================================================
//
//==========================================================================
	ADCON0=0x81;
    ADCON1=0x84;
//==========================================================================
//
//==========================================================================
	PEIE=1;
	GIE=1;

	bADCChannel=PV_VOLTAGE; V_PV;
	__delay_ms(10);
	GODONE=1;

	//vSetDutyCycle(500); while(1);

	while(1) 
	{ 
		/*
		if(RC0) 
		{
			if(duty>127) duty=0;
				else duty++;
			vSetDutyCycle(duty)	;
			__delay_ms(30);
		}
		*/

//==========================================================================
		if(GODONE==0)
		{
			switch(bADCChannel)
			{
				case PV_VOLTAGE:
					wPVVoltage=ADRESH; wPVVoltage<<=8; wPVVoltage|=ADRESL;
					bADCChannel=PV_CURRENT; //I_PV; 
					//PORTB=sMppt&0xFF;
					//PORTD=sMppt>>8;
					break;
				case PV_CURRENT: 
					wPVCurrent=ADRESH; wPVCurrent<<=8; wPVCurrent|=ADRESL;
					bADCChannel=OUTPUT_VOLTAGE; V_OUT;
					//PORTB=wPVCurrent&0xFF;
					//PORTD=wPVCurrent>>8;
					wPower=wPVVoltage*wPVCurrent;
					if(sIntegral==MAX_INTEGRAL_ERROR) bitMppt=ON;
					if(bitMppt==ON)
					{
						RE0=1;
						if(wPower<=wLastPower) sMppt++;
							//else if(sMppt>0) sMppt--;
								else bitMppt=OFF;
					}
						else
						{
							if(wPower<wLastPower) { if(sMppt>0) sMppt--; }
							RE0=0;
						}
					wLastPower=wPower;
					break;
				case OUTPUT_VOLTAGE:
					RC1=1;
					wOutputVoltage=ADRESH; wOutputVoltage<<=8; wOutputVoltage|=ADRESL;
					bADCChannel=PV_VOLTAGE; V_PV;

					//regulation
					sCurrentError=SET_VALUE-wOutputVoltage-sMppt;

					sProportional=sCurrentError/GAIN_P;
					if(sProportional>MAX_PROPORTIONAL_ERROR) sProportional=MAX_PROPORTIONAL_ERROR;
						else if(sProportional<-MAX_PROPORTIONAL_ERROR) sProportional=-MAX_PROPORTIONAL_ERROR;
					
					sIntegral+=sCurrentError/GAIN_I;
					if(sIntegral>MAX_INTEGRAL_ERROR) sIntegral=MAX_INTEGRAL_ERROR;
						else if(sIntegral<-MAX_INTEGRAL_ERROR) sIntegral=-MAX_INTEGRAL_ERROR;
				/*	*/
					wDuty=sProportional+sIntegral;
					if(wDuty>1023) wDuty=0;

					vSetDutyCycle(wDuty);	
					//PORTB=sCurrentError&0xFF;
					//PORTD=sCurrentError>>8;
					//PORTB=wDuty&0xFF;
					//PORTD=wDuty>>8;
					RC1=0;
					break;
			}
			//RC1=0;
			while(GODONE==0);
		}
//==========================================================================

	}

}

void interrupt ISR(void)
{
	//if(TMR2IF) { RC1=1; TMR2IF=0; GODONE=1;}
	//RC1=1; 
	TMR2IF=0; GODONE=1;
	//if(bADCChannel==OUTPUT_VOLTAGE) RC1=1;




jrcapa

Alıntı Yapancak ben çıkış gerilimini belirli bir değerde tutup o değere göre güç çekiyorum panelden sanırım.
Zaten böyle olmalı, yoksa boost gerilimi alır başını gider. Çıkış gerilimini veya akımını sabitlerken bir yandan da panelden max. güç çekmeye çalışırız.Yalnız mppt algoritmasında sadece panel(giriş) gücü ölçülür ve belli aralıklarla karşılaştırılır.Devrede sıkıntı çok. Modellemeye çalıştığınız panelin normal DC kaynaktan farkı ne?Simüle ettiniz mi?

kinghenry

modellediğim kaynak güneş paneli gibi akım gerilim karakteristiğine sahip normal dc kaynaktan farklı olarak. simule ettiğimde de panel karakteristiğine benzer hatta hemen hemen aynı grafiği aldım. zaten panelin elektriksel eşdeğer devresi bu şekilde oluyor araştırdığımda böyle modellendiğini gördüm. devrede sıkıntı çok derken başka neler var mesela?

jrcapa

Simulasyonda çalışır ama pratik için; mosfeti sürücü ile sürsen, C1'in değerini yükseltsen,akım okuma direncini panelin eksisine bağlasan daha iyi olur.Bir de osiloskopun D ucunu mV'lar  mertebesinde gözlemlemek lazım;opampın çıkışında dalgalı gerilim olabilir, bu durumda doğru ölçüm yapabilmek için opamp çıkışına alçak geçiren filtre yapmak lazım.