Недавно я провел некоторую работу над прошивкой моего квадрокоптера. Модель стабилизирует свое отношение относительно хорошо сейчас. Однако я заметил, что он иногда меняет свою высоту (может быть, изменение давления, ветер или турбулентность). Теперь я хочу избавиться от этих перепадов высоты и не нашел много литературы. Мой подход использует акселерометр:
- Рассчитывает текущую g-силу оси Z
- если сила перегрузки> 0,25 г и дольше 25 мс, я подаю термин акселерометр (см на с²) в пид
- выход отправляется на моторы
Модель теперь реагирует, когда она падает, с повышением мощности двигателей. Тем не менее, я не уверен, разумно ли подавать текущее ускорение в регулятор, и я в настоящее время задаюсь вопросом, существует ли более разумный метод для борьбы с внезапными и меньшими изменениями высоты.
Текущий код:
# 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();
}