본문 바로가기
Power Electronics/DC-DC변환

TI C2000 DSP를 사용한 LLC 풀-브릿지 컨버터 2차측 동기 정류 디지털 제어기 설계

by linuxgo 2025. 8. 26.
반응형

1. 서론

LLC 공진 컨버터는 절연형 DC-DC 변환기로, 제로 전압 스위칭(ZVS)과 제로 전류 스위칭(ZCS)을 통해 높은 효율을 제공합니다. 풀-브릿지 토폴로지와 2차측 동기 정류(SR)를 사용하여 고전력 애플리케이션에 적합하며, TI의 C2000 DSP(F28379D)는 고속 PWM, ADC, CLA를 활용해 정밀한 디지털 제어를 구현합니다. 본 문서는 LLC 풀-브릿지 컨버터의 2차측 동기 정류 디지털 제어기를 설계하며, 주파수 변조(FM) 제어를 적용합니다. UART를 통한 RUN/STOP 제어, 외부 스위치 입력, 소프트 스타트, 과전압/과전류 보호(OVP/OCP)를 포함합니다.

2. 설계 요구사항

  • 입력 전압 (\( V_{in} \)): 300V ~ 400V
  • 출력 전압 (\( V_{out} \)): 48V
  • 출력 전류 (\( I_{out} \)): 10A
  • 스위칭 주파수 (\( f_{sw} \)): 100kHz ~ 200kHz (공진 주파수 \( f_r = 150kHz \))
  • 샘플링 주기 (\( T_s \)): 5μs (PWM 동기화)
  • 제어 모드: 연속 공진 모드 (CRM)
  • 제어 방식: 주파수 변조 (FM) 및 2차측 동기 정류
  • 하드웨어 플랫폼: TI Delfino F28379D LaunchPad (200MHz) + 커스터마이징된 LLC 보드
  • 성능 목표:
    • 출력 전압 리플: \( \Delta V_{out} \leq 480mV \) (1% 이하)
    • 과도 응답 시간: \( \leq 200\mu s \) (부하/전압 스텝 응답)
    • 위상 마진: 45° ~ 60°
    • 대역폭: 약 10kHz (\( f_{sw}/10 \))
  • 추가 요구사항:
    • ADC: 12비트, 3.3V 기준
    • PWM: Phase-Shift 모드, 200MHz 시스템 클럭
    • 안정성: 주파수 제한 (80kHz ~ 250kHz), ADC 입력 보호
    • 디버깅: UART (SCIA, 115200 baud)로 \( V_{out}, I_{out} \), 상태 모니터링
    • 보호: 과전압 (\( V_{out} > 52.8V \)), 과전류 (\( I_{out} > 15A \))
    • 기능: UART 명령 ('R'/'S'), 외부 스위치 (GPIO4), 소프트 스타트 (20ms)
    • 최적화: CLA로 PI 연산, IQmath로 고정소수점 연산, Pre-warping

3. LLC 설계 절차

LLC 공진 컨버터 설계는 다음 단계를 따르며, 각 단계에서 필요한 수식을 명확히 제시합니다.

3.1 입력/출력 사양 정의

출력 전력 (\( P_{out} \)):

\[ P_{out} = V_{out} \times I_{out} = 48 \times 10 = 480 \, \text{W} \]

입력 전력 (효율 \( \eta = 0.95 \) 가정):

\[ P_{in} = \frac{P_{out}}{\eta} = \frac{480}{0.95} \approx 505.26 \, \text{W} \]

입력 전류 (최소 입력 전압 \( V_{in,min} = 300V \)):

\[ I_{in,rms} = \frac{P_{in}}{V_{in,min} / \sqrt{2}} = \frac{505.26}{300 / \sqrt{2}} \approx \frac{505.26}{212.13} \approx 2.38 \, \text{A} \]

3.2 트랜스포머 설계

3.2.1 턴 비율 (\( n \))

풀-브릿지 LLC에서 1차측 전압은 입력 전압의 절반으로 작용:

\[ n = \frac{V_{in,min} / 2}{V_{out}} = \frac{300 / 2}{48} = \frac{150}{48} \approx 3.125 \]

정수비로 조정하여 \( n = 3 \) (3:1) 선택.

3.2.2 이득 곡선 분석

First Harmonic Approximation (FHA)을 사용하여 이득 계산:

\[ M = \frac{V_{out}}{V_{in} / (2n)} \]

최소 이득 (\( V_{in,max} = 400V \)):

\[ M_{min} = \frac{48}{400 / (2 \times 3)} = \frac{48}{66.67} \approx 0.72 \]

최대 이득 (\( V_{in,min} = 300V \)):

\[ M_{max} = \frac{48}{300 / (2 \times 3)} = \frac{48}{50} = 0.96 \]

이득 곡선 공식:

\[ Q = \frac{\sqrt{L_r / C_r}}{R_{eq}}, \quad R_{eq} = \frac{8 n^2 R}{\pi^2} \]
\[ M = \frac{1}{\sqrt{\left(1 + \frac{L_r}{L_m} \left(1 - \frac{f_r^2}{f_{sw}^2}\right)\right)^2 + \left(Q \left(\frac{f_{sw}}{f_r} - \frac{f_r}{f_{sw}}\right)\right)^2}} \]

