乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      開源Flight飛控系列 | Baseflight核心函數(shù)解析

       西北望msm66g9f 2025-01-16 發(fā)布于山東
      圖片
      圖片

      本文是系列的第三部分,詳細(xì)探討了多旋翼飛行控制器中兩個核心函數(shù) pidMultiWii() 和 mixTable() 的工作原理,以及PWM寫入函數(shù) pwmWriteMotor() 的具體實現(xiàn)。pidMultiWii() 函數(shù)負(fù)責(zé)根據(jù)傳感器數(shù)據(jù)和遙控器輸入計算姿態(tài)調(diào)整值,以確保飛行器的穩(wěn)定性和響應(yīng)性。mixTable() 函數(shù)則將這些姿態(tài)調(diào)整值轉(zhuǎn)換為具體的電機功率輸出,并處理舵機控制信號,使飛行器能夠按照預(yù)期的姿態(tài)和運動進行操作。最后,pwmWriteMotor() 函數(shù)實現(xiàn)了將計算出的PWM值寫入對應(yīng)的定時器寄存器,從而控制電機的實際轉(zhuǎn)速。

      圖片

      01

      pid_controller()的解析

      pid_controller()是一個函數(shù)指針,指向pidMultiWii() ,pidMultiWii() 函數(shù)是 baseflight 飛行控制器中實現(xiàn) PID 控制邏輯的核心部分。它負(fù)責(zé)根據(jù)傳感器數(shù)據(jù)(如陀螺儀和加速度計)以及遙控器輸入,計算出每個軸(滾轉(zhuǎn)、俯仰、偏航)的姿態(tài)調(diào)整值 (axisPID)。下面是對該函數(shù)的詳細(xì)解析。

      函數(shù)結(jié)構(gòu)與變量

      static void pidMultiWii(void){    int axis, prop;    int32_t error, errorAngle;    int32_t PTerm, ITerm, PTermACC = 0, ITermACC = 0, PTermGYRO = 0, ITermGYRO = 0, DTerm;    static int16_t lastGyro[3] = { 000 };    static int32_t delta1[3], delta2[3];    int32_t deltaSum;    int32_t delta;

      axis:循環(huán)變量,用于遍歷三個軸(滾轉(zhuǎn)、俯仰、偏航)。

      prop:比例因子,基于遙控輸入的最大值來決定混合模式的比例。

      error, errorAngle:誤差值,分別表示基于角速度和角度的誤差。

      PTerm, ITerm, DTerm:PID控制中的比例、積分和微分項。

      PTermACC, ITermACC, PTermGYRO, ITermGYRO:分別為基于角度和角速度的P和I項。

      lastGyro[]:存儲上次的陀螺儀讀數(shù),用于計算角速度變化。

      delta1[], delta2[]:存儲前兩次的角速度變化量,用于計算 deltaSum。

      比例因子計算

      prop=max(abs(rcCommand[PITCH]), abs(rcCommand[ROLL])); // range [0;500]

      計算滾轉(zhuǎn)和俯仰軸遙控輸入的最大絕對值,并將其映射到范圍 [0, 500] 內(nèi)。這個值將用于后續(xù)的角度模式和地平線模式下的比例混合。

      遍歷每個軸

      for (axis = 0; axis < 3; axis++) {

      對每個軸(滾轉(zhuǎn)、俯仰、偏航)進行處理。

      角度模式或地平線模式

      if ((f.ANGLE_MODE || f.HORIZON_MODE) && axis < 2) {    errorAngle = constrain(2 * rcCommand[axis] + GPS_angle[axis], -((int)mcfg.max_angle_inclination), +mcfg.max_angle_inclination) - angle[axis] + cfg.angleTrim[axis];    PTermACC = errorAngle * cfg.P8[PIDLEVEL] / 100;    PTermACC = constrain(PTermACC, -cfg.D8[PIDLEVEL] * 5, +cfg.D8[PIDLEVEL] * 5);    errorAngleI[axis] = constrain(errorAngleI[axis] + errorAngle, -10000, +10000); // WindUp    ITermACC = (errorAngleI[axis] * cfg.I8[PIDLEVEL]) >> 12;}

      依賴于加速度傳感器

      errorAngle:計算期望角度與實際角度之間的誤差,考慮了GPS角度校正和角度修剪。

      PTermACC:基于誤差計算比例項,并限制其范圍。

      errorAngleI[] 和 ITermACC:更新并計算積分項,防止積分風(fēng)-up(即積分值過大導(dǎo)致系統(tǒng)不穩(wěn)定)。

      非角度模式或地平線模式

      if (!f.ANGLE_MODE || f.HORIZON_MODE || axis == 2) {    error = (int32_t)rcCommand[axis] * 10 * 8 / cfg.P8[axis];    error -= gyroData[axis];    PTermGYRO = rcCommand[axis];    errorGyroI[axis] = constrain(errorGyroI[axis] + error-16000, +16000); // WindUp    if ((abs(gyroData[axis]) > 640) || ((axis == YAW) && (abs(rcCommand[axis]) > 100)))        errorGyroI[axis] = 0;    ITermGYRO = (errorGyroI[axis] / 125 * cfg.I8[axis]) >> 6;}

      依賴于陀螺儀

      error:計算基于角速度的誤差。

      PTermGYRO:直接使用遙控輸入作為比例項。

      errorGyroI[] 和 ITermGYRO:更新并計算積分項,同樣防止積分風(fēng)-up。對于高角速度或大遙控輸入情況,重置積分項以避免不穩(wěn)定的積累。

      混合比例項和積分項

      if (f.HORIZON_MODE && axis < 2) {    PTerm = (PTermACC * (500 - prop) + PTermGYRO * prop) / 500;    ITerm = (ITermACC * (500 - prop) + ITermGYRO * prop) / 500;else {    if (f.ANGLE_MODE && axis < 2) {        PTerm = PTermACC;        ITerm = ITermACC;    } else {        PTerm = PTermGYRO;        ITerm = ITermGYRO;    }}

      根據(jù)當(dāng)前飛行模式(角度模式或地平線模式),按比例混合基于角度和角速度的比例項和積分項。

      計算最終的 P-term 和 D-term

      PTerm -= (int32_t)gyroData[axis] * dynP8[axis] / 10 / 8;delta = gyroData[axis] - lastGyro[axis];lastGyro[axis] = gyroData[axis];deltaSum = delta1[axis] + delta2[axis] + delta;delta2[axis] = delta1[axis];delta1[axis] = delta;DTerm = (deltaSum * dynD8[axis]) / 32;axisPID[axis] = PTerm + ITerm - DTerm;

      PTerm:進一步調(diào)整比例項,考慮動態(tài)比例增益。

      delta 和 deltaSum:計算最近三次角速度變化的總和,用于生成更穩(wěn)定的微分項。

      DTerm:基于累積的角速度變化計算微分項,并通過縮放操作確保數(shù)值在合理范圍內(nèi)。

      axisPID[]:將比例、積分和微分項組合成最終的姿態(tài)調(diào)整命令。

      小結(jié)

      pidMultiWii() 函數(shù)實現(xiàn)了多旋翼飛行器的姿態(tài)控制邏輯,通過結(jié)合來自不同傳感器的數(shù)據(jù)和用戶輸入,精確計算每個軸的姿態(tài)調(diào)整值。它根據(jù)不同的飛行模式(角度模式、地平線模式)和飛行條件,靈活調(diào)整控制策略,最終為下一級處理函數(shù)提供了axisPID內(nèi)容。

      圖片

      這個函數(shù)不僅體現(xiàn)了 PID 控制算法的核心思想,還展示了如何在實際應(yīng)用中針對特定需求進行優(yōu)化和調(diào)整。例如,通過混合比例項和積分項,可以在不同飛行模式下提供更加適合的控制效果;而通過累積角速度變化(delta1[axis] + delta2[axis] + delta)來計算微分項,則有助于提高系統(tǒng)的穩(wěn)定性和抗噪能力。

      02

      mixTable()的解析

      mixTable() 函數(shù)在 baseflight飛行控制器中負(fù)責(zé)將姿態(tài)調(diào)整命令(axisPID)轉(zhuǎn)換為具體的電機功率輸出(motor[])。它還處理舵機控制信號的生成,確保飛行器按照期望的姿態(tài)和運動進行操作。下面是對該函數(shù)的詳細(xì)解析。

      函數(shù)結(jié)構(gòu)與變量

      void mixTable(void){    int16_t maxMotor;    uint32_t i;

      maxMotor:用于記錄所有電機中的最大功率值,以便進行后續(xù)的歸一化處理。

      i:循環(huán)變量,用于遍歷電機和舵機。

      防止偏航跳躍

      if (numberMotor > 3) {    axisPID[YAW] = constrain(axisPID[YAW], -100 - abs(rcCommand[YAW]), +100 + abs(rcCommand[YAW]));}

      如果電機數(shù)量大于3個,則限制 axisPID[YAW]的范圍,以防止偏航修正過程中出現(xiàn)突然的大角度變化(即“偏航跳躍”),這有助于保持飛行器的穩(wěn)定性。

      計算非伺服混合的電機功率

      if (numberMotor > 1) {    for (i = 0; i < numberMotor; i++) {        motor[i] = rcCommand[THROTTLE] * currentMixer[i].throttle +                   axisPID[PITCH] * currentMixer[i].pitch +                   axisPID[ROLL] * currentMixer[i].roll +                   -cfg.yaw_direction * axisPID[YAW] * currentMixer[i].yaw;        if (f.FIXED_WING) { // vector_thrust handling            if (cfg.fw_vector_thrust) {                if (f.PASSTHRU_MODE)                    motor[i] = rcCommand[THROTTLE] - rcCommand[YAW] * (i - 0.5f);            } else { // Override mixerVectorThrust                motor[i] = rcCommand[THROTTLE];            }        }    }}

      motor[i]:計算每個電機的功率輸出,基于油門輸入、姿態(tài)調(diào)整命令(俯仰、滾轉(zhuǎn)、偏航)以及當(dāng)前混合配置 (`currentMixer`)。

      固定翼模式:根據(jù)配置是否啟用矢量推力(fw_vector_thrust),進一步調(diào)整電機輸出。如果啟用了直通模式(PASSTHRU_MODE),則對每個電機應(yīng)用不同的偏航修正;否則,直接使用油門輸入作為電機功率。

      處理飛機或舵機混合

      switch (mcfg.mixerConfiguration) {    case MULTITYPE_CUSTOM_PLANE:    case MULTITYPE_FLYING_WING:    case MULTITYPE_AIRPLANE:    case MULTITYPE_BI:    case MULTITYPE_TRI:    case MULTITYPE_DUALCOPTER:    case MULTITYPE_SINGLECOPTER:        servoMixer();        break;    case MULTITYPE_GIMBAL:        servo[0] = (((int32_t)cfg.servoConf[0].rate * angle[PITCH]) / 50) + servoMiddle(0);        servo[1] = (((int32_t)cfg.servoConf[1].rate * angle[ROLL]) / 50) + servoMiddle(1);        break;}

      根據(jù)混合配置類型調(diào)用相應(yīng)的舵機混合函數(shù)(如 servoMixer())或直接設(shè)置舵機位置(如云臺控制)。

      相機穩(wěn)定(CamStab)

      if (feature(FEATURE_SERVO_TILT)) {    servo[0] = servoMiddle(0);    servo[1] = servoMiddle(1);    if (rcOptions[BOXCAMSTAB]) {        if (cfg.gimbal_flags & GIMBAL_MIXTILT) {            servo[0] -= (-(int32_t)cfg.servoConf[0].rate) * angle[PITCH] / 50 - (int32_t)cfg.servoConf[1].rate * angle[ROLL] / 50;            servo[1] += (-(int32_t)cfg.servoConf[0].rate) * angle[PITCH] / 50 + (int32_t)cfg.servoConf[1].rate * angle[ROLL] / 50;        } else {            servo[0] += (int32_t)cfg.servoConf[0].rate * angle[PITCH] / 50;            servo[1] += (int32_t)cfg.servoConf[1].rate * angle[ROLL]  / 50;        }    }}

      如果啟用了相機穩(wěn)定功能(FEATURE_SERVO_TILT),則根據(jù)姿態(tài)調(diào)整命令(俯仰、滾轉(zhuǎn))更新舵機位置,以實現(xiàn)相機的穩(wěn)定。

      約束舵機輸出

      for (i = 0; i < MAX_SERVOS; i++)    servo[i] = constrain(servo[i], cfg.servoConf[i].min, cfg.servoConf[i].max); // limit the values

      確保每個舵機的輸出值在其允許范圍內(nèi),避免超出極限導(dǎo)致?lián)p壞或其他問題。

      AUX通道轉(zhuǎn)發(fā)到舵機輸出

      if (cfg.gimbal_flags & GIMBAL_FORWARDAUX) {    int offset = core.numServos - 4;    for (i = 0; i < 4; i++)        pwmWriteServo(i + offset, rcData[AUX1 + i]);}

      將輔助通道(AUX1-AUX4)的數(shù)據(jù)直接轉(zhuǎn)發(fā)到指定的舵機輸出,適用于需要額外控制信號的應(yīng)用場景。

      歸一化電機輸出并約束功率

      maxMotor = motor[0];for (i = 1; i < numberMotor; i++)    if (motor[i] > maxMotor)        maxMotor = motor[i];for (i = 0; i < numberMotor; i++) {    if (maxMotor > mcfg.maxthrottle && !f.FIXED_WING) {        motor[i] -= maxMotor - mcfg.maxthrottle;    }    if (feature(FEATURE_3D)) {        if ((rcData[THROTTLE]) > mcfg.midrc) {            motor[i] = constrain(motor[i], mcfg.deadband3d_high, mcfg.maxthrottle);            if ((mcfg.mixerConfiguration) == MULTITYPE_TRI) {                servo[5] = constrain(servo[5], cfg.servoConf[5].min, cfg.servoConf[5].max);            }        } else {            motor[i] = constrain(motor[i], mcfg.mincommand, mcfg.deadband3d_low);            if ((mcfg.mixerConfiguration) == MULTITYPE_TRI) {                servo[5] = constrain(servo[5], cfg.servoConf[5].max, cfg.servoConf[5].min);            }        }    } else {        motor[i] = constrain(motor[i], mcfg.minthrottle, mcfg.maxthrottle);        if ((rcData[THROTTLE]) < mcfg.mincheck) {            if (!feature(FEATURE_MOTOR_STOP))                motor[i] = mcfg.minthrottle;            else {                motor[i] = mcfg.mincommand;                f.MOTORS_STOPPED = 1;            }        } else {            f.MOTORS_STOPPED = 0;        }    }    if (!f.ARMED) {        motor[i] = motor_disarmed[i];        f.MOTORS_STOPPED = 1;    }}

      歸一化:找到所有電機的最大功率值,并將其歸一化至最大允許值(mcfg.maxthrottle),以確保不會超過安全范圍。

      約束功率:根據(jù)不同條件(如3D飛行模式、未武裝狀態(tài)等)進一步約束電機功率,確保其在合理范圍內(nèi)工作。

      特殊處理:對于某些特定的混合配置(如三軸飛行器),還需要額外處理舵機輸出,以適應(yīng)特定的機械設(shè)計需求。

      小結(jié)

      mixTable()函數(shù)是連接姿態(tài)控制和電機驅(qū)動的關(guān)鍵環(huán)節(jié),它負(fù)責(zé)將 PID 控制器計算出的姿態(tài)調(diào)整命令轉(zhuǎn)換為具體的電機功率輸出,并處理相關(guān)的舵機控制信號。這個過程不僅考慮了基本的飛行控制需求,還涵蓋了多種特殊情況和功能擴展,如防止偏航跳躍、相機穩(wěn)定、輔助通道轉(zhuǎn)發(fā)等,確保飛行器能夠在各種條件下穩(wěn)定運行。

      圖片

      通過這種方式,mixTable() 實現(xiàn)了從姿態(tài)調(diào)整到實際物理動作的橋梁作用,保證了飛行器能夠精確響應(yīng)用戶指令和環(huán)境變化,提供了靈活且可靠的飛行體驗。

      03

      pwmWriteMotor()解析

      我們直接看主體的控制動力電機部分pwmWriteMotor()

      pwmWriteMotor()在 drv_pwm.c 文件中, 函數(shù)的具體實現(xiàn)如下。

      輸入?yún)?shù)

      void pwmWriteMotor(uint8_t index, uint16_t value){    if (index < numMotors)        pwmWritePtr(index, value);}

      uint8_t index:表示電機的索引號。它指定了要控制哪個電機。

      uint16_t value`:表示要設(shè)置的PWM值,通常是一個介于0到最大占空比之間的整數(shù)值。

      該條件確保提供的電機索引在合法范圍內(nèi)(即小于 numMotors)。如果索引超出范圍,則不會執(zhí)行任何操作,避免訪問無效的內(nèi)存地址或引起其他錯誤。

       如果索引有效,則通過 pwmWritePtr函數(shù)指針調(diào)用實際的PWM寫入函數(shù)。

      pwmWritePtr是一個函數(shù)指針,在初始化時根據(jù)配置選擇不同的PWM寫入方法。這允許代碼根據(jù)不同的硬件配置或需求靈活選擇最合適的PWM生成方式。

      pwmWritePtr的選擇

      在 pwmInit()函數(shù)中,pwmWritePtr被賦值為以下幾種可能之一:

      // determine motor writer functionpwmWritePtr = pwmWriteStandard;if (init->motorPwmRate > 500)    pwmWritePtr = pwmWriteBrushed;else if (init->syncPWM)    pwmWritePtr = pwmWriteSyncPwm;

      pwmWriteStandard:標(biāo)準(zhǔn)的PWM寫入方法,適用于大多數(shù)情況。

      pwmWriteBrushed:用于高頻率PWM(如無刷電機),當(dāng) motorPwmRate大于500Hz時使用。

      pwmWriteSyncPwm:同步PWM模式,適用于需要嚴(yán)格同步的場景。

      實際寫入函數(shù)解析

      以下是三種可能的PWM寫入函數(shù)的具體實現(xiàn):

      1. pwmWriteStandard

      static void pwmWriteStandard(uint8_t index, uint16_t value)   {       *motors[index]->ccr = value;   }

      直接將PWM值寫入對應(yīng)的定時器捕獲/比較寄存器 (CCR),以設(shè)置占空比。

      2. pwmWriteBrushed

        static void pwmWriteBrushed(uint8_t index, uint16_t value)   {       *motors[index]->ccr = (value - 1000) * motors[index]->period / 1000;   }

      對于高頻率PWM,先對輸入值進行縮放和偏移處理,然后寫入定時器捕獲/比較寄存器。

      3. pwmWriteSyncPwm

         static void pwmWriteSyncPwm(uint8_t index, uint16_t value)   {       *motors[index]->cr1 &= (uint16_t) ~(0x0001);    // disable timer       *motors[index]->cnt = 0x0000;                   // set timer counter to zero       *motors[index]->ccr = value;                    // set the pwm value       *motors[index]->cr1 |= (uint16_t) (0x0001);     // enable timer   }

      在同步PWM模式下,先禁用定時器,重置計數(shù)器,設(shè)置新的PWM值,最后重新啟用定時器。這種模式確保所有PWM信號同步更新。

      小結(jié)

      pwmWriteMotor()函數(shù)通過簡單的索引檢查和函數(shù)指針調(diào)用機制,實現(xiàn)了高效且靈活的PWM信號生成。它能夠根據(jù)不同的硬件配置和需求選擇最合適的方法來設(shè)置電機的PWM值,確保飛行控制器能夠在各種條件下穩(wěn)定運行并精確控制電機輸出。這種方式不僅簡化了代碼結(jié)構(gòu),還提高了系統(tǒng)的可維護性和擴展性。

      圖片

      04

      最后

      圖片

      pidMultiWii()函數(shù),該函數(shù)通過結(jié)合傳感器數(shù)據(jù)(如陀螺儀、加速度計)和遙控器輸入來計算每個軸的姿態(tài)調(diào)整值,確保飛行器在各種飛行模式下保持穩(wěn)定與響應(yīng)性。它根據(jù)不同的飛行條件靈活調(diào)整控制策略,并通過混合比例項和積分項為不同模式提供更佳的控制效果。

      mixTable()函數(shù),這是連接姿態(tài)控制與實際物理動作的關(guān)鍵環(huán)節(jié),將PID控制器計算出的姿態(tài)調(diào)整命令轉(zhuǎn)換成具體的電機功率輸出,并處理相關(guān)的舵機控制信號,以滿足多種特殊配置需求,如防止偏航跳躍、相機穩(wěn)定等。

      pwmWriteMotor()的具體實現(xiàn),包括如何選擇適當(dāng)?shù)腜WM寫入方法以及如何安全地設(shè)置占空比以控制電機轉(zhuǎn)速。

      END

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多