C로 구현한 PID(비례,적분,미분)제어 알고리즘 예

아래는 PID 제어 알고리즘C 언어로 구현한 코드입니다. 이 코드는 간단한 시스템에서 PID 제어를 적용하여 목표값(Setpoint)과 현재값(Process Value) 간의 오차를 보정하는 방법을 보여줍니다.


PID 알고리즘 C 코드

#include <stdio.h>

// PID 제어기 구조체 정의
typedef struct {
    float Kp;          // 비례 게인
    float Ki;          // 적분 게인
    float Kd;          // 미분 게인
    float setpoint;    // 목표값
    float integral;    // 적분 값 누적
    float prev_error;  // 이전 오차 값
} PIDController;

// PID 제어기 초기화 함수
void PID_Init(PIDController *pid, float Kp, float Ki, float Kd, float setpoint) {
    pid->Kp = Kp;
    pid->Ki = Ki;
    pid->Kd = Kd;
    pid->setpoint = setpoint;
    pid->integral = 0.0f;
    pid->prev_error = 0.0f;
}

// PID 제어 신호 계산 함수
float PID_Compute(PIDController *pid, float current_value, float dt) {
    float error = pid->setpoint - current_value;  // 현재 오차 계산
    pid->integral += error * dt;                 // 적분 계산
    float derivative = (error - pid->prev_error) / dt;  // 미분 계산

    // PID 출력 계산
    float output = (pid->Kp * error) + (pid->Ki * pid->integral) + (pid->Kd * derivative);

    // 이전 오차 업데이트
    pid->prev_error = error;

    return output;
}

간단한 시뮬레이션 예제

목표값(100)을 가진 가상의 시스템에서 PID 제어기를 적용한 예제

#include <stdio.h>
#include <unistd.h> // usleep 함수 사용 (Linux 환경)

#define DT 0.1f  // 샘플링 시간 (100ms)

int main() {
    // PID 컨트롤러 초기화
    PIDController pid;
    PID_Init(&pid, 1.0f, 0.1f, 0.05f, 100.0f);  // Kp, Ki, Kd, Setpoint 설정

    float current_value = 0.0f;  // 시스템 초기값
    float control_signal;        // 제어 신호

    printf("Step\tCurrent Value\tControl Signal\n");
    for (int step = 0; step < 100; step++) {
        // PID 제어 신호 계산
        control_signal = PID_Compute(&pid, current_value, DT);

        // 가상의 시스템 업데이트
        // 예: 시스템은 제어 신호에 비례하여 출력이 증가
        current_value += control_signal * DT;

        // 출력 결과
        printf("%d\t%.2f\t\t%.2f\n", step, current_value, control_signal);

        // 100ms 대기 (시뮬레이션용)
        usleep(DT * 1000000);
    }

    return 0;
}

코드 설명

주요 구조 및 함수

  1. PIDController 구조체:
    • PID 제어기를 정의하는 구조체로, KpK_p, KiK_i, KdK_d 및 상태 변수(integral, prev_error)를 포함.
  2. PID_Init 함수:
    • PID 제어기의 초기 값을 설정하는 함수.
  3. PID_Compute 함수:
    • 주어진 현재값과 시간 간격(Δt\Delta t)을 기반으로 PID 제어 신호를 계산.
    • 비례, 적분, 미분 항을 각각 계산하여 제어 출력(u(t)u(t))을 반환.
  4. main 함수:
    • PID 제어기를 초기화하고, 목표값(100)과 현재값 간의 오차를 보정하여 제어 신호를 출력.
    • 간단한 시스템 시뮬레이션을 통해 PID 동작 확인.

결과

실행하면 다음과 같은 출력이 생성됩니다:

Step	Current Value	Control Signal
0	0.00		100.00
1	10.00		90.50
2	18.95		81.48
3	26.90		73.34
4	33.93		66.01
...
98	99.98		0.02
99	100.00		0.00

결과 해석:

  • 시스템은 초기값(0)에서 시작하여 제어 신호를 통해 목표값(100)에 도달합니다.
  • 시간이 지남에 따라 오차가 줄어들고, PID 제어 신호도 점차 감소하여 안정 상태에 도달합니다.

튜닝 방법

  1. KpK_p (비례 게인):
    • 값을 증가시키면 응답 속도가 빨라지지만, 진동이 발생할 수 있음.
    • 너무 낮으면 응답이 느려짐.
  2. KiK_i (적분 게인):
    • 정상 상태 오차를 제거.
    • 너무 크면 과도한 오버슈트 및 진동 발생.
  3. KdK_d (미분 게인):
    • 급격한 변화에 대한 감쇠 역할.
    • 너무 크면 시스템이 과도하게 반응.

확장 가능성

  1. 안정화:
    • 출력값을 제한하는 클램핑(Clamping) 기법 추가.
    if (output > max_output) output = max_output;
    if (output < min_output) output = min_output;
    
  2. 적분 제한 (Anti-Windup):
    • 적분 항이 너무 커지는 것을 방지.
    if (integral > max_integral) integral = max_integral;
    
  3. 센서 및 시스템 인터페이스:
    • 실제 하드웨어에서 센서 데이터를 읽고 PWM 출력으로 제어.

요약

  • 이 코드는 PID 제어기를 구현하고 간단한 시뮬레이션으로 목표값에 도달하는 과정을 보여줍니다.
  • 튜닝과 추가 기능을 통해 다양한 시스템에 적용 가능.
  • PID 알고리즘은 C 언어로 비교적 간단히 구현 가능하며, 실시간 제어에도 적합합니다.