여기서 \( R = V_{out} / I_{out} = 48 / 10 = 4.8 \, \Omega \).

3.2.3 코어 및 턴 수

코어: ETD49 페라이트 (N87, \( A_e = 2.11 \times 10^{-4} \, \text{m}^2 \), \( l_e = 0.114 \, \text{m} \)).

실용적 턴 수: \( N_1 = 30 \), \( N_2 = 10 \) (n = 3).

3.2.4 자화 인덕턴스 (\( L_m \))

요구사항: \( L_m = 300 \, \mu H \).

\[ L_m = \frac{\mu_r \mu_0 N_1^2 A_e}{l_e + \mu_r l_g} \]

에어 갭 (\( l_g \)) 계산:

\[ l_g = \frac{\mu_0 N_1^2 A_e}{L_m} - \frac{l_e}{\mu_r} \]

대입: \( \mu_0 = 4\pi \times 10^{-7} \), \( N_1 = 30 \), \( A_e = 2.11 \times 10^{-4} \, \text{m}^2 \), \( l_e = 0.114 \, \text{m} \), \( \mu_r = 2000 \), \( L_m = 300 \times 10^{-6} \, \text{H} \)

\[ l_g = \frac{4\pi \times 10^{-7} \times 30^2 \times 2.11 \times 10^{-4}}{300 \times 10^{-6}} - \frac{0.114}{2000} \]
\[ \frac{1.256637 \times 10^{-6} \times 900 \times 2.11 \times 10^{-4}}{300 \times 10^{-6}} \approx 0.795 \]
\[ \frac{0.114}{2000} = 5.7 \times 10^{-5} \]
\[ l_g \approx 0.795 - 0.000057 \approx 0.7949 \, \text{mm} \]

결과: 에어 갭 약 0.8mm로 조정하여 \( L_m \approx 300 \, \mu H \).

3.2.5 와이어 선택

1차측 전류: \( I_{1,rms} \approx 2.38 \, \text{A} \), AWG 20.
2차측 전류: \( I_{2,rms} \approx 6.366 \, \text{A} \), AWG 16.
Litz wire 권장 (스킨 효과 감소).

3.3 공진 탱크 설계

공진 인덕터 (\( L_r \)): 50μH
공진 커패시터 (\( C_r \)): 22nF

공진 주파수 (\( f_r \)):

\[ f_r = \frac{1}{2\pi \sqrt{L_r C_r}} \]
\[ L_r C_r = 50 \times 10^{-6} \times 22 \times 10^{-9} = 1.1 \times 10^{-12} \]
\[ \sqrt{L_r C_r} \approx 1.0488088 \times 10^{-6} \]
\[ 2\pi \sqrt{L_r C_r} \approx 6.5918 \times 10^{-6} \]
\[ f_r = \frac{1}{6.5918 \times 10^{-6}} \approx 151,716 \, \text{Hz} \approx 150 \, \text{kHz} \]

품질 인자 (\( Q \)):

\[ R_{eq} = \frac{8 n^2 R}{\pi^2} = \frac{8 \times 3^2 \times 4.8}{\pi^2} \approx \frac{345.6}{9.8696} \approx 35.01 \, \Omega \]
\[ Q = \frac{\sqrt{L_r / C_r}}{R_{eq}} = \frac{\sqrt{50 \times 10^{-6} / 22 \times 10^{-9}}}{35.01} \]
\[ \sqrt{\frac{50 \times 10^{-6}}{22 \times 10^{-9}}} \approx \sqrt{2.2727 \times 10^3} \approx 47.673 \, \Omega \]
\[ Q \approx \frac{47.673}{35.01} \approx 1.36 \]

3.4 출력 커패시터 설계

리플 전압:

\[ \Delta V_{out} = \frac{I_{out}}{2 \pi f_{sw} C_{out}} \]
\[ C_{out} = \frac{10}{2 \times 3.141592653589793 \times 150000 \times 0.48} \approx \frac{10}{452389.34} \approx 22.1 \, \mu F \]

안정성을 위해: \( C_{out} = 1000 \, \mu F \) (ESR ≤ 5mΩ, 63V, 예: Panasonic EEH-ZA1J101P).

3.5 스위치 및 정류기

1차측 MOSFET: N-채널, 600V, 20A (TI CSD19536KCS, \( R_{DS(on)} \leq 5m\Omega \)), ePWM1A/B, ePWM2A/B (GPIO0~3).
2차측 SR MOSFET: N-채널, 100V, 50A (TI CSD19535KCS), ePWM3A/B (GPIO4~5), 데드타임 100ns.
게이트 드라이버: UCC27211, 4A 듀얼 채널, 3.3V 로직 호환.

3.6 센싱 및 제어 회로

전압 센싱:

\[ V_{sense} = V_{out} \times \frac{R_2}{R_1 + R_2} = 48 \times \frac{3.3k}{100k + 3.3k} \approx 1.5336 \, \text{V} \]

ADC 입력: ADCINA0 (GPIO6), 12비트, 3.3V 기준.

전류 센싱:

