Đng cơ

Đng cơ

Cách FTCLib quản lý động cơ, encoder và chế độ điều khiển tốc độ.

Cách FTCLib quản lý động cơ, encoder và chế độ điều khiển tốc độ.

Level

Intermediate

Source

Source

Author

Author

FTC Lib

FTC Lib

Translator

Translator

FTC26749 aDudu

FTC26749 aDudu

Date Published

Date Published

Jan 18, 2026

Jan 18, 2026

package com.arcrobotics.ftclib.hardware.motors
package com.arcrobotics.ftclib.hardware.motors

FTCLib cung cấp các wrapper động cơ đầy đủ tính năng nhằm giúp người dùng dễ sử dụng hơn. Ẩn phía sau, thư viện này tận dụng các tính năng nâng cao của FTCLib để tạo ra một triển khai mạnh mẽ hơn cho các đối tượng DcMotor được cung cấp trong SDK.
Tương tự, FTCLib có các đối tượng MotorMotorEx, mỗi đối tượng cho phép người dùng truy cập trực tiếp instance từ hardware map trong trường hợp muốn làm việc trực tiếp với nó.

Tạo một đối tượng Motor (Creating a Motor Object)

Việc tạo một motor đơn giản chỉ là truyền vào hardware map, tên của thiết bị trong cấu hình robot controller, và một tham số thứ ba tùy chọn là loại motor GoBILDA. Điều này là cần thiết vì các motor goBILDA trong cấu hình không chỉ rõ các giá trị RPM tối đa (rotations per minute)CPR (counts per revolution) khác nhau.

Ngoài ra còn có tùy chọn sử dụng giá trị CPRRPM tùy chỉnh.

Motor m_motor_1 = new Motor(hardwareMap, "motorOne");
Motor m_motor_2 = new Motor(hardwareMap, "motorTwo", GoBILDA.RPM_312);
Motor m_motor_3 = new Motor(hardwareMap, "motorThree", CPR, RPM);
// lấy đối tượng DcMotor bên trong
DcMotor motorOne = m_motor_1.motor;
Motor m_motor_1 = new Motor(hardwareMap, "motorOne");
Motor m_motor_2 = new Motor(hardwareMap, "motorTwo", GoBILDA.RPM_312);
Motor m_motor_3 = new Motor(hardwareMap, "motorThree", CPR, RPM);
// lấy đối tượng DcMotor bên trong
DcMotor motorOne = m_motor_1.motor;

Sử dụng RunMode (Using a RunMode)

RunMode là phương thức vận hành motor khi được cấp nguồn. Có ba chế độ: VelocityControl, PositionControl, và RawPower.

// trong Motor.java
/**
 * RunMode của motor.
 */
public enum RunMode {
    VelocityControl, PositionControl, RawPower
}
// trong Motor.java
/**
 * RunMode của motor.
 */
public enum RunMode {
    VelocityControl, PositionControl, RawPower
}

RawPower đặt công suất motor trực tiếp thông qua một giá trị trong khoảng

[−1,1][-1, 1][−1,1]

trong đó giá trị biểu thị phần trăm tốc độ tối đa của motor. Đây cũng là điều khiển vòng hở (open loop control), nghĩa là không có điều khiển phản hồi. Đây là chế độ mặc định của motor.

// đặt run mode
m_motor.setRunMode(Motor.RunMode.RawPower);
// đặt công suất đầu ra tỷ lệ của motor
m_motor.set(0.37);    // 37% tốc độ tối đa theo hướng hiện tại
// đặt run mode
m_motor.setRunMode(Motor.RunMode.RawPower);
// đặt công suất đầu ra tỷ lệ của motor
m_motor.set(0.37);    // 37% tốc độ tối đa theo hướng hiện tại

Position control cho motor chạy tới một vị trí mong muốn dựa trên tốc độ đầu vào và khoảng cách giữa vị trí hiện tại của motor và vị trí mục tiêu (tính theo tick). Chế độ này sử dụng một bộ điều khiển P với hệ số có thể thay đổi bằng phương thức setPositionCoefficient(double). Đây là một giá trị cần được tinh chỉnh. Để tinh chỉnh, hiện tại chúng tôi khuyến nghị sử dụng FTC Dashboard.

