Gần đây tôi đã dành một số công việc cho phần mềm quad quad của tôi. Mô hình đang ổn định thái độ của nó tương đối tốt bây giờ. Tuy nhiên tôi nhận thấy rằng đôi khi nó đang thay đổi độ cao (có thể thay đổi áp suất, gió hoặc nhiễu loạn). Bây giờ tôi muốn thoát khỏi những giọt nước cao độ và không tìm thấy nhiều tài liệu. Cách tiếp cận của tôi là sử dụng gia tốc kế:
- Tính lực g hiện tại của trục z
- nếu lực g> 0,25 g và dài hơn 25 ms, thì tôi nạp thuật ngữ gia tốc (cm trên s²) vào pid
- đầu ra được gửi đến động cơ
Mô hình bây giờ phản ứng khi nó rơi xuống với sự điều chỉnh tăng của động cơ. Tuy nhiên, tôi không chắc chắn, liệu có thông minh khi đưa gia tốc hiện tại vào bộ điều chỉnh hay không và tôi hiện đang tự hỏi, liệu có một phương pháp thông minh hơn để đối phó với những thay đổi đột ngột và nhỏ hơn về độ cao.
Mã hiện tại:
# define HLD_ALTITUDE_ZGBIAS 0.25f
# define HLD_ALTITUDE_ZTBIAS 25
const float fScaleF_g2cmss = 100.f * INERT_G_CONST;
int_fast16_t iAccZOutput = 0; // Accelerometer
// Calc current g-force
bool bOK_G;
float fAccel_g = Device::get_accel_z_g(m_pHalBoard, bOK_G); // Get the acceleration in g
// Small & fast stabilization using the accelerometer
static short iLAccSign = 0;
if(fabs(fAccel_g) >= HLD_ALTITUDE_ZGBIAS) {
if(iLAccSign == 0) {
iLAccSign = sign_f(fAccel_g);
}
// The g-force must act for a minimum time interval before the PID can be used
uint_fast32_t iAccZTime = m_pHalBoard->m_pHAL->scheduler->millis() - m_iAccZTimer;
if(iAccZTime < HLD_ALTITUDE_ZTBIAS) {
return;
}
// Check whether the direction of acceleration changed suddenly
// If so: reset the timer
short iCAccSign = sign_f(fAccel_g);
if(iCAccSign != iLAccSign) {
// Reset the switch if acceleration becomes normal again
m_iAccZTimer = m_pHalBoard->m_pHAL->scheduler->millis();
// Reset the PID integrator
m_pHalBoard->get_pid(PID_ACC_RATE).reset_I();
// Save last sign
iLAccSign = iCAccSign;
return;
}
// Feed the current acceleration into the PID regulator
float fAccZ_cmss = sign_f(fAccel_g) * (fabs(fAccel_g) - HLD_ALTITUDE_ZGBIAS) * fScaleF_g2cmss;
iAccZOutput = static_cast<int_fast16_t>(constrain_float(m_pHalBoard->get_pid(PID_ACC_RATE).get_pid(-fAccZ_cmss, 1), -250, 250) );
} else {
// Reset the switch if acceleration becomes normal again
m_iAccZTimer = m_pHalBoard->m_pHAL->scheduler->millis();
// Reset the PID integrator
m_pHalBoard->get_pid(PID_ACC_RATE).reset_I();
}