\[ V_{shunt} = I_{out} \times R_{shunt} = 10 \times 0.005 = 0.05 \, \text{V} \]

ADC 입력: ADCINA1 (GPIO7), CMPSS1 사용. INA240 앰프(옵션, 게인 20: 0.05V → 1V).

외부 스위치: GPIO8, 풀업 10kΩ, Low=RUN, High=STOP.
UART: SCIA, GPIO28(TX), GPIO29(RX), 115200 baud.

3.7 하드웨어 플랫폼

F28379D LaunchPad: 200MHz, 12비트 ADC, 16채널 PWM, CLA.
LLC 보드: 풀-브릿지 MOSFET, SR MOSFET, \( L_r = 50\mu H \), \( C_r = 22nF \), \( L_m = 300\mu H \), \( C_{out} = 1000\mu F \).
외부 장비: 400V/5A 전원, Tektronix TBS2000 오실로스코프, 4.8Ω 부하.

4. 아날로그 모델링

4.1 State-Space 평균화 모델

상태 변수: 공진 전류 (\( i_r \)), 공진 전압 (\( v_{Cr} \)), 자화 전류 (\( i_m \)).

Extended Describing Function (EDF) 모델:

\[ \frac{di_r}{dt} = \frac{1}{L_r} \left( v_{in} \cdot \text{sign}(\sin(\omega t)) - v_{Cr} - n V_{out} \cdot \text{sign}(i_r) \right) \]
\[ \frac{dv_{Cr}}{dt} = \frac{1}{C_r} i_r \]
\[ \frac{di_m}{dt} = \frac{1}{L_m} n V_{out} \cdot \text{sign}(i_r) \]

매트릭스 형태:

\[ \frac{d}{dt} \begin{bmatrix} i_r \\ v_{Cr} \\ i_m \end{bmatrix} = \begin{bmatrix} 0 & -\frac{1}{L_r} & 0 \\ \frac{1}{C_r} & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix} \begin{bmatrix} i_r \\ v_{Cr} \\ i_m \end{bmatrix} + \begin{bmatrix} \frac{1}{L_r} \\ 0 \\ 0 \end{bmatrix} v_{in} + \begin{bmatrix} -\frac{n}{R_{eq}} \\ 0 \\ \frac{n}{R_{eq}} \end{bmatrix} V_{out} \]

4.2 소신호 모델

FM 소신호 전달 함수:

\[ G_{vf}(s) = \frac{\hat{v}_{out}(s)}{\hat{f}_{sw}(s)} = \frac{V_{out} / f_r}{1 + s \frac{L_r}{R_{eq}} + s^2 L_r C_r} \]
\[ \frac{L_r}{R_{eq}} = \frac{50 \times 10^{-6}}{35.01} \approx 1.428 \times 10^{-6} \]
\[ L_r C_r = 50 \times 10^{-6} \times 22 \times 10^{-9} = 1.1 \times 10^{-12} \]
\[ G_{vf}(s) \approx \frac{48 / 150000}{1 + 1.428 \times 10^{-6} s + 1.1 \times 10^{-12} s^2} \approx \frac{0.00032}{1 + 1.428 \times 10^{-6} s + 1.1 \times 10^{-12} s^2} \]

4.3 MATLAB 모델링

% LLC 컨버터 플랜트 모델
Vout = 48; fr = 150000; Lr = 50e-6; Cr = 22e-9; n = 3; R = 4.8;
Req = 8 * n^2 * R / pi^2;
K = Vout / fr;
Gvf = tf(K, [Lr*Cr, Lr/Req, 1]);
figure; bode(Gvf); grid on;
figure; step(Gvf); grid on;

5. 디지털 제어기 설계

5.1 아날로그 PI 제어기

\[ G_c(s) = K_p + \frac{K_i}{s} = \frac{K_p s + K_i}{s} \]

MATLAB pidTuner로 튜닝: \( K_p = 0.2 \), \( K_i = 2000 \).

5.2 이산화 (Tustin 변환 with Pre-warping)

Pre-warping 주파수: \( \omega_p = 2 \pi \times 10000 = 62831.85 \, \text{rad/s} \).

\[ \tan\left(\frac{\omega_p T_s}{2}\right) = \tan\left(62831.85 \times \frac{5 \times 10^{-6}}{2}\right) = \tan(0.1570796) \approx 0.1583844 \]
\[ s = \frac{62831.85}{0.1583844} \cdot \frac{z - 1}{z + 1} \approx 396693.5 \cdot \frac{z - 1}{z + 1} \]

이산 PI 제어기:

\[ G_c(z) \approx \frac{0.205 z - 0.195}{z - 1} \]

차분 방정식:

\[ u[n] = u[n-1] + 0.205 e[n] - 0.195 e[n-1] \]
Ts = 5e-6;
Gc = tf([0.2 2000], [1 0]);
Gc_d = c2d(Gc, Ts, 'tustin', 'PrewarpFrequency', 2*pi*10000);
[num, den] = tfdata(Gc_d, 'v');

5.3 2차측 SR 설계

CMPSS로 전류 제로 크로싱 감지.
데드타임: 100ns (200MHz에서 20 클럭).
주파수 제한: 80kHz ~ 250kHz.

