Xe 2 bánh tự cân bằng (P2)



Chào mọi người, lại là mình đây.

Nếu đây là lần đầu bạn đến với blog của mình thì hãy theo dõi P1 của bài viết "Xe 2 bánh tự cân bằng" ở đây nhé: Xe 2 bánh tự cân bằng (P1)

Hôm nay chúng ta sẽ tìm hiểu về chương trình điều khiển xe 2 bánh tự cân bằng. Như mình đã đề cập ở phần trước, để xe 2 bánh có thể tự cân bằng yêu cầu chúng ta phải điều khiển động cơ chống lại sự ngã của xe. Để làm được điều này, chúng ta cần chương trình cho vi điều khiển và các thư viện liên quan, mình để ở phía dưới, các bạn tải về nhé.


Sau khi tải các chương trình về, chúng ta mở file .ino trong Arduino IDE.



Chương trình đã bao gồm gói thư viện đính kèm, các bạn chỉ cần nạp file .ino vào vi điều khiển Arduino nano (không di chuyển vị trí file .ino), hoặc các bạn cũng có thể thêm các thư viện thủ công.

Chúng ta sẽ quan tâm những khai báo sau đây:

#define MIN_ABS_SPEED 20: Tốc độ tối thiểu của các motor, có thể hiểu là đối với điều khiển 8 bit (từ 0 đến 255) thì tốc độ motor được cài đặt để không nhỏ hơn 20. Chúng ta có thể thấy rõ việc giới hạn tốc độ này tại hàm LMotorController::move() trong thư viện LMotorController.cpp như sau:

void LMotorController::move()
{
    if (rightSpeed < 0)
    {
        rightSpeed = min(rightSpeed, -1*minAbsSpeed);
        rightSpeed = max(rightSpeed, -255);
    }
    else if (rightSpeed > 0)
    {
        rightSpeed = max(rightSpeed, minAbsSpeed);
        rightSpeed = min(rightSpeed, 255);
    }
}

Để theo dõi các chương trình phía sau các thư viện, mình đề xuất các bạn sử dụng Notepad++, đây là một chương trình soạn thảo ngôn ngữ lập trình đa dụng. Các bạn có thể tải xuống và cài đặt tại: Đây

double originalSetpoint = 180: Khai báo điểm ổn định (Setpoint), xe đạt được trạng thái cân bằng. Setpoint này sẽ được đưa vào hàm PID để làm giá trị bám. Xung động cơ phát ra sau bộ điều khiển PID sẽ được điều chỉnh để giữ xe ổn định xung quanh góc 180.


double motorSpeedFactorLeft = 0.24: Hệ số xung động cơ bên trái, giá trị nhận từ 0 đến 1

int Kp, Ki, Kd: Khai báo các giá trị của bộ điều khiển PID

Với các giá trị khai báo, các bạn có thể để mặc định như khai báo của mình. Tuy nhiên, có thể các bạn cần phải điều chỉnh các thông số PID trong khoảng thay đổi nhỏ để phù hợp với hệ thống của các bạn. Các thông số PID sẽ được khai báo tại chương trình .ino. Sau đó, các giá trị này được trỏ đến chương trình PID_v1.cpp thông qua lệnh PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT) để thực hiện tính toán tại đây. Chúng ta có thể thấy rõ việc trỏ các biến khai báo giá trị Kp, Ki, Kd trong hàm PID::PID() như sau:

PID::PID(double* Input, double* Output, double* Setpoint,
        double Kp, double Ki, double Kd, int ControllerDirection)
{
    PID::SetOutputLimits(0, 255);
    SampleTime = 100;		
    PID::SetControllerDirection(ControllerDirection);
    PID::SetTunings(Kp, Ki, Kd);
    lastTime = millis()-SampleTime;	
    inAuto = false;
    myOutput = Output;
    myInput = Input;
    mySetpoint = Setpoint;		
}

Trong đó, PID::SetOutputLimits(0, 255) mang chức năng giới hạn xung ra của hàm PID không vượt quá giá trị 255 (8 bit). SampleTime = 100 là thời gian lấy mẫu của vi điều khiển khi điều khiển rời rạc.  Ở bài viết sau, chúng ta sẽ cùng tìm hiểu nhiều hơn về giải thuật PID, cách để tính toán các giá trị PID cho hệ thống và đưa các giá trị đó vào vi điều khiển để thực hiện điều khiển. Chúc mọi người ngủ ngon.