// đặt run mode
m_motor.setRunMode(Motor.RunMode.PositionControl);
// đặt và lấy hệ số position
m_motor.setPositionCoefficient(0.05);
double kP = m_motor.getPositionCoefficient();
// đặt vị trí mục tiêu
m_motor.setTargetPosition(1200);      // một số nguyên biểu diễn
                                      // số tick mong muốn
m_motor.set(0);
// đặt dung sai
m_motor.setPositionTolerance(13.6);   // sai số tối đa cho phép
// thực hiện vòng lặp điều khiển
while (!m_motor.atTargetPosition()) {
  m_motor.set(0.75);
}
m_motor.stopMotor(); // dừng motor
/* KHOẢNG CÁCH MỤC TIÊU THAY THẾ */
// cấu hình distance per pulse,
// là khoảng cách di chuyển trong một tick
// dpp = quãng đường di chuyển trong một vòng quay / CPR
m_motor.setDistancePerPulse(0.015);
// đặt mục tiêu
m_motor.setTargetDistance(18.0);
// phương thức này phải được gọi trong vòng lặp điều khiển
m_motor.set(0.5); // mode phải là PositionControl
// đặt run mode
m_motor.setRunMode(Motor.RunMode.PositionControl);
// đặt và lấy hệ số position
m_motor.setPositionCoefficient(0.05);
double kP = m_motor.getPositionCoefficient();
// đặt vị trí mục tiêu
m_motor.setTargetPosition(1200);      // một số nguyên biểu diễn
                                      // số tick mong muốn
m_motor.set(0);
// đặt dung sai
m_motor.setPositionTolerance(13.6);   // sai số tối đa cho phép
// thực hiện vòng lặp điều khiển
while (!m_motor.atTargetPosition()) {
  m_motor.set(0.75);
}
m_motor.stopMotor(); // dừng motor
/* KHOẢNG CÁCH MỤC TIÊU THAY THẾ */
// cấu hình distance per pulse,
// là khoảng cách di chuyển trong một tick
// dpp = quãng đường di chuyển trong một vòng quay / CPR
m_motor.setDistancePerPulse(0.015);
// đặt mục tiêu
m_motor.setTargetDistance(18.0);
// phương thức này phải được gọi trong vòng lặp điều khiển
m_motor.set(0.5); // mode phải là PositionControl

Velocity control cho motor chạy theo vận tốc (tính bằng tick trên giây), sử dụng cả bộ điều khiển phản hồi (feedback) và feedforward thay vì chỉ đặt tốc độ theo phần trăm của tốc độ tối đa. Điều này có thể mang lại điều khiển mượt mà hơn cho motor và được khuyến nghị mạnh mẽ cho các chương trình autonomous.

// đặt run mode
m_motor.setRunMode(Motor.RunMode.VelocityControl);
// đặt và lấy các hệ số
m_motor.setVeloCoefficients(0.05, 0.01, 0.31);
double[] coeffs = m_motor.getVeloCoefficients();
double kP = coeffs[0];
double kI = coeffs[1];
double kD = coeffs[2];
// đặt và lấy các hệ số feedforward
m_motor.setFeedforwardCoefficients(0.92, 0.47);
double[] ffCoeffs = m_motor.getFeedforwardCoefficients();
double kS = ffCoeffs[0];
double kV = ffCoeffs[1];
m_motor.setFeedforwardCoefficients(0.92, 0.47, 0.3);
ffCoeffs = m_motor.getFeedforwardCoefficients();
kA = ffCoeffs[2];
// đặt đầu ra của motor
// phương thức này phải được gọi trong vòng lặp điều khiển
m_motor.set(-0.54);
// đặt run mode
m_motor.setRunMode(Motor.RunMode.VelocityControl);
// đặt và lấy các hệ số
m_motor.setVeloCoefficients(0.05, 0.01, 0.31);
double[] coeffs = m_motor.getVeloCoefficients();
double kP = coeffs[0];
double kI = coeffs[1];
double kD = coeffs[2];
// đặt và lấy các hệ số feedforward
m_motor.setFeedforwardCoefficients(0.92, 0.47);
double[] ffCoeffs = m_motor.getFeedforwardCoefficients();
double kS = ffCoeffs[0];
double kV = ffCoeffs[1];
m_motor.setFeedforwardCoefficients(0.92, 0.47, 0.3);
ffCoeffs = m_motor.getFeedforwardCoefficients();
kA = ffCoeffs[2];
// đặt đầu ra của motor
// phương thức này phải được gọi trong vòng lặp điều khiển
m_motor.set(-0.54);