dead_time = 100e-9;
f_min = 80e3; f_max = 250e3;
t = 0:1e-9:1e-5;
pwm = square(2*pi*150e3*t, 50);
pwm_sr = [zeros(1, dead_time/1e-9) pwm(1:end-dead_time/1e-9)];
plot(t, pwm, t, pwm_sr);

6. TI C2000 DSP 구현

#include "F28x_Project.h" // F28379D 헤더 파일: 시스템 레지스터 및 함수 정의
#include "IQmathLib.h"    // 고정소수점 연산을 위한 IQmath 라이브러리

// 상수 정의: 시스템 파라미터 및 제어 설정
#define VREF _IQ(48.0)            // 출력 전압 기준값: 48V
#define KP _IQ(0.2)               // PI 제어기 비례 게인
#define KI _IQ(2000.0)            // PI 제어기 적분 게인
#define TS _IQ(0.000005)          // 샘플링 주기: 5us (200kHz)
#define ADC_VREF _IQ(3.3)         // ADC 기준 전압: 3.3V
#define ADC_MAX _IQ(4095.0)       // 12비트 ADC 최대값: 4095
#define FSW_INIT _IQ(150000.0)    // 초기 스위칭 주파수: 150kHz
#define FSW_MIN _IQ(80000.0)      // 최소 스위칭 주파수: 80kHz
#define FSW_MAX _IQ(250000.0)     // 최대 스위칭 주파수: 250kHz
#define DEAD_TIME _IQ(0.0000001)  // 데드타임: 100ns
#define SHUNT_R _IQ(0.005)        // 션트 저항: 5mΩ
#define V_OVP _IQ(52.8)           // 과전압 보호 임계값: 52.8V
#define I_OCP _IQ(15.0)           // 과전류 보호 임계값: 15A
#define SOFT_START_TIME _IQ(0.02) // 소프트 스타트 시간: 20ms
#define SOFT_START_STEPS 4000     // 소프트 스타트 단계 수: 4000
#define ERROR_COUNT_MAX 10        // 최대 에러 카운터 임계값

// 전역 변수: 시스템 상태 및 제어 변수
volatile _iq g_Vout = _IQ(0.0);         // 현재 출력 전압 (IQ 포맷)
volatile _iq g_Iout = _IQ(0.0);         // 현재 출력 전류 (IQ 포맷)
volatile _iq g_error = _IQ(0.0);        // PI 제어기 오차
volatile _iq g_fsw = _IQ(0.0);          // 현재 스위칭 주파수
volatile _iq g_error_prev = _IQ(0.0);   // 이전 오차 (PI 제어용)
volatile _iq g_fsw_prev = _IQ(0.0);     // 이전 스위칭 주파수
volatile Uint16 g_error_count = 0;       // ADC 에러 카운터
volatile Uint16 g_system_state = 0;      // 시스템 상태 (0: STOP, 1: RUN, 2: FAULT)
volatile Uint16 g_soft_start_count = 0;  // 소프트 스타트 카운터
volatile _iq g_fsw_target = FSW_INIT;   // 목표 스위칭 주파수

// 이동 평균 필터용 변수
#define FILTER_SIZE 4
volatile _iq g_Vout_buffer[FILTER_SIZE];
volatile _iq g_Iout_buffer[FILTER_SIZE];
volatile Uint16 g_filter_index = 0;

// CLA 메모리 할당: 고속 연산을 위한 CLA 데이터
#pragma DATA_SECTION(CLA_Vout, "Cla1DataRam0");  // CLA용 출력 전압
#pragma DATA_SECTION(CLA_Iout, "Cla1DataRam0");  // CLA용 출력 전류
#pragma DATA_SECTION(CLA_error, "Cla1DataRam0"); // CLA용 오차
#pragma DATA_SECTION(CLA_fsw, "Cla1DataRam0");   // CLA용 스위칭 주파수
volatile _iq CLA_Vout, CLA_Iout, CLA_error, CLA_fsw;

// 시스템 초기화: 클럭, 인터럽트, 메모리 설정
void initSystem(void) {
    InitSysCtrl();                   // 시스템 클럭 및 PLL 초기화 (200MHz)
    DINT;                            // 글로벌 인터럽트 비활성화
    InitPieCtrl();                   // PIE (Peripheral Interrupt Expansion) 초기화
    IER = 0x0000; IFR = 0x0000;     // 인터럽트 레지스터 초기화
    InitPieVectTable();              // 인터럽트 벡터 테이블 설정
    InitCla();                       // CLA (Control Law Accelerator) 초기화
}

