// Solar Panel Maximum Power Point Controller V0.1 // PIC 16F690 // Last Rev. 28.9.2014 // Last Rev. 14.2.2015 // Written by P. Viljakainen // Internal oscillator 8 MHz #include #include "lcd.h" #include __CONFIG(INTCLK & WDTDIS & PWRTDIS & MCLREN& UNPROTECT& BORDIS& IESODIS & FCMDIS ) ; bit direction; unsigned int w; unsigned int y; unsigned int current; // measured current variable unsigned int solpanelv; unsigned int boostv; unsigned int filt_prespower[5]; unsigned int sum_power; unsigned int pres_power; unsigned int past_power; int diff; /* //------ interrupts handling ------------------------------------- void interrupt tc_int(void) { if(C1IF) // Comparator 1 interrupt { C1IE=0; // Komparaattorikeskeytys pois paalta, C1IF=0; // clear comparator interrupt bit Comparator=1; // flagi paalle } } //---------------------------------------------------------------- */ void Dither(void); void initialize(void); void ReadAnalog(void); void Display(void); void main(void) { initialize(); while(1) { if (y==10) { Display(); y=1; } if(w==100) { Dither(); w=1; } y++; w++; } } void Dither() { past_power = pres_power; ReadAnalog(); if (boostv<270) //Jos lahtojannite ei yli maksimin { if (boostv<268) RC7=0; diff=pres_power-past_power; if(diff>1) { if(direction==1) { CCPR1L--; if(CCPR1L<0x01) { CCPR1L=0x01; } } else { CCPR1L++; if(CCPR1L>0x64) { CCPR1L=0x64; } } } else if(diff<-1) { if(direction==1) { CCPR1L++; direction=0; } else { CCPR1L--; direction=1; } } } else { CCPR1L=0x0; // Setpoint to zero pres_power=2; past_power=0; RC7=1; // Battery full led turn on } } void ReadAnalog() { int z; // Delay loop variable CHS0=1; // channel select AN1 (pin18, current) CHS1=0; CHS2=0; CHS3=0; ADON=1; // Enable for(z=0;z<15;z++) // sampling C charges ADCON0 |= 0x02; // initiate conversion on the selected channel while(ADCON0 & 0x02)continue; // wait until conversion is done current=((ADRESH<<8)+(ADRESL)); // current variable, float CHS0=1; // channel select AN5 (pin15, boostv) CHS1=0; CHS2=1; CHS3=0; for(z=0;z<15;z++) // sampling C charges ADCON0 |= 0x02; // initiate conversion on the selected channel while(ADCON0 & 0x02)continue; // wait until conversion is done boostv=((ADRESH<<8)+(ADRESL)); // boost voltage variable, float CHS0=0; // channel select AN4 (pin16, solpanelv) CHS1=0; CHS2=1; CHS3=0; for(z=0;z<15;z++) // sampling C charges ADCON0 |= 0x02; // initiate conversion on the selected channel while(ADCON0 & 0x02)continue; // wait until conversion is done solpanelv=((ADRESH<<8)+(ADRESL)); // solar panel voltage variable, float //filt_prespower[9]=filt_prespower[8]; //filt_prespower[8]=filt_prespower[7]; //filt_prespower[7]=filt_prespower[6]; //filt_prespower[6]=filt_prespower[5]; //filt_prespower[5]=filt_prespower[4]; filt_prespower[4]=filt_prespower[3]; filt_prespower[3]=filt_prespower[2]; filt_prespower[2]=filt_prespower[1]; filt_prespower[1]=filt_prespower[0]; filt_prespower[0]=(current*solpanelv)>>5; for(z=0;z<5;z++) { sum_power=sum_power+filt_prespower[z]; } pres_power=sum_power/5; sum_power=0; ADON=0; // Disable } void Display() { lcd_line1(); //lcd_cmd(0x01); //ylarivi 0x00-0x13 alarivi 0x40-0x53 lcd_string("cu="); lcd_16number((int)current); lcd_goto (0x08); lcd_string("sp="); lcd_16number (solpanelv); lcd_line2(); lcd_string("p="); lcd_16number((pres_power-past_power)); lcd_goto (0x47); lcd_string("bv="); lcd_16number (boostv); } void initialize() { IRCF0=1; //Internal oscillator 8 MHz IRCF1=1; IRCF2=1; SCS=1; //internal osc used for system clock ANSEL=0x33; //AN0=analog pin 19 C1+ //AN1=analog pin 18 C1- //AN4=analog pin 16 Sol_Panel_V //AN5=analog pin 15 Boost_V ANSELH=0x0; // Loput AN kanavat digitaali IOta TRISA=0b001011; // RA0-1 analog TRISB4=0; // RB4-RB7 output TRISB5=0; TRISB6=0; TRISB7=0; TRISC=0b00100011; // RC0-1 analog input, RC5 = PWM aluksi pois asettamalla inputiksi C1CH0=0; //C1VIN- of C1 connects to C12IN0- pin 18 C1CH1=0; C1POL=0; //C1 lähtö ei invertoitu C1OE=1; //C1 output to pin 17 C1ON=0; //C1 Komparaattori aluksi pois päältä C2CH0=1; //C2VIN- of C1 connects to C12IN1- pin 15 C2CH1=0; C2POL=1; //C2 lähtö on invertoitu C2OE=1; //C2 output to pin 6 C2ON=0; //C2 Komparaattori aluksi pois päältä C2R=1; //C2+ connects to C2Vref VRCON=0x6F; //Voltage reference moduli2 päälle asetus 3.125V kytketty C2+:aan RABPU=0; //A ja B pull-upit pois TMR2IF=0; //Nollataan mahdollinen TMR2 keskeytysbitti TMR2ON=1; //Timer 2 päälle PWMää varten PR2=0x65; //PWM period = ((PR2+1)*4*Tosc*TMR2prescale= (101+1)*4*1/8e6*1= 51us=>19.6 kHz CCP1CON=0b00001100; //Valitaan PWM mode CCPR1L=0x06; //Current Setpoint aloituksessa (8 MSB; esim. CCPR1L=32h = 200dec duty cyclessä ; 2 LSB:tä CCP1CON reksiterissä T2CKPS0=0; //Prescaler bitit=00; 1:1 T2CKPS1=0; //Prescaler bitit=00; 1:1 TRISC5=0; //Enabloidaan PWM output portti CCP1IE=0; //Capture/Compare modulin keskeytykset pois päältä C1IE=1; //Komparaattorikeskeytys C1 paalle PEIE=1; //Periferiakesketys paalle RBIE=0; //B-tulojen keskeytys pois GIE=0; //enable interrupts C1ON=0; //Komparaattorit C1 ja C2 pois päältä C2ON=0; // AD conversion setup ADFM= 1; // Right justified VCFG=0; // reference voltage = Vdd ADCS0=1; // select Fosc/16 , in ADCON1 ADCS1=0; // select Fosc/16 , in ADCON1 ADCS2=1; // select Fosc/16, in ADCON1 lcd_init(); // Display module initialization direction = 1; // Set Dither routine direction past_power=0; }