Đây là thuật toán được sử dụng phổ biến để tự động điều chỉnh, giúp động cơ luôn hoạt động ở giá trị cân bằng và ít độ lỗi nhất. Bài viết nhằm giúp độc giả nắm được thuật toán PID theo cách dễ hiểu nhất. Tác giả sử dụng MATLAB để minh họa thuật toán và cách áp dụng vào bài toán thực tế.
Data Structure & Algorithm Toán học Kim Uyên 2017-03-09 17:26:50

Giới thiệu

PID là thuật toán được sử dụng phổ biến trong lĩnh vực điện, điện tử. Dùng để điều khiển để động cơ tự động và giúp đạt được giá trị chuẩn mong muốn, có độ lỗi nhỏ nhất.

Bài viết trình bày chi tiết về thuật toán, đưa ra ví dụ thực tế và hướng đưa thuật toán vào để giải quyết bài toán thực tế. Hi vọng cách hiểu của tôi về thuật toán PID trong bài toán này có thể giúp các bạn có cái nhìn dễ dàng về nó.

Tiền đề bài viết

Trong quá trình học tập ở STDIO Training, nhóm tôi được giao đề tài tạo một chiếc xe tự động sử dụng Arduino, cảm biến âm thanh cùng bộ điều khiển động cơ. Bài toán đặt ra là chiếc xe có thể chạy thẳng, do đó, PID là lựa chọn phù hợp để giải quyết trường hợp này. Tuy nhiên, trong quá trình tìm hiểu, phải qua 3 lần làm lại tôi mới hiểu thuật toán hoạt động như thế nào. Vì thế, bài viết này nhằm đưa đến độc giả cái nhìn dễ hiểu nhất về thuật toán.

Đối tượng hướng đến

Bài viết hướng đến mọi đối tượng quan tâm và có chút kiến thức cơ bản về lập trình điện, điện tử.

Nguyên lý thuật toán

Tôi có một ví dụ: có một chiếc xe như đã nói ở trên, giả sử rằng, muốn bánh xe quay được 200 vòng/giây, sẽ tương đương với giá trị truyền vào cho động cơ là pwm = 200. Trong khi đó, thực tế chiếc xe đang chạy vào mép lề của một bãi cát (tức là bánh trái chạy ở đường bình thường, bánh phải chạy trên bãi cát), ma sát lớn làm bánh phải chỉ quay được 100 vòng/giây, như vậy xe có thể chạy lệch phải. Và ta tính được độ lỗi bánh xe phải lúc này là 100 vòng. Ta thấy rằng để xe chạy thẳng, cần tăng tốc độ truyền vào cho động cơ bên phải ở thời điểm này để giúp bánh xe phải đạt được 200 vòng/giây bất kể có ma sát. Từ giá trị độ lỗi của số vòng quay, ta cần quy ra giá trị pwm để truyền vào cho động cơ. Khi này pwm = 200 + 50 (giả sử: 100 vòng/giây ~ 50 pwm). P/S: Những con số trong ví dụ này đều là giả.

Kết quả của thuật toán là độ lỗi của tốc độ động cơ tại một thời điểm. Để từ giá trị này, ta có thể sử dụng để điều chỉnh và đưa vào bài toán một cách hợp lý.

Giá trị trả về của thuật toán được tổng hợp dựa trên 3 thành phần là P, I và D. Có nghĩa, thuật toán dựa trên độ lỗi theo thời gian trong quá trình hoạt động của động cơ. Bao gồm độ lỗi ở thời điểm hiện tại, độ lỗi dựa trên toàn bộ quá trình và đạo hàm độ lỗi ở thời điểm hiện tại.

Công thức:

img_01

Giải thích:

Kp, Ki, Kd lấy giá trị không âm và tương ứng với độ ảnh hưởng của 3 thành phần P, I hay D vào giá trị trả về.
Phân tích về 3 thành phần:

  • P: độ lỗi ở thời điểm hiện tại. Để có độ lỗi này, bạn cần một giá trị tên pivot, là giá trị lý tưởng mà bạn mong muốn động cơ đạt được. Ta có thể suy ra độ lỗi từ pivot.
  • I: độ lỗi của toàn bộ quá trình, với giá trị này, giá trị điều chỉnh sẽ phụ thuộc vào toàn bộ quá trình hoạt động của động cơ. Giá trị này bạn sẽ lấy dựa vào trung bình độ lỗi ở mỗi thời điểm trước đó.
  • D: đạo hàm độ lỗi trong một khoảng thời gian trước đó. Giá trị này có nghĩa giá trị điều chỉnh sẽ phần nào đó đoán được xu hướng của động cơ mà điều chỉnh cho hợp lý.

img_02

Vậy để thuật toán có thể hoạt động, bạn cần các giá trị:

  • Giá trị lý tưởng (giá trị mốc). Ta dựa vào giá trị này để tính độ lỗi.
  • Cần đo được giá trị thực tế ở mỗi thời điểm.
  • Kp, Ki, Kd.

Mã nguồn ví dụ

Tôi sử dụng MATLAB để code và vẽ biểu đồ để dễ hình dung. Vì không thể lấy giá trị thực tế, tôi random giá trị để sử dụng.

Nói sơ qua về đoạn code bên dưới, tôi random giá trị ngẫu nhiên từ 150 đến 200 và coi nó như là số vòng đo được trong 1 giây. Sau đó tính độ lỗi dựa vào kết quả đo được, giá trị pivot (200), độ lỗi trong quá khứ. Có kết quả độ lỗi, tôi quy độ lỗi về giá trị pwm, từ đó tính được pwm cần truyền vào cho động cơ.

Kp = 0.6;
Ki = 0.2;
Kd = 0.2;
Pivot = 200;  // pivot value (round/s)
sum_e = 0;
N = 100;       // amount of random numbers

X = zeros(1, N);  // create array has size N to contain random values. (round/s)
E = zeros(1, N);  // create array has size N to contain error values. (round/s)
PWM = ones(1, N) * 200; // create array has N element, the value of each element is 200. (pwm)
idx = zeros(1, N);
xPrev = 200;  // to save the previous value. (round/s)

for i = 1:1:N
    X(i) = rand(1) * 100 + 150; // random from 150 -> 250
    e = Pivot - X(i);    // calculate the error value.
    sum_e = sum_e + e;

    P = Kp * e;
    I = Ki * (sum_e / i);
    D = Kd * (X(i) - xPrev);

    E(i) = (P + I + D)/ (Kp + Ki + Kd);  // OUTPUT OF THE PID ALGORITHM.
    PWM(i) = PWM(i) - E(i);    // calculate pwm to control. You need to convert E(i) (round/s) to pwm. Ex: 100round/s ~ 50pwm. 

    xPrev = X(i);
   idx(i) = i;
end

plot(idx, X, idx, PWM, idx, E);  // plot the chart.

img_03

Bài viết ở mức độ cơ bản, hi vọng độc giả có những góp ý bổ sung để bài viết tốt hơn.