// GPIO 초기화: PWM, ADC, 외부 스위치, UART 핀 설정
void initGPIO(void) {
    EALLOW;                          // 보호된 레지스터 접근 허용
    // PWM 출력 (ePWM1, ePWM2: 1차측, ePWM3: 2차측 SR)
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // ePWM1A
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // ePWM1B
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0; // ePWM2A
    GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0; // ePWM2B
    GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1; GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO4 = 0; // ePWM3A (SR)
    GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1; GpioCtrlRegs.GPADIR.bit.GPIO5 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0; // ePWM3B (SR)
    // ADC 입력 (ADCA 모듈 사용)
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 0; GpioCtrlRegs.GPADIR.bit.GPIO6 = 0; GpioCtrlRegs.GPAQSEL1.bit.GPIO6 = 0; // ADCINA0 (전압)
    GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 0; GpioCtrlRegs.GPADIR.bit.GPIO7 = 0; GpioCtrlRegs.GPAQSEL1.bit.GPIO7 = 0; // ADCINA1 (전류)
    // 외부 스위치
    GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0; GpioCtrlRegs.GPADIR.bit.GPIO8 = 0; GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1; // GPIO8 (RUN/STOP)
    // UART (SCIA)
    GpioCtrlRegs.GPBMUX1.bit.GPIO28 = 1; GpioCtrlRegs.GPBDIR.bit.GPIO28 = 1; GpioCtrlRegs.GPBPUD.bit.GPIO28 = 0; // SCIA TX
    GpioCtrlRegs.GPBMUX1.bit.GPIO29 = 1; GpioCtrlRegs.GPBDIR.bit.GPIO29 = 0; GpioCtrlRegs.GPBPUD.bit.GPIO29 = 1; // SCIA RX
    EDIS;                            // 보호된 레지스터 접근 비활성화
}

// ADC 초기화: ADCA 모듈로 전압/전류 센싱
void initADC(void) {
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 8;                   // ADC 클럭 분주: 200MHz/8 = 25MHz
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;                   // SOC0: ADCINA0 (전압 센싱)
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14;                  // 샘플링 윈도우: 14 클럭
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5;                 // 트리거: ePWM1 SOCA
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1;                   // SOC1: ADCINA1 (전류 센싱)
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = 14;                  // 샘플링 윈도우: 14 클럭
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5;                 // 트리거: ePWM1 SOCA
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0;               // 인터럽트: SOC0 완료 시
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;                 // ADC 인터럽트 1 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;               // 인터럽트 플래그 초기화
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;                // 인터럽트 펄스 위치 설정
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;                   // ADC 전원 활성화
    DELAY_US(1000);                                     // ADC 안정화 대기: 1ms
    EDIS;
}

// PWM 초기화: 1차측 풀-브릿지 및 2차측 SR PWM 설정
void initPWM(void) {
    EALLOW;
    // ePWM1 설정 (1차측 풀-브릿지 상단)
    EPwm1Regs.TBCTL.bit.CTRMODE = 0;                    // 업카운트 모드
    EPwm1Regs.TBCTL.bit.PHSEN = 1;                      // 페이즈 동기화 활성화
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1;                  // 고속 클럭 분주: 200MHz
    EPwm1Regs.TBCTL.bit.CLKDIV = 0;                     // 클럭 분주: 1
    EPwm1Regs.TBPRD = (Uint16)(200e6 / (2 * _IQtoF(FSW_INIT))); // 주기: 150kHz
    EPwm1Regs.CMPA.bit.CMPA = EPwm1Regs.TBPRD / 2;      // 듀티 사이클: 50%
    EPwm1Regs.TBCTR = 0;                                // 타이머 카운터 초기화
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;                     // SOCA 활성화 (ADC 트리거)
    EPwm1Regs.ETSEL.bit.SOCASEL = 1;                    // SOCA 트리거: 카운터=0
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;                     // SOCA 주기: 매 사이클
    EPwm1Regs.DBCTL.bit.OUT_MODE = 3;                   // 데드밴드 활성화
    EPwm1Regs.DBRED.bit.DBRED = (Uint16)(_IQtoF(DEAD_TIME) * 200e6); // 상승 데드타임: 100ns
    EPwm1Regs.DBFED.bit.DBFED = (Uint16)(_IQtoF(DEAD_TIME) * 200e6); // 하강 데드타임: 100ns
    EPwm1Regs.TBCTL.bit.SYNCOSEL = 0;                   // 동기화 출력: CTR=0
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;                  // 프리-런 모드

    // ePWM2 설정 (1차측 풀-브릿지 하단)
    EPwm2Regs = EPwm1Regs;                              // ePWM1 설정 복사
    EPwm2Regs.TBPHS.bit.TBPHS = 0;                      // 페이즈 오프셋: 0

    // ePWM3 설정 (2차측 SR)
    EPwm3Regs = EPwm1Regs;                              // ePWM1 설정 복사
    EPwm3Regs.TBPHS.bit.TBPHS = (Uint16)(EPwm1Regs.TBPRD / 2); // SR 페이즈 오프셋: 180도
    EDIS;
}

// CMPSS 초기화: 2차측 SR 전류 제로 크로싱 감지
void initCMPSS(void) {
    EALLOW;
    Cmpss1Regs.COMPCTL.bit.COMPDACE1 = 1;               // 비교기 1 활성화
    Cmpss1Regs.COMPCTL.bit.COMPHSOURCE = 0;             // 하이 사이드 소스: DAC
    Cmpss1Regs.COMPDACCTL.bit.DACSOURCE = 0;            // DAC 소스: 내부 DAC
    Cmpss1Regs.DACHVALS.bit.DACVAL = 0;                 // DAC 기준: 0V (제로 크로싱)
    Cmpss1Regs.COMPCTL.bit.ASYNCHEN = 1;                // 비동기 출력 활성화
    EDIS;
}

