FPGA 기반 FOC 전류 제어 루프 구현: Verilog 하드웨어 설계

FPGA에 모터 제어를 집어넣는 작업은 어렵지 않다. 이 글에서는 간소화된 FOC 전류 제어 루프 구현을 단계별로 분석하며, Verilog 코드가 하드웨어와 어떻게 상호작용하는지 살펴본다. 이 버전은 위치 루프나 속도 루프 없이 전류 폐루프 제어에만 집중하며, 빠른 응답이 필요한 상황에 적합하다.

먼저 RTL 구조를 살펴보자. 최상위 모듈은 AD7928의 샘플 데이터를 입력받아 Clarke/Park 변환을 거친 후 PI 제어기로 전달하고, SVPWM 모듈이 듀티 사이클 신호를 생성한다. 흥미로운 점은 전체 데이터 흐름이 고정 소수점 연산으로 처리되며, PI 조정도 자체 정수 연산을 사용한다는 것이다.

ADC 인터페이스는 다음과 같이 구현한다:

module adc_interface(
    input clk,
    input [11:0] adc_raw,
    output reg signed [15:0] phase_current
);
// 전류 보정 계수: 샘플링 저항과 연산 증폭기 회로 기반 계산
parameter SCALE_FACTOR = 3276; // Q12 형식

always @(posedge clk) begin
    // 원시 ADC 값을 부호 있는 숫자로 변환
    phase_current <= (adc_raw - 2048) * SCALE_FACTOR >>> 12;
end
endmodule

여기서 주의할 점이 있다. AD7928은 단일 입력이므로 영점 드리프트 보정이 필요하다. 실제로는 초기화 시 오프셋을 읽고 전원 켜짐 시 자동 보정을 수행하는 것이 좋다.

PI 제어기 구현은 실력이 드러나는 부분으로, 하드코어 코드를 직접 보자:

module pi_controller(
    input clk,
    input rst,
    input signed [15:0] err,
    output reg signed [15:0] out
);
parameter KP = 80;   // Q8.8 형식
parameter KI = 5;    // Q8.8
reg signed [31:0] integ;

always @(posedge clk or posedge rst) begin
    if(rst) begin
        integ <= 0;
        out <= 0;
    end else begin
        integ <= integ + (err * KI) >>> 8; // 적분 항
        out <= (err * KP + integ) >>> 16;  // 오버플로 방지
    end
end
endmodule

이 우측 시프트 연산의 위치가 제어 정밀도에 직접적인 영향을 미친다. 시뮬레이션 중 적분 포화가 발생하면, 안티-와인드업 로직을 추가해야 하지만, 이 간소화 버전에서는 생략한다.

SVPWM 생성이 핵심이다. 2-레벨 알고리즘은 다음과 같다:

module svpwm(
    input clk,
    input signed [15:0] Vα,
    input signed [15:0] Vβ,
    output reg [2:0] PWM
);
// 공간 벡터 섹터 판별
wire [2:0] sector = calc_sector(Vα, Vβ);

// 듀티 사이클 계산
reg [15:0] T1, T2;
always @(posedge clk) begin
    case(sector)
        1: begin
            T1 = (Vβ * 886) >> 12; // 886 ≈ sqrt(3) * 512
            T2 = (Vα * 512 + Vβ * 296) >> 12;
        end
        //... 다른 섹터는 유사하게 처리
    endcase
end

// 타이머 비교값 생성
reg [15:0] cmp[0:2];
always @(*) begin
    cmp[0] = (PERIOD - T1 - T2) / 2;
    cmp[1] = cmp[0] + T1;
    cmp[2] = cmp[1] + T2;
end
endmodule

근사 계산을 통해 삼각 함수를 대체했으며, 측정된 파형 왜곡은 2% 미만이다. 타이머 주기는 PWM 주파수에 따라 조정되어야 하며, 예를 들어 20kHz에서 50us 주기가 타이머 값 = 클록 주파수 * 50e-6에 해당한다.

직렬 통신 모듈은 파라미터 조정을 담당하며, 상태 머신을 통해 명령을 해석한다:

case(rx_state)
    IDLE: if(rx_data == 'hAA') rx_state <= CMD;
    CMD: begin
        case(rx_data)
            'h01: begin target_Iq <= next_data; end
            'h02: begin Kp <= next_data; end
            //...
        endcase
    end
endcase

실제 측정에서 115200 보드레이트는 문제없지만, 클록 도메인 간 처리에 주의해야 한다. AS5600 피드백 처리는 간단하며, I2C를 통해 매 밀리초마다 각도 값을 읽으면 된다.

Simulink 모델에서 전류 루프는 이산 전달 함수 블록으로 추상화되며, Verilog 코드의 샘플링/계산 주기와 엄격하게 일치한다. 시뮬레이션 중 위상 지연이 30도를 초과하면 계산 주파수를 조정해야 하며, 그때 클록 분할 파라미터를 수정하러 돌아와야 한다.

마지막으로 하드웨어 적응 팁을 소개한다:

  1. 전류 샘플링 타이밍은 PWM 중점에 맞춰 스위칭 노이즈를 피해야 한다.
  2. 데드 타임은 PWM 모듈에서 직접 처리하며, 4개의 클록 사이클 지연을 추가한다.
  3. Q 형식 변환은 Python 스크립트로 계수를 사전 처리하여 수동 계산 오류를 방지하는 것이 좋다.

이 코드는 Artix-7에서 실행되며, 리소스 사용량은 대략 다음과 같다:

  • LUT: 12%
  • FF: 8%
  • BRAM: 3개
  • 최대 주파수: 85MHz

다른 플랫폼으로 이식할 때는 주로 세 가지를 수정해야 한다: 클록 관리, 주변 인터페이스 주소, PWM 생성 모듈의 구체적인 구현. 전류 루프 핵심 코드는 기본적으로 변경할 필요가 없으며, 이는 FPGA로 제어하는 장점이다 — 하드웨어가 변경되어도 알고리즘을 다시 작성할 필요가 없다.

태그: FPGA FOC Verilog 전류제어 PI제어기

6월 2일 19:34에 게시됨