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();
}
