J'ai récemment passé un peu de travail sur mon firmware quadcopter. Le modèle stabilise relativement bien son attitude maintenant. Cependant, j'ai remarqué qu'il change parfois d'altitude (peut-être des changements de pression, du vent ou des turbulences). Maintenant, je veux me débarrasser de ces chutes d'altitude et je n'ai pas trouvé beaucoup de littérature. Mon approche utilise l'accéléromètre:
- Calcule la force g actuelle de l'axe z
- si la force g est> 0,25 g et supérieure à 25 ms, alors j'introduis le terme accéléromètre (cm par s²) dans le pid
- la sortie est envoyée aux moteurs
Le modèle réagit maintenant lorsqu'il tombe avec une régulation à la hausse des moteurs. Cependant, je ne sais pas s'il est judicieux d'introduire l'accélération actuelle dans le régulateur et je me demande actuellement s'il existe une méthode plus intelligente pour faire face aux changements soudains et moins importants d'altitude.
Code actuel:
# 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();
}