// CLA 초기화: PI 제어 연산을 위한 CLA 설정
void initCLA(void) {
    EALLOW;
    Cla1Regs.MVECT1 = (Uint16)((Uint32)&cla_task1_isr); // CLA 태스크 1 인터럽트 벡터
    Cla1Regs.MCTL.bit.IACKE = 1;                        // CLA 인터럽트 활성화
    Cla1Regs.MIER.bit.MINT1 = 1;                        // 태스크 1 인터럽트 활성화
    EDIS;
}

// UART 초기화: 디버깅 및 상태 모니터링 (115200 baud)
void initUART(void) {
    EALLOW;
    SciaRegs.SCICCR.all = 0x0007;                       // 8비트 데이터, 패리티 없음, 1 스톱 비트
    SciaRegs.SCICTL1.all = 0x0023;                      // 송수신 활성화, SWRESET
    SciaRegs.SCIHBAUD.all = 0x0000;                     // Baud rate: 115200 (200MHz 기준)
    SciaRegs.SCILBAUD.all = 216;                        // Baud rate 설정
    SciaRegs.SCICTL2.bit.RXBKINTENA = 1;                // 수신 인터럽트 활성화
    SciaRegs.SCIFFTX.bit.TXFIFORST = 1;                 // 송신 FIFO 리셋
    SciaRegs.SCIFFRX.bit.RXFIFORST = 1;                 // 수신 FIFO 리셋
    SciaRegs.SCIFFTX.bit.TXFFIENA = 1;                  // 송신 FIFO 인터럽트 활성화
    SciaRegs.SCIFFRX.bit.RXFFIENA = 1;                  // 수신 FIFO 인터럽트 활성화
    EDIS;
}

// UART 데이터 전송: 전압/전류 데이터 전송
void scia_xmit(_iq data) {
    Uint16 val = (Uint16)(_IQtoF(data) * 1000);         // IQ 포맷을 정수로 변환 (mV 단위)
    while (SciaRegs.SCIFFTX.bit.TXFFST != 0);           // 송신 버퍼가 비어질 때까지 대기
    SciaRegs.SCITXBUF.all = val;                        // 데이터 전송
}

// UART 상태 전송: 시스템 상태 전송
void scia_xmit_status(Uint16 status) {
    while (SciaRegs.SCIFFTX.bit.TXFFST != 0);           // 송신 버퍼가 비어질 때까지 대기
    SciaRegs.SCITXBUF.all = status;                     // 상태 전송 (0: STOP, 1: RUN, 2: FAULT)
}

// 이동 평균 필터: ADC 입력 노이즈 감소
_iq movingAverageFilter(_iq new_value, volatile _iq *buffer) {
    buffer[g_filter_index] = new_value;
    g_filter_index = (g_filter_index + 1) % FILTER_SIZE;
    _iq sum = _IQ(0.0);
    Uint16 i;
    for (i = 0; i < FILTER_SIZE; i++) {
        sum = _IQmpy(sum, buffer[i]);
    }
    return _IQdiv(sum, _IQ(FILTER_SIZE));
}

// 소프트 스타트: 부팅 시 전류 충격 방지를 위한 주파수 점진적 감소
void softStart(void) {
    if (g_soft_start_count < SOFT_START_STEPS) {         // 소프트 스타트 진행 중
        g_fsw = FSW_MAX - _IQmpy(_IQdiv(_IQ(g_soft_start_count), _IQ(SOFT_START_STEPS)), (FSW_MAX - g_fsw_target));
        Uint16 prd = (Uint16)(200e6 / (2 * _IQtoF(g_fsw))); // PWM 주기 계산
        EPwm1Regs.TBPRD = prd; EPwm1Regs.CMPA.bit.CMPA = prd / 2; // ePWM1 업데이트
        EPwm2Regs.TBPRD = prd; EPwm2Regs.CMPA.bit.CMPA = prd / 2; // ePWM2 업데이트
        EPwm3Regs.TBPRD = prd; EPwm3Regs.CMPA.bit.CMPA = prd / 2; // ePWM3 업데이트
        g_soft_start_count++;                                   // 카운터 증가
    } else {
        g_fsw = g_fsw_target;                                  // 목표 주파수로 전환
        Uint16 prd = (Uint16)(200e6 / (2 * _IQtoF(g_fsw)));    // 최종 PWM 주기
        EPwm1Regs.TBPRD = prd; EPwm1Regs.CMPA.bit.CMPA = prd / 2;
        EPwm2Regs.TBPRD = prd; EPwm2Regs.CMPA.bit.CMPA = prd / 2;
        EPwm3Regs.TBPRD = prd; EPwm3Regs.CMPA.bit.CMPA = prd / 2;
    }
}

