STM32マイコンを用いた単相系統連系インバータの制御アルゴリズムと実装

システムアーキテクチャと制御概要

単相系統連系インバータは、直流電力を商用電力系統と同期した交流電力へと変換する電力変換装置です。本システムでは、電圧形インバータ(VSI)トポロジーを採用し、電圧外環と電流内環からなるカスケード制御(2重ループ制御)を適用しています。これにより、力率1.0での運転、高精度な出力電力制御、および系統電圧のサポート(LVRT機能)を実現します。

ハードウェア構成

  • メイン回路: 直流電源 → DC-DCコンバータ(Boost) → フルブリッジインバータ(IGBT/MOSFET) → LCフィルタ → 電力系統
  • 制御マイコン: STM32F407VG (ARM Cortex-M4, FPU搭載, 168MHz動作)
  • センシング: 系統電圧、連系電流、直流母線電圧のADCサンプリング
  • ゲート駆動: デッドタイム挿入機能を備えた4chの相補PWM出力
  • 保護回路: 過電流、過電圧、孤立運転検出(アンチアイランディング)

制御アルゴリズムの設計

制御ブロック線図のデータフロー

  1. 系統電圧 (vg) → SOGI-PLL → 同期正弦波 (sinθ) 生成
  2. 直流母線電圧 (Vdc) → 電圧PI制御 → 電流振幅指令 (Iref)
  3. 電流振幅指令 (Iref) × sinθ → 電流基準 (ig_ref)
  4. 電流基準 (ig_ref) と 連系電流 (ig) → 電流PI制御 → 電圧指令 (Vcontrol)
  5. 電圧指令 (Vcontrol) + 系統電圧前饋 (vg) → インバータ出力電圧指令 (Vinv)
  6. Vinv → SPWM変調 → Hブリッジゲート駆動信号

1. SOGI-PLL(2次一般化積分器を用いた位相同期回路)

系統電圧の位相を高精度に抽出するため、SOGI(Second-Order Generalized Integrator)に基づくPLLを実装します。これにより、系統電圧の歪みやノイズに対するロバスト性を確保します。直交成分(α軸、β軸)を生成し、そのアークタンジェントから位相角を算出します。

2. カスケード制御(電圧環・電流環)

直流母線電圧を一定に保つための電圧PI制御器(外環)と、系統電流を正弦波状に制御するための電流PI制御器(内環)で構成されます。電流環には系統電圧のフィードフォワード補償を導入し、外乱に対する応答速度を向上させています。

3. SPWM(正弦波パルス幅変調)

制御器から出力される電圧指令値を三角波キャリアと比較し、インバータのスイッチング素子を駆動するためのPWMデューティ比を生成します。スイッチング素子の短絡を防ぐため、適切なデッドタイム補償を組み込んでいます。

STM32向けC言語実装

メインアプリケーション

// app_main.c
#include "stm32f4xx_hal.h"
#include "grid_tied_inverter.h"

int main(void) {
    HAL_Init();
    SystemClock_Config();
    Peripheral_Init(); // GPIO, ADC, TIM1, UART の初期化
    
    InverterConfig cfg = {
        .vdc_target = 400.0f,       // 直流母線目標電圧 (V)
        .grid_freq = 50.0f,         // 系統周波数 (Hz)
        .grid_v_peak = 311.0f,      // 系統電圧ピーク値 (V)
        .v_loop_kp = 0.45f,         // 電圧環 Pゲイン
        .v_loop_ki = 12.0f,         // 電圧環 Iゲイン
        .i_loop_kp = 0.9f,          // 電流環 Pゲイン
        .i_loop_ki = 60.0f,         // 電流環 Iゲイン
        .filter_l = 2.5e-3f,        // フィルタインダクタンス (H)
        .filter_c = 15.0e-6f        // フィルタキャパシタンス (F)
    };
    
    InverterCtx ctx;
    reset_inverter_context(&ctx);
    
    start_pwm_outputs();
    
    // メイン制御ループ (10kHz)
    while (1) {
        if (is_control_period_ready()) { 
            // 1. センサーデータ取得
            ctx.v_grid = read_sensor(SENSOR_V_GRID) * V_GRID_SCALE;
            ctx.i_grid = read_sensor(SENSOR_I_GRID) * I_GRID_SCALE;
            ctx.v_dc = read_sensor(SENSOR_V_DC) * V_DC_SCALE;
            
            // 2. 制御アルゴリズム実行
            update_sogi_pll(&ctx, &cfg);
            run_dc_voltage_controller(&ctx, &cfg);
            run_grid_current_controller(&ctx, &cfg);
            compute_modulation_duty(&ctx, &cfg);
            
            // 3. PWMデューティ適用
            apply_pwm_duties(&ctx);
            
            // 4. 異常状態の評価
            evaluate_fault_conditions(&ctx, &cfg);
        }
    }
}

