怎么利用網(wǎng)站做cpa推廣傳播易廣告投放平臺
PID 控制算法是一種常用的反饋控制算法,用于控制系統(tǒng)的穩(wěn)定性和精度。PID 分別代表比例(Proportional)、積分(Integral)和微分(Derivative),通過組合這三個部分來調(diào)節(jié)控制輸出,以使系統(tǒng)的實際輸出值盡可能接近預(yù)期的參考值。
算法介紹
PID(比例-積分-微分)控制算法是一種廣泛使用的控制算法,用于調(diào)節(jié)系統(tǒng)的輸出以匹配所需的參考輸入。PID 控制器基于三個基本組件來計算其控制輸出:比例(Proportional)、積分(Integral)和微分(Derivative)。
- 比例(P)控制:
- 比例控制是最簡單的控制形式??刂破鞯妮敵鍪禽斎胝`差的一個比例。誤差是參考輸入與實際系統(tǒng)輸出之間的差異。
- 比例控制可以快速響應(yīng)誤差,但它不能消除穩(wěn)態(tài)誤差(即系統(tǒng)穩(wěn)定后仍然存在的誤差)。
- 如果比例系數(shù)設(shè)置得太大,系統(tǒng)可能會變得不穩(wěn)定,出現(xiàn)振蕩。
- 積分(I)控制:
- 積分控制考慮了過去的誤差。它通過對誤差進(jìn)行積分來消除穩(wěn)態(tài)誤差。
- 積分控制有助于減小系統(tǒng)穩(wěn)定后的誤差,但也可能導(dǎo)致系統(tǒng)響應(yīng)變慢,并可能增加超調(diào)(即系統(tǒng)輸出超過參考輸入的情況)。
- 如果積分系數(shù)設(shè)置得太大,系統(tǒng)可能變得對擾動非常敏感,甚至可能產(chǎn)生積分飽和現(xiàn)象(即積分項累積到過大,導(dǎo)致系統(tǒng)響應(yīng)異常)。
- 微分(D)控制:
- 微分控制基于誤差的變化率來預(yù)測未來的誤差,并據(jù)此調(diào)整控制輸出。
- 微分控制有助于加快系統(tǒng)的響應(yīng)速度,減少超調(diào),并增加系統(tǒng)的穩(wěn)定性。
- 然而,微分控制對噪聲非常敏感,因為噪聲通常會導(dǎo)致誤差的突然變化,這可能被誤認(rèn)為是誤差的變化率。
PID 的基本公式:
Output = K_p * Error + K_i * Integral(Error) + K_d * Derivative(Error)
其中,Error 表示期望值與實際值之間的偏差,(K_p)、(K_i) 和 (K_d) 分別表示比例、積分和微分部分的系數(shù)。如何使用 PID 控制算法:
-
確定系統(tǒng)模型和參數(shù) 在應(yīng)用 PID 控制算法前,需要確定控制對象的數(shù)學(xué)模型和相關(guān)參數(shù),例如比例系數(shù) (K_p)、積分時間 (T_i)、微分時間 (T_d) 等。
-
實現(xiàn) PID 控制器 在代碼中實現(xiàn) PID 控制器,通常需要記錄上一次的誤差值以及積分值,以便計算出下一次的控制輸出。
?
PID 控制器的調(diào)整
調(diào)整 PID 控制器的參數(shù)(即?K_p
、K_i
?和?K_d
)是 PID 控制中的關(guān)鍵任務(wù)。這通常涉及到一些試驗和誤差調(diào)整,或者使用更先進(jìn)的調(diào)優(yōu)方法。
對不同工況和“場景”下往往需要設(shè)置不同的PID形式,不同的PID參數(shù)達(dá)到預(yù)期控制效果,其實就是需要人工經(jīng)驗設(shè)定規(guī)則來適應(yīng)不同工況,所以不能算是自動的控制;相信用過PID的都知道一套口訣,在實際調(diào)參依賴口訣調(diào)參,然后調(diào)出一個理想的控制曲線,調(diào)參過程依賴人工。
也可以借助野火的 PID調(diào)試助手工具來調(diào)試pid的參數(shù)。
代碼示例?
class PIDController {
public:double compute(double setpoint, double measurement) {double error = setpoint - measurement;integral += error * dt;derivative = (error - prevError) / dt;output = Kp * error + Ki * integral + Kd * derivative;prevError = error;return output;}private:double Kp = 1.0;double Ki = 0.1;double Kd = 0.01;double integral = 0.0;double derivative = 0.0;double prevError = 0.0;double output = 0.0;double dt = 0.1; // 采樣時間
};
-
調(diào)試和調(diào)整參數(shù) 調(diào)試 PID 控制器需要不斷調(diào)整參數(shù),觀察實際輸出值與期望值之間的偏差,逐步優(yōu)化參數(shù),以實現(xiàn)系統(tǒng)的穩(wěn)定控制。
-
實時應(yīng)用 在實際控制系統(tǒng)中,將計算得到的 PID 控制器的輸出值應(yīng)用到相應(yīng)的執(zhí)行機(jī)構(gòu)或系統(tǒng)中,以實現(xiàn)期望的控制效果。
以下是一個簡單的 C++ 示例,演示如何實現(xiàn)一個基本的 PID 控制器,并在一個簡單的模擬系統(tǒng)中應(yīng)用該控制器。這個例子中,模擬一個以恒定速度運動的小車,通過 PID 控制器調(diào)節(jié)小車的速度,使其盡快達(dá)到期望速度。注意,這只是一個簡單的演示,實際系統(tǒng)中可能需要更復(fù)雜的控制邏輯和參數(shù)調(diào)整。
#include <iostream>class PIDController {
public:PIDController(double kp, double ki, double kd, double dt) : Kp(kp), Ki(ki), Kd(kd), dt(dt) {}double compute(double setpoint, double measurement) {double error = setpoint - measurement;integral += error * dt;derivative = (error - prevError) / dt;output = Kp * error + Ki * integral + Kd * derivative;prevError = error;return output;}private:double Kp;double Ki;double Kd;double dt;double integral = 0.0;double derivative = 0.0;double prevError = 0.0;double output = 0.0;
};class Car {
public:void setSpeed(double speed) {currentSpeed = speed;}void update() {// 模擬小車運動,這里假設(shè)小車以固定加速度加速到目標(biāo)速度currentSpeed += acceleration;std::cout << "Current speed: " << currentSpeed << std::endl;}double getSpeed() const {return currentSpeed;}private:double currentSpeed = 0.0;double acceleration = 0.1;
};int main() {PIDController pid(0.5, 0.01, 0.1, 0.1); // 設(shè)置 PID 控制器的參數(shù)Car car;double targetSpeed = 10.0; // 設(shè)置目標(biāo)速度for (int i = 0; i < 100; ++i) {double speedError = targetSpeed - car.getSpeed();double controlOutput = pid.compute(targetSpeed, car.getSpeed());std::cout << "speedError: " << speedError << std::endl;std::cout << "controlOutput: " << controlOutput << std::endl;car.setSpeed(9+i/50.0); // 應(yīng)用控制輸出調(diào)節(jié)小車速度car.update();}return 0;
}
在這個簡單的示例中,創(chuàng)建了一個 PIDController 類來模擬 PID 控制器的行為,然后創(chuàng)建了一個 Car 類來模擬一個運動的小車。在主函數(shù)中,設(shè)置?PID 控制器的參數(shù),并循環(huán)調(diào)用 PID 控制器來調(diào)節(jié)小車的速度,直到達(dá)到目標(biāo)速度為止。
注意,實際的 PID 控制器需要根據(jù)具體的控制對象和系統(tǒng)需求進(jìn)行調(diào)整和優(yōu)化。
c語言實現(xiàn)
#include "pid.h"
/***************************************************************批量復(fù)位PID函數(shù)* @param[in] * @param[out] * @return ***************************************************************/
void pidRest(PidObject **pid,const uint8_t len)
{uint8_t i;for(i=0;i<len;i++){pid[i]->integ = 0;pid[i]->prevError = 0;pid[i]->out = 0;pid[i]->offset = 0;}
}/*************************************************************** Update the PID parameters.** @param[in] pid A pointer to the pid object.* @param[in] measured The measured value* @param[in] updateError Set to TRUE if error should be calculated.* Set to False if pidSetError() has been used.* @return PID algorithm output***************************************************************/
void pidUpdate(PidObject* pid,const float dt)
{float error;float deriv;error = pid->desired - pid->measured + pid->offset; //當(dāng)前角度與實際角度的誤差pid->integ += error * dt; //誤差積分累加值// pid->integ = LIMIT(pid->integ,pid->IntegLimitLow,pid->IntegLimitHigh); //進(jìn)行積分限幅deriv = (error - pid->prevError)/dt; //前后兩次誤差做微分pid->out = pid->kp * error + pid->ki * pid->integ + pid->kd * deriv;//PID輸出//pid->out = LIMIT(pid->out,pid->OutLimitLow,pid->OutLimitHigh); //輸出限幅pid->prevError = error; //更新上次的誤差}/*************************************************************** CascadePID* @param[in] * @param[out] * @return ***************************************************************/
void CascadePID(PidObject* pidRate,PidObject* pidAngE,const float dt) //串級PID
{ pidUpdate(pidAngE,dt); //先計算外環(huán)pidRate->desired = pidAngE->out;pidUpdate(pidRate,dt); //再計算內(nèi)環(huán)
}
應(yīng)用示例
#include "pid.h"
#include <stdio.h>int main()
{printf("hello pid test \n");float target_water_level = 100.0; // 目標(biāo)水位10Lfloat feedback_water_level = 0.0; // 初始水位0LPidObject pidRate;PidObject *pPidObject[]={&pidRate};pidRest(pPidObject,1);pidRate.kp = 0.1f; // 比例系數(shù)pidRate.ki = 0.01f; // 積分系數(shù)pidRate.kd = 0.05f; // 微分系數(shù)float dt = 0.003;// 3ms 采樣時間pidRate.measured = 0;pidRate.desired = 100.00; //控制期望值 10L// 模擬控制循環(huán)for (int i = 0; i < 100; i++) { // 模擬水位反饋pidUpdate(&pidRate,dt); //pid處理feedback_water_level = 91+i/50.00; // 模擬每次循環(huán)水位波動 (傳感器水位采集反饋值)pidRate.measured = feedback_water_level;//pidRate.desired = pidRate.out;// 輸出當(dāng)前水位和閥門開度補償值printf("Feedback Water Level: %.2fL, Valve Openness: %.2f\n", feedback_water_level, pidRate.out);}return 0;
}
為什么pwm可以調(diào)速
pwm占空比就是一個脈沖周期內(nèi)有效電平在整個周期所占的比例。
通過調(diào)節(jié)PWM的占空比就能調(diào)節(jié)IO口上電壓的持續(xù)性變化,因此也能夠控制外設(shè)的功率進(jìn)行持續(xù)性變化,也就能控制直流電機(jī)的轉(zhuǎn)速快慢。
一種情況,對于電阻,直流電機(jī)來說,有占空比雖然從微觀來說是波,但從宏觀來說,就相當(dāng)于將輸入電壓打個折扣再輸出,輸入5伏,占空比是50%,那么輸出就是2.5伏,一般來說,直流電機(jī)的轉(zhuǎn)速是和其輸入電壓成正比的。
還有種情況,就是通過連續(xù)改變PWM的占空比,將直流電切成大小不一,有規(guī)律的波形,宏觀上形成不同頻率的正弦波,這就叫斬波。通過斬波可以產(chǎn)生任意頻率的交流電。
其他資源
PID算法詳解及實例分析_pid控制原理詳解及實例說明-CSDN博客
一文搞懂PID控制算法_pid算法-CSDN博客
什么是PID控制?
PWM原理 PWM頻率與占空比詳解-CSDN博客
電機(jī)控制進(jìn)階——PID速度控制 - 知乎
通俗易懂!講解PID! - 知乎
編碼器計數(shù)原理與電機(jī)測速原理——多圖解析 - 知乎
電機(jī)PID控制補充篇-野火上位機(jī)串口協(xié)議介紹 - 知乎
電機(jī)控制進(jìn)階——PID速度控制
野火串口調(diào)試助手PID功能(文末有工程鏈接)_野火多功能調(diào)試助手-CSDN博客