Thiết lập hành vi (Setting Behaviors)

FTCLib, giống như SDK, có các phương thức wrapper để thiết lập ZeroPowerBehavior và hướng quay của motor. ZeroPowerBehavior thường được dùng cho các cơ cấu khác ngoài drivetrain; ví dụ như cách bạn sử dụng chế độ BRAKE cho một cơ cấu nâng (lift).

// đặt hệ số đảo chiều
m_motor.setInverted(true);
// lấy hệ số đảo chiều
boolean isInverted = m_motor.getInverted();
// đặt zero power behavior thành BRAKE
m_motor.setZeroPowerBehavior(Motor.ZeroPowerBehavior.BRAKE);
// đặt hệ số đảo chiều
m_motor.setInverted(true);
// lấy hệ số đảo chiều
boolean isInverted = m_motor.getInverted();
// đặt zero power behavior thành BRAKE
m_motor.setZeroPowerBehavior(Motor.ZeroPowerBehavior.BRAKE);

Encoder tích hợp (The Built-In Encoder)

Nhiều motor có encoder tích hợp sẵn. FTCLib cung cấp một lớp lồng Motor.Encoder sử dụng các cơ chế nâng cao và hiệu chỉnh hiện tượng tràn vận tốc (velocity overflow). Một điểm rất hữu ích khác là việc reset encoder không yêu cầu phải dừng motor. Thư viện sẽ tính toán một offset và trừ offset đó khỏi vị trí hiện tại. Offset này được đặt bằng vị trí hiện tại của encoder mỗi khi phương thức reset() được gọi.
Đối tượng Motor cũng có các phương thức thao tác với encoder, vì vậy bạn không cần phải lấy instance encoder bên trong.

Bạn cũng có thể sử dụng encoder tích hợp như một encoder độc lập khi dùng encoder ngoài.

// reset encoder
m_motor.resetEncoder();
// vị trí hiện tại của motor
int pos = m_motor.getCurrentPosition();
// lấy vận tốc hiện tại
double velocity = m_motor.getVelocity(); // chỉ cho MotorEx
double corrected = m_motor.getCorrectedVelocity();
// lấy instance encoder
Motor.Encoder encoder = m_motor.encoder;
// lấy số vòng quay
double revolutions = encoder.getRevolutions();
// đặt distance per pulse là 18 mm / tick
encoder.setDistancePerPulse(18.0);
m_motor.setDistancePerPulse(18.0); // cũng là một lựa chọn
// lấy quãng đường đã di chuyển
double distance = encoder.getDistance();
distance = m_motor.getDistance(); // cũng là một lựa chọn
/** TÍNH NĂNG HỮU ÍCH **/
// bạn có thể gán encoder của motor này
// bằng encoder của một motor khác
m_motor.encoder = other_motor.encoder;
// đôi khi encoder cần được reset hoàn toàn
// thông qua phần cứng
m_motor.stopAndResetEncoder();
// reset encoder
m_motor.resetEncoder();
// vị trí hiện tại của motor
int pos = m_motor.getCurrentPosition();
// lấy vận tốc hiện tại
double velocity = m_motor.getVelocity(); // chỉ cho MotorEx
double corrected = m_motor.getCorrectedVelocity();
// lấy instance encoder
Motor.Encoder encoder = m_motor.encoder;
// lấy số vòng quay
double revolutions = encoder.getRevolutions();
// đặt distance per pulse là 18 mm / tick
encoder.setDistancePerPulse(18.0);
m_motor.setDistancePerPulse(18.0); // cũng là một lựa chọn
// lấy quãng đường đã di chuyển
double distance = encoder.getDistance();
distance = m_motor.getDistance(); // cũng là một lựa chọn
/** TÍNH NĂNG HỮU ÍCH **/
// bạn có thể gán encoder của motor này
// bằng encoder của một motor khác
m_motor.encoder = other_motor.encoder;
// đôi khi encoder cần được reset hoàn toàn
// thông qua phần cứng
m_motor.stopAndResetEncoder();