SOGI-PLLの実装

// sogi_pll.c
#include "sogi_pll.h"
#include 

void init_sogi_pll(SogiPll *pll, float nominal_freq) {
    pll->phase = 0.0f;
    pll->omega_nom = 2.0f * M_PI * nominal_freq;
    pll->sogi_gain = 1.414f; // 最適ダンピングのための sqrt(2)
    pll->v_alpha = 0.0f;
    pll->v_beta = 0.0f;
    pll->omega_int = 0.0f;
}

void update_sogi_pll(InverterCtx *ctx, InverterConfig *cfg) {
    SogiPll *pll = &ctx->pll;
    float dt = 1e-4f; // 100us 制御周期
    float k_sogi = 0.8f; 
    
    // SOGI 直交信号生成
    float v_err = ctx->v_grid - pll->v_alpha;
    float dv_alpha = pll->omega_nom * (k_sogi * v_err - pll->v_beta);
    float dv_beta = pll->omega_nom * pll->v_alpha;
    
    pll->v_alpha += dv_alpha * dt;
    pll->v_beta += dv_beta * dt;
    
    // 位相抽出
    pll->phase = atan2f(pll->v_beta, pll->v_alpha);
    if (pll->phase < 0.0f) pll->phase += 2.0f * M_PI;
    
    // 周波数追従 (簡易PI制御)
    float freq_err = pll->v_beta * cosf(pll->phase) - pll->v_alpha * sinf(pll->phase);
    pll->omega_int += 5.0f * freq_err * dt;
    pll->omega_nom = 2.0f * M_PI * 50.0f + pll->omega_int + 20.0f * freq_err;
}

カスケード制御(電圧環・電流環)

// cascade_control.c
void run_dc_voltage_controller(InverterCtx *ctx, InverterConfig *cfg) {
    float v_err = cfg->vdc_target - ctx->v_dc;
    
    ctx->v_int += v_err * 1e-4f;
    // アンチワインドアップ
    if (ctx->v_int > 10.0f) ctx->v_int = 10.0f;
    if (ctx->v_int < -10.0f) ctx->v_int = -10.0f;
    
    ctx->i_ref_peak = (cfg->v_loop_kp * v_err) + (cfg->v_loop_ki * ctx->v_int);
    
    // 指令電流のリミット
    if (ctx->i_ref_peak > 15.0f) ctx->i_ref_peak = 15.0f;
    if (ctx->i_ref_peak < -15.0f) ctx->i_ref_peak = -15.0f;
}

void run_grid_current_controller(InverterCtx *ctx, InverterConfig *cfg) {
    float i_target = ctx->i_ref_peak * sinf(ctx->pll.phase);
    float i_err = i_target - ctx->i_grid;
    
    ctx->i_int += i_err * 1e-4f;
    if (ctx->i_int > 50.0f) ctx->i_int = 50.0f;
    if (ctx->i_int < -50.0f) ctx->i_int = -50.0f;
    
    float v_ctrl = (cfg->i_loop_kp * i_err) + (cfg->i_loop_ki * ctx->i_int);
    
    // 系統電圧フィードフォワード補償
    ctx->v_inv_cmd = v_ctrl + ctx->v_grid;
    
    if (ctx->v_inv_cmd > 350.0f) ctx->v_inv_cmd = 350.0f;
    if (ctx->v_inv_cmd < -350.0f) ctx->v_inv_cmd = -350.0f;
}

SPWM変調とデューティ適用

// modulation.c
void compute_modulation_duty(InverterCtx *ctx, InverterConfig *cfg) {
    float v_carrier_peak = ctx->v_dc; 
    if (v_carrier_peak < 10.0f) v_carrier_peak = 10.0f; // ゼロ除算防止
    
    float m_index = ctx->v_inv_cmd / v_carrier_peak;
    if (m_index > 0.95f) m_index = 0.95f;
    if (m_index < -0.95f) m_index = -0.95f;
    
    // フルブリッジ用のデューティ比計算
    float duty_leg_a = 0.5f * (1.0f + m_index);
    float duty_leg_b = 0.5f * (1.0f - m_index);
    
    ctx->duty_ch1 = duty_leg_a;
    ctx->duty_ch2 = duty_leg_b;
}

