

其实串级PID都是一样的(也有人用并级的),主要还是姿态要解的好,不然啥控制都没用的。
下面是代码:
/****************主函数运行*************************************/
if(++ tmrBase1ms >= 4){
tmrBase1ms = 0;
commanderGetRPY(&eulerRollDesired, &eulerPitchDesired, &eulerYawDesired);
IMUupdate(&ANGL.X, &ANGL.Y, &ANGL.Z,
GYRO.X, GYRO.Y, GYRO.Z, ACCEL.X, ACCEL.Y, ACCEL.Z);
Kalman_Filter(ANGL.X, ANGL.Y, ANGL.Z,
GYRO.X, GYRO.Y, GYRO.Z,
&eulerRollActual, &eulerPitchActual, &eulerYawActual);
#if 0
controllerCorrectAttitudePID(eulerRollActual, eulerPitchActual, eulerYawActual,
eulerRollDesired, eulerPitchDesired, eulerYawDesired,
&ANGL_out.X, &ANGL_out.Y, &ANGL_out.Z);
#endif
//#if 0
controllerCorrectAttitudePID(eulerRollActual, eulerPitchActual, eulerYawActual,
eulerRollDesired, eulerPitchDesired, eulerYawDesired,
&rollRateDesired, &pitchRateDesired, &yawRateDesired);
controllerCorrectRatePID(GYRO.X, GYRO.Y, GYRO.Z,
rollRateDesired, pitchRateDesired, yawRateDesired,
&ANGL_out.X, &ANGL_out.Y, &ANGL_out.Z);
//#endif
distributePower(thrust, ANGL_out.X, ANGL_out.Y, ANGL_out.Z,
&motorPowerLeft, &motorPowerRight, &motorPowerFront, &motorPowerRear);
}
/*************子函数*********************/
void controllerCorrectRatePID(
float rollRateActual, float pitchRateActual, float yawRateActual,
float rollRateDesired, float pitchRateDesired, float yawRateDesired,
float* rollOut, float* pitchOut, float* yawOut)
{
#ifdef PidRateAdd
pidSetDesired(&pidRollRate, rollRateDesired);
TRUNCATE_SINT16(rollOutput, pidUpdate(&pidRollRate, rollRateActual, TRUE));
pidSetDesired(&pidPitchRate, pitchRateDesired);
TRUNCATE_SINT16(pitchOutput, pidUpdate(&pidPitchRate, pitchRateActual, TRUE));
pidSetDesired(&pidYawRate, yawRateDesired);
TRUNCATE_SINT16(yawOutput, pidUpdate(&pidYawRate, yawRateActual, TRUE));
*rollOut = rollOutput;
*pitchOut = pitchOutput;
*yawOut = yawOutput;
#else
TRUNCATE_SINT16(rollOutput, rollRateDesired);
TRUNCATE_SINT16(pitchOutput, pitchRateDesired);
TRUNCATE_SINT16(yawOutput, yawRateDesired);
*rollOut = rollOutput;
*pitchOut = pitchOutput;
*yawOut = yawOutput;
#endif
}
void controllerCorrectAttitudePID(
float eulerRollActual, float eulerPitchActual, float eulerYawActual,
float eulerRollDesired, float eulerPitchDesired, float eulerYawDesired,
float* rollRateDesired, float* pitchRateDesired, float* yawRateDesired)
{
float yawError;
pidSetDesired(&pidRoll, eulerRollDesired);
*rollRateDesired = pidUpdate(&pidRoll, eulerRollActual, TRUE);
// Update PID for pitch axis
pidSetDesired(&pidPitch, eulerPitchDesired);
*pitchRateDesired = pidUpdate(&pidPitch, eulerPitchActual, TRUE);
// Update PID for yaw axis
yawError = eulerYawDesired - eulerYawActual;
if (yawError > 180.0)
yawError -= 360.0;
else if (yawError < -180.0)
yawError += 360.0;
pidSetError(&pidYaw, yawError);
*yawRateDesired = pidUpdate(&pidYaw, eulerYawActual, FALSE);
}
/***************pid函数***********************/
float pidUpdate(PidObject* pid, const float measured,
const bool updateError)
{
float output;
if (updateError)
{
pid->err = pid->desired - measured;
}
pid->integ += pid->err * IMU_UPDATE_DT;
if (pid->integ > pid->iLimit)
{
pid->integ = pid->iLimit;
}
else if (pid->integ < -pid->iLimit)
{
pid->integ = -pid->iLimit;
}
pid->deriv = (pid->err - pid->prevError) * IMU_UPDATE_FREQ;
pid->outP = pid->kp * pid->err;
pid->outI = pid->ki * pid->integ;
pid->outD = pid->kd * pid->deriv;
output = (pid->kp * pid->err) +
(pid->ki * pid->integ) +
(pid->kd * pid->deriv);
pid->prevError = pid->err;
return output;
}

回复
有奖活动 | |
---|---|
【EEPW电子工程师创研计划】技术变现通道已开启~ | |
发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
【EEPW在线】E起听工程师的声音! | |
“我踩过的那些坑”主题活动——第001期 | |
高校联络员开始招募啦!有惊喜!! | |
【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
送您一块开发板,2025年“我要开发板活动”又开始了! | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
电流检测模块MAX4080S被打赏10分 | |
【我踩过的那些坑】calloc和malloc错误使用导致跑飞问题排查被打赏50分 | |
多组DCTODC电源方案被打赏50分 | |
【我踩过的那些坑】STM32cubeMX软件的使用过程中的“坑”被打赏50分 | |
新手必看!C语言精华知识:表驱动法被打赏50分 | |
【我踩过的那些坑】杜绑线问题被打赏50分 | |
【我踩过的那些坑】STM32的硬件通讯调试过程的“坑”被打赏50分 | |
【我踩过的那些坑】晶振使用的问题被打赏100分 | |
【我踩过的那些坑】电感选型错误导致的处理器连接不上被打赏50分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏10分 |