// 보호 기능: 과전압/과전류 감지 및 시스템 정지
void checkProtection(void) {
    if (_IQtoF(g_Vout) > _IQtoF(V_OVP) || _IQtoF(g_Iout) > _IQtoF(I_OCP)) { // OVP/OCP 조건 확인
        updateSystemState(2);                                       // FAULT 상태로 전환
        EALLOW;
        EPwm1Regs.TBCTL.bit.CTRMODE = 3; EPwm1Regs.CMPA.bit.CMPA = 0; // PWM1 정지
        EPwm2Regs.TBCTL.bit.CTRMODE = 3; EPwm2Regs.CMPA.bit.CMPA = 0; // PWM2 정지
        EPwm3Regs.TBCTL.bit.CTRMODE = 3; EPwm3Regs.CMPA.bit.CMPA = 0; // PWM3 정지
        g_soft_start_count = 0; g_fsw = _IQ(0.0); g_fsw_prev = _IQ(0.0); // 변수 초기화
        EDIS;
    }
}

// 시스템 상태 업데이트: RUN/STOP/FAULT 상태 관리
void updateSystemState(Uint16 new_state) {
    if (new_state == g_system_state) return;                    // 동일 상태면 무시
    g_system_state = new_state;                                 // 상태 업데이트
    EALLOW;
    if (g_system_state == 1) {                                  // RUN 상태
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;                       // PWM1 활성화
        EPwm2Regs.TBCTL.bit.CTRMODE = 0;                       // PWM2 활성화
        EPwm3Regs.TBCTL.bit.CTRMODE = 0;                       // PWM3 활성화
        g_soft_start_count = 0; g_fsw = FSW_MAX;               // 소프트 스타트 초기화
    } else {                                                   // STOP 또는 FAULT
        EPwm1Regs.TBCTL.bit.CTRMODE = 3; EPwm1Regs.CMPA.bit.CMPA = 0; // PWM1 정지
        EPwm2Regs.TBCTL.bit.CTRMODE = 3; EPwm2Regs.CMPA.bit.CMPA = 0; // PWM2 정지
        EPwm3Regs.TBCTL.bit.CTRMODE = 3; EPwm3Regs.CMPA.bit.CMPA = 0; // PWM3 정지
        g_soft_start_count = 0; g_fsw = _IQ(0.0); g_fsw_prev = _IQ(0.0); // 변수 초기화
    }
    EDIS;
    scia_xmit_status(g_system_state);                           // 상태 UART 전송
}

// 인터럽트 초기화: ADC, CLA, UART 인터럽트 설정
void initInterrupts(void) {
    EALLOW;
    PieVectTable.ADCA1_INT = &adc_isr;                         // ADC 인터럽트 벡터
    PieVectTable.CLA1_1_INT = &cla_task1_isr;                  // CLA 태스크 1 벡터
    PieVectTable.SCIA_RX_INT = &scia_rx_isr;                   // UART 수신 벡터
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;                         // ADC 인터럽트 활성화
    PieCtrlRegs.PIEIER11.bit.INTx1 = 1;                        // CLA 인터럽트 활성화
    PieCtrlRegs.PIEIER9.bit.INTx1 = 1;                         // UART 인터럽트 활성화
    IER |= M_INT1 | M_INT9 | M_INT11;                          // CPU 인터럽트 활성화
    EDIS;
}

// ADC 인터럽트: 전압/전류 센싱 및 보호 로직
__interrupt void adc_isr(void) {
    // SOC 완료 확인
    if (AdcaRegs.ADCSOCFLG1.bit.SOC0 && AdcaRegs.ADCSOCFLG1.bit.SOC1) {
        _iq Vout_raw = _IQmpy(_IQ(AdcaResultRegs.ADCRESULT0), _IQdiv(ADC_VREF, ADC_MAX));
        _iq Iout_raw = _IQmpy(_IQ(AdcaResultRegs.ADCRESULT1), _IQdiv(ADC_VREF, _IQmpy(ADC_MAX, SHUNT_R)));
        // 이동 평균 필터 적용
        g_Vout = movingAverageFilter(Vout_raw, g_Vout_buffer);
        g_Iout = movingAverageFilter(Iout_raw, g_Iout_buffer);
        // ADC 입력 범위 검증
        if (_IQtoF(g_Vout) < 0.0f || _IQtoF(g_Vout) > 60.0f || _IQtoF(g_Iout) < 0.0f || _IQtoF(g_Iout) > 20.0f) {
            g_error_count++;
            if (g_error_count >= ERROR_COUNT_MAX) {
                g_Vout = _IQ(0.0); g_Iout = _IQ(0.0); // 지속적 오류 시 초기화
            }
        } else {
            g_error_count = 0; // 정상 입력 시 에러 카운터 리셋
        }
        CLA_Vout = g_Vout; CLA_Iout = g_Iout; // CLA로 데이터 전달
    }
    checkProtection();
    if (g_system_state == 1) {
        softStart();
        Cla1Regs.MIFRC.bit.INT1 = 1; // CLA 태스크 트리거
    }
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIE 그룹 ACK
}

