⚙️ Mô phỏng PID Động cơ & Code Arduino

Trải nghiệm trực quan thuật toán PID, theo dõi log thời gian thực.

Thiết lập Vận hành

Tốc độ mong muốn (Setpoint)100 RPM
Tải nhiễu (Disturbance)0 %

Thông số Bộ PID

Kp (Tỷ lệ)2.0
Ki (Tích phân)0.50
Kd (Đạo hàm)0.10

Quản lý Log Dữ liệu

Ghi log thời gian thực và tải về dạng CSV.
Tổng bản ghi: 0
Mô phỏng Động cơ
0.0 RPM
PWM điều khiển: 0%

Công thức tính toán rời rạc

1. Sai số: e(t) = Setpoint − Actual

2. Khâu P: P = Kp × e(t)

3. Khâu I: I = Ki × Σ(e(t) × dt)

4. Khâu D: D = Kd × (e(t) − e(t−1)) / dt

PWM = P + I + D (giới hạn 0% – 100%)
Đồ thị phản hồi thời gian thực SetpointThực tế
Đánh giá chất lượng điều khiển Thời gian đo: 0.0s  ĐANG ĐO…
Tự động đo lại mỗi khi bạn đổi Setpoint, Tải nhiễu hoặc bấm Đặt lại. Kết luận sau 8 giây.
Tiêu chíYêu cầu đạtKết quả
Vọt lố (Overshoot)≤ 10%…·
Thời gian lên (đạt 90%)≤ 2 s…·
Thời gian xác lập (±5%)≤ 5 s…·
Sai số tĩnh≤ 3%…·

Chú thích các khâu P – I – D

P – Tỷ lệ (Kp): phản ứng theo sai số hiện tại

Sai số càng lớn thì lực điều khiển càng mạnh. Quyết định tốc độ phản ứng.

Quá thấp: động cơ chậm, đồ thị bò lên từ từ, còn sai số khi đã ổn định.

Quá cao: vọt lố mạnh, đồ thị dao động qua lại quanh Setpoint.

I – Tích phân (Ki): cộng dồn sai số trong quá khứ

Triệt tiêu sai số tĩnh, giúp tốc độ về đúng Setpoint, nhất là khi có tải nhiễu.

Quá thấp: tốc độ dừng lại hơi lệch Setpoint, về đích rất chậm.

Quá cao: vọt lố, dao động chậm và kéo dài (hiện tượng windup).

D – Đạo hàm (Kd): dự đoán xu hướng thay đổi

Phanh bớt khi sai số giảm nhanh, giúp giảm vọt lố và làm đồ thị mượt hơn.

Quá thấp: vọt lố và dao động không được dập tắt.

Quá cao: nhạy với nhiễu, PWM giật liên tục, động cơ rung.

Thế nào là một bộ PID tốt?

ĐẠT: lên nhanh, vọt lố nhỏ, về đúng Setpoint và đứng yên, PWM ổn định không giật.

KHÔNG ĐẠT: chậm, vọt lố lớn, dao động mãi không tắt, hoặc dừng lệch Setpoint.

Gợi ý chỉnh: tăng Kp để nhanh hơn, tăng Ki để hết lệch, tăng Kd để bớt vọt lố. Mỗi lần chỉ đổi một thông số.

Bảng log hoạt động trực tiếp

Thời gian (s)SetpointThực tếSai sốPWM (%)
Đang chờ dữ liệu log...
Mã nguồn Arduino điều khiển động cơ thực tế
Dùng cho Arduino Uno/Nano, encoder đo tốc độ và PWM điều khiển driver động cơ DC (cần thư viện Encoder).
#include 

const int encoderPinA = 2;
const int encoderPinB = 3;
const int pwmPin = 9;   // PWM ra driver (L298N / BTS7960...)

Encoder myEnc(encoderPinA, encoderPinB);

double Setpoint = 100.0; // RPM mong muốn
double Input = 0.0;      // RPM thực tế
double Output = 0.0;     // PWM 0 - 255

double Kp = 2.0, Ki = 0.5, Kd = 0.1;

unsigned long lastTime = 0;
double errSum = 0, lastErr = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pwmPin, OUTPUT);
}

void loop() {
  unsigned long now = millis();
  double timeChange = (double)(now - lastTime); // ms

  if (timeChange >= 50) {
    // 1. Đọc xung encoder -> RPM (giả sử 500 xung/vòng)
    long count = myEnc.read();
    myEnc.write(0);
    Input = (count / 500.0) * (60000.0 / timeChange);

    // 2. Sai số, tích phân (đơn vị giây) và chống bão hòa
    double dt = timeChange / 1000.0;
    double error = Setpoint - Input;
    errSum += error * dt;
    errSum = constrain(errSum, -255, 255);
    double dErr = (error - lastErr) / dt;

    // 3. PID
    double out = (Kp * error) + (Ki * errSum) + (Kd * dErr);

    // 4. Xuất PWM
    Output = constrain(out, 0, 255);
    analogWrite(pwmPin, (int)Output);

    lastErr = error;
    lastTime = now;

    Serial.print("Setpoint: "); Serial.print(Setpoint);
    Serial.print("\tRPM: ");    Serial.print(Input);
    Serial.print("\tPWM: ");    Serial.println(Output);
  }
}
💡 Hướng dẫn trải nghiệm
  • Setpoint & Nhiễu: thay đổi tốc độ hoặc kéo thanh nhiễu để xem PID ứng phó.
  • Bảng log: dữ liệu được đẩy trực tiếp theo thời gian thực, có thể tải CSV.
  • Code Arduino: bấm "Xem Code Arduino" để lấy mã cho phần cứng thật.