Đối tượng MotorEx (The MotorEx Object)

MotorEx là một triển khai của lớp Motor với khả năng điều khiển vận tốc được tích hợp tốt hơn. Không giống như đối tượng Motor, nó sử dụng vận tốc đã được hiệu chỉnh (corrected velocity) theo mặc định thay vì vận tốc thô do SDK ước lượng từ encoder. Nó cũng sử dụng đối tượng DcMotorEx thay cho DcMotor. Gọi getVelocity() sẽ trả về vận tốc.

Bạn cũng có thể đặt vận tốc trực tiếp bằng setVelocity(). Bạn có thể truyền vào tốc độ góc và đơn vị góc (tùy chọn). Nếu chỉ truyền tốc độ góc, vận tốc sẽ được đặt theo đơn vị tick trên giây. Nếu truyền thêm đơn vị góc, vận tốc sẽ được đặt theo đơn vị trên giây tương ứng với đơn vị được truyền vào.

Bulk Reading

Bulk read đọc toàn bộ dữ liệu cảm biến (ngoại trừ I2C) trên một module Lynx để tiết kiệm thời gian chu kỳ. Bulk read được giới thiệu trong SDK phiên bản 5.4. Vì FTCLib sử dụng các wrapper, chúng ta có thể xử lý chúng giống như các cảm biến khác.

Dưới đây là một ví dụ triển khai auto-caching.

// lấy danh sách các hub
List<LynxModule> hubs = hardwareMap.getAll(LynxModule.class);
MotorEx m1 = new MotorEx(hardwareMap, "one");
MotorEx m2 = new MotorEx(hardwareMap, "two");
for (LynxModule hub : hubs) {
     hub.setBulkCachingMode(LynxModule.BulkCachingMode.AUTO);
}
// vòng lặp điều khiển
int cycles = 0;
while (cycles++ < 500) {
    double v1 = m1.getVelocity();
    double v2 = m2.getVelocity();
    /* triển khai */
}
// lấy danh sách các hub
List<LynxModule> hubs = hardwareMap.getAll(LynxModule.class);
MotorEx m1 = new MotorEx(hardwareMap, "one");
MotorEx m2 = new MotorEx(hardwareMap, "two");
for (LynxModule hub : hubs) {
     hub.setBulkCachingMode(LynxModule.BulkCachingMode.AUTO);
}
// vòng lặp điều khiển
int cycles = 0;
while (cycles++ < 500) {
    double v1 = m1.getVelocity();
    double v2 = m2.getVelocity();
    /* triển khai */
}

Bạn cũng có thể xem ví dụ này trong SDK.

CRServo

Lớp CRServo chỉ là một đối tượng motor được thiết kế để sử dụng cho servo quay liên tục (continuous rotation servo). Mục đích chung của nó là dùng trong các lớp FTCLib yêu cầu đầu vào là Motor. Nó hoạt động giống như một motor thông thường, không bao gồm các chức năng liên quan đến encoder.

MotorGroup

Đối tượng MotorGroup nhận nhiều motor và vận hành chúng song song như một motor duy nhất. Motor group có một leader và một tập các follower. Với mọi group, bắt buộc phải có một leader, còn số lượng follower có thể bằng 0. Điều này giúp việc tạo các profile điều khiển khác nhau trở nên đơn giản hơn. Constructor của MotorGroup như sau:

MotorGroup myMotors = new MotorGroup(leader, follower1, follower2, ...);
MotorGroup myMotors = new MotorGroup(leader, follower1, follower2, ...);

Số lượng follower là biến đổi. Các phương thức khác của MotorGroup giống với các phương thức trong Motor. Bạn có thể xử lý một đối tượng MotorGroup giống hệt như một đối tượng Motor đơn lẻ. Ví dụ flywheel trong thư mục examples cho thấy một số phương thức khác mà bạn có thể sử dụng với MotorGroup.

ADUDU

A proud team of passionate Robotics Enthusiasts competing in nation-wide Technology competitions in Vietnam, the FIRST Tech Challenge and the FIRST Robotics Competition.

Copyright ©

, all rights reserved

Made by aDudu's Programming Department

made by aDudu

made by aDudu

Động cơ