なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

MPPT太陽電池充電器(2)

Posted by arms22 on 2008年03月13日 0  0

mppt_sch_3_13

MPPT太陽電池充電器のプログラムを作成中です。まずはMPPT制御処理を実装しました。MPPTには幾つかの追従方式があるようですが、ハード、ソフトとも簡単に実装できる電圧追従方式を採用しました。

4秒周期で太陽電池の開放時電圧をチェックし、その68%を最適動作点とし追従します。アモルファスシリコン太陽電池の場合、開放時電圧の68%が最適動作点になるようです。
MPPT動作中は太陽電池電圧を測定し、PWMデューティを調節、最適動作点を追従します。PICのクロックは内蔵発振で4MHz、PWM周期は19.531kHzとしました。

浮動小数点演算、割り算、掛け算は一切使わないようコーディングした。コンパイラはsdcc 2.6.0を使用。sdccのバグかどうかわからないけど、char型の掛け算が正しく動かないので、掛け算処理は自前で処理した。

簡単に動作確認してみたところ、負荷側に期待したほど電流が流れなかった。入力と出力の電流が同じに。。開放時電圧が4.8vの時、3.2vで最適動作点を追従しているので、MPPT制御はうまくうごいていそうだ。
部品を変えてみてもう少し試行錯誤してみよう。ソースコードの一部を続きに載せておきます。

#include <pic12f683.h>
#include <stdint.h>
#include "delay.h"
#include "adc.h"
#include "pwm.h"
#include "gpio.h"

int at 0x2007 __configuration = _INTOSCIO & _WDT_OFF & _PWRTE_ON & _CP_OFF;

#define VSOL 0
#define VSOL_LEVEL(v) ((((v)*1000)/2)/((5.0*1000)/256))
#define VSOL_CHARGE_WAIT 500

#define PWM_PR2 63 /* pwm period = 19.531kHz = (63+1) * 4 * 0.2usec * 1 */
#define DUTY_100 (256)

#define DUTY(x) (((DUTY_100*x)/100))

enum {
S_VBAT_CHK,
S_VSOL_CHK,
S_MPPT,
};

static uint8_t calc_vmpp(uint8_t vs)
{
uint8_t i;
uint16_t a = vs;
uint8_t b = (uint8_t)(0.68 * 256);
uint16_t w = 0;
for(i=0;i<8;i++){
if(b&1){
w+=a;
}
a<<=1;
b>>=1;
}
return w>>8;
}

static uint8_t c_mppt = 0;

void isr(void) interrupt 0
{
INTCON &= ~0x4;
if(c_mppt){
c_mppt--;
}
TMR0 = 178;
}

void main(void)
{
uint8_t state;
uint8_t v;
uint8_t vmpp;
uint8_t duty;

OSCCON = 0x00; /* 32kHz */
delay_ms(8); /* wait 125*8ms for power-on */

OSCCON = 0x60; /* 4MHz */
GPIO = 0; /* all pins low */
TRISIO = 0x3b; /* GP0/GP1/GP3/GP4/GP5 input, GP2 output */
ANSEL = 0x33; /* RC,AN0/AN1 analog */
ADCON0 = 0x01; /* adc ena, left justfy, VDD ref*/
CMCON0 = 0x07; /* comparetor off */
CCP1CON = 0x0c; /* pwm mode */
PR2 = PWM_PR2;
CCPR1L = 0; /* pwm duty 0 (duty range 0-156)*/
T2CON = 0; /* pre-scaler 1:1 */
OPTION_REG = 0x87; /* TMR0 pre-scaler 1:256 */
TMR0 = 178; /* 20ms interval */
INTCON = 0xa0; /* Global int ena,TMR0 int ena */

state = S_VSOL_CHK;
vmpp = 0;
duty = 0;

adc_set_channel(VSOL);
pwm_start();

do{
delay_us(500);

switch(state){
case S_VSOL_CHK:
v = adc_read();
if(v > (uint8_t)VSOL_LEVEL(2.2)){ /* 2.2v * 0.68 = 1.496v */
vmpp = calc_vmpp(v);
c_mppt = 200; /* 4sec */
duty = DUTY(20); /* start-up duty 20% */
pwm_set_duty(duty);
state = S_MPPT;
}
break;
case S_MPPT:
v = adc_read();
if(v >= vmpp){
if(duty < DUTY(100)){
pwm_set_duty(++duty);
}
}else if(v < vmpp){
if(duty){
pwm_set_duty(--duty);
}
}
if(c_mppt == 0){
pwm_set_duty(0);
delay_ms(VSOL_CHARGE_WAIT);
state = S_VSOL_CHK;
}
break;
}
}while(1);
}

Ads by Google

Leave a reply






管理者にだけ表示を許可する

該当の記事は見つかりませんでした。