// CLA 태스크: PI 제어 및 주파수 업데이트
__interrupt void cla_task1_isr(void) {
    if (g_system_state != 1) return;                            // RUN 상태가 아니면 종료
    CLA_error = _IQmpy(VREF - CLA_Vout, _IQ(1.0));           // 오차 계산: Vref - Vout
    // PI 제어기: u[n] = u[n-1] + 0.205*e[n] - 0.195*e[n-1]
    CLA_fsw = g_fsw_prev + _IQmpy(_IQ(0.205), CLA_error) - _IQmpy(_IQ(0.195), g_error_prev);
    // 주파수 제한: 80kHz ~ 250kHz
    if (CLA_fsw > FSW_MAX) CLA_fsw = FSW_MAX;
    if (CLA_fsw < FSW_MIN) CLA_fsw = FSW_MIN;
    // 소프트 스타트 완료 후 PWM 업데이트
    if (g_soft_start_count >= SOFT_START_STEPS) {
        Uint16 prd = (Uint16)(200e6 / (2 * _IQtoF(CLA_fsw))); // PWM 주기 계산
        EPwm1Regs.TBPRD = prd; EPwm1Regs.CMPA.bit.CMPA = prd / 2; // ePWM1 업데이트
        EPwm2Regs.TBPRD = prd; EPwm2Regs.CMPA.bit.CMPA = prd / 2; // ePWM2 업데이트
        EPwm3Regs.TBPRD = prd; EPwm3Regs.CMPA.bit.CMPA = prd / 2; // ePWM3 업데이트
    }
    Cmpss1Regs.DACHVALS.bit.DACVAL = 0;                      // SR 제로 크로싱 기준
    g_error_prev = CLA_error; g_fsw_prev = CLA_fsw;          // 이전 값 업데이트
    Cla1Regs.MIRUN.bit.INT1 = 0;                             // CLA 인터럽트 클리어
}

// UART 수신 인터럽트: 'R' (RUN), 'S' (STOP) 명령 처리
__interrupt void scia_rx_isr(void) {
    Uint16 rx_data = SciaRegs.SCIRXBUF.all;                  // 수신 데이터 읽기
    if (rx_data == 'R' && g_system_state == 0) {             // 'R' 명령: STOP → RUN
        updateSystemState(1);
    } else if (rx_data == 'S' && g_system_state == 1) {      // 'S' 명령: RUN → STOP
        updateSystemState(0);
    } else {
        scia_xmit_status(0xFFFF);                            // 잘못된 명령어: 에러 상태 전송
    }
    SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1;                    // 오버플로우 클리어
    SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1;                    // 수신 인터럽트 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;                  // PIE 그룹 ACK
}

// 메인 함수: 시스템 초기화 및 메인 루프
void main(void) {
    initSystem();                                            // 시스템 초기화
    initGPIO();                                              // GPIO 설정
    initADC();                                               // ADC 설정
    initPWM();                                               // PWM 설정
    initCMPSS();                                             // CMPSS 설정
    initCLA();                                               // CLA 설정
    initUART();                                              // UART 설정
    initInterrupts();                                        // 인터럽트 설정
    EALLOW; EINT; ERTM; EDIS;                               // 글로벌 인터럽트 활성화
    updateSystemState(0);                                    // 초기 상태: STOP
    // 이동 평균 필터 버퍼 초기화
    Uint16 i;
    for (i = 0; i < FILTER_SIZE; i++) {
        g_Vout_buffer[i] = _IQ(0.0);
        g_Iout_buffer[i] = _IQ(0.0);
    }
    while(1) {                                               // 메인 루프
        // 외부 스위치 (GPIO8)로 RUN/STOP 제어
        if (GpioDataRegs.GPADAT.bit.GPIO8 == 0 && g_system_state == 0) {
            updateSystemState(1);                            // Low: RUN
        } else if (GpioDataRegs.GPADAT.bit.GPIO8 == 1 && g_system_state == 1) {
            updateSystemState(0);                            // High: STOP
        }
        // 주기적 상태 모니터링 (100ms 간격)
        scia_xmit(g_Vout); scia_xmit(g_Iout); scia_xmit_status(g_system_state);
        DELAY_US(100000);                                    // 100ms 대기
    }
}

7. 시뮬레이션 및 검증

7.1 MATLAB/Simulink 시뮬레이션

파라미터: \( L_r = 50 \, \mu H \), \( C_r = 22 \, \text{nF} \), \( L_m = 300 \, \mu H \), \( R = 4.8 \, \Omega \).
제어기: Discrete Transfer Function [0.205, -0.195], [1, -1].
테스트: 부하 스텝 (5A → 10A), 전압 스텝 (48V → 50V), 소프트 스타트 (20ms).
기준: 리플 \( \leq 480mV \), 과도 응답 \( \leq 200\mu s \), 위상 마진 \( \geq 45^\circ \).

7.2 하드웨어 테스트

장비: F28379D LaunchPad, LLC 보드, 400V/5A 전원, 오실로스코프, 4.8Ω 부하.
절차:

  1. CCS v12로 빌드/플래시.
  2. Simulink External Mode로 \( K_p \), \( K_i \), \( f_{sw} \) 튜닝.
  3. UART로 \( V_{out}, I_{out} \), 상태 모니터링 ('R'/'S' 명령).
  4. 외부 스위치 (GPIO8)로 RUN/STOP 테스트.
  5. 소프트 스타트, OVP, OCP 확인.

기준: \( V_{out} = 48V \pm 480mV \), 위상 마진 \( \geq 45^\circ \), 과도 응답 \( \leq 200\mu s \).

8. 참고 자료

 

반응형