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
Thông số Bộ PID
Quản lý Log Dữ liệu
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
Chú thích các khâu P – I – D
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.
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).
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.
ĐẠ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) | Setpoint | Thực tế | Sai số | PWM (%) |
|---|---|---|---|---|
| Đang chờ dữ liệu log... | ||||
#includeconst 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); } }