void apply_pwm_duties(InverterCtx *ctx) {
    uint32_t arr = __HAL_TIM_GET_AUTORELOAD(&htim1);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)(ctx->duty_ch1 * arr));
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, (uint32_t)(ctx->duty_ch2 * arr));
}

保護機能と異常検出

// fault_handler.c
void evaluate_fault_conditions(InverterCtx *ctx, InverterConfig *cfg) {
    uint32_t fault_code = 0;
    
    if (fabsf(ctx->i_grid) > 12.0f) fault_code |= FAULT_OVERCURRENT;
    if (ctx->v_dc > 460.0f) fault_code |= FAULT_OVERVOLTAGE;
    if (fabsf(ctx->v_grid) < 80.0f) fault_code |= FAULT_ANTI_ISLANDING;
    
    if (fault_code != 0) {
        trigger_hardware_shutdown();
        log_fault_event(fault_code);
    }
}

void trigger_hardware_shutdown() {
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
    HAL_GPIO_WritePin(GRID_RELAY_PORT, GRID_RELAY_PIN, GPIO_PIN_RESET);
}

拡張機能の実装

MPPT(最大電力点追従制御)

// mppt_controller.c
void run_perturb_and_observe(float v_pv, float i_pv, float *v_ref) {
    static float prev_p = 0.0f;
    static float prev_v = 0.0f;
    float curr_p = v_pv * i_pv;
    float delta_p = curr_p - prev_p;
    float delta_v = v_pv - prev_v;
    
    float step = 0.5f;
    if (delta_p != 0.0f) {
        if (delta_p > 0.0f) {
            *v_ref += (delta_v > 0.0f) ? step : -step;
        } else {
            *v_ref += (delta_v > 0.0f) ? -step : step;
        }
    }
    prev_p = curr_p;
    prev_v = v_pv;
}

LVRT(低電圧ライドスルー)

// lvrt_handler.c
void manage_lvrt_state(InverterCtx *ctx, InverterConfig *cfg) {
    float v_grid_rms = ctx->v_grid * 0.707f; // 実効値の近似
    float nominal_rms = cfg->grid_v_peak * 0.707f;
    
    if (v_grid_rms < 0.8f * nominal_rms) {
        ctx->lvrt_active = true;
        ctx->i_reactive_ref = 1.2f * ctx->i_ref_peak; // 無効電流の注入
    } else if (ctx->lvrt_active && v_grid_rms > 0.9f * nominal_rms) {
        ctx->lvrt_active = false;
        ctx->i_reactive_ref = 0.0f;
    }
}

パラメータ調整と実験結果

PIゲインの調整ガイドライン

制御ループ Kp 範囲 Ki 範囲 調整手法
電圧外環 0.2 ~ 1.0 5 ~ 20 システムが限界振動するまでKiを徐々に増加させる
電流内環 0.5 ~ 2.0 20 ~ 100 制御帯域幅をスイッチング周波数の1/10に設定する

SPWM変調パラメータ

パラメータ 推奨値 備考
キャリア周波数 10 ~ 20 kHz 可聴域以上のノイズ低減
デッドタイム 2 ~ 5 μs 上下アームの短絡防止
変調率リミット ±0.95 過変調による波形歪みの回避

システム性能評価

評価項目 測定結果
THD(全高調波歪み率) < 3.0% (定格負荷時)
力率 (Power Factor) > 0.99
変換効率 96.5% (定格負荷時)
電流応答時間 < 100 μs

トラブルシューティング

症状 推定される原因 解決策
連系電流の波形歪み デッドタイムが長すぎる デッドタイムを2μsまで短縮する
システムの発振 PIゲイン(特にKi)が大きすぎる 積分ゲイン(Ki)を削減する
系統連系できない PLLの位相同期外れ SOGIのパラメータ(k_sogi)を再調整する
変換効率の低下 スイッチング損失の増大 キャリア周波数を最適化、またはSiC/GaN素子への変更を検討

タグ: STM32 PowerElectronics GridTiedInverter SOGI-PLL SPWM

9月24日 13:51 投稿