昆明企业网站建设一条龙,cnnic可信网站必须做吗,wordpress不小心改了网站地址,徐州小程序开发商差分变换法与双线性变换法的基本原理和代码实现
1.差分变换法
差分变换法就是把微分方程中的导数用有限差分来近似等效#xff0c;得到一个与原微分方程逼近的差分方程。
差分变换法包括后向差分与前向差分。
1.1 后向差分法
差分变换如下#xff1a; d e ( t ) d t e…差分变换法与双线性变换法的基本原理和代码实现
1.差分变换法
差分变换法就是把微分方程中的导数用有限差分来近似等效得到一个与原微分方程逼近的差分方程。
差分变换法包括后向差分与前向差分。
1.1 后向差分法
差分变换如下 d e ( t ) d t e ( k T ) − e ( k T − T ) T \frac{de(t)}{dt}\frac{e(kT)-e(kT-T)}{T} dtde(t)Te(kT)−e(kT−T) 对两边进行z变换可得 s 1 − z − 1 T s\frac{1-z^{-1}}{T} sT1−z−1 后向差分变换法又称后向矩阵积分法即用后向矩形面积来代替。因此当采样周期较大时这种变换方法精度变差。
由变换过程可知
若D(s)稳定则D(z)一定稳定对于不稳定的D(s)D(z)也有可能稳定。由于后向差分变换不再满足z变换定义ze^(sT)因此s平面与z平面的映射关系发生了改变数字控制器D(z)的频率响应产生了较大的畸变。
严重的频率映射畸变导致变换精度下降使后向差分变换的应用受到了一定限制但当系统性能要求不是很高时后向差分也起到一定作用。
例 D ( s ) 20 s 80 s 10 , T 0.015 D(s) \frac{20s80}{s10},T0.015 D(s)s1020s80,T0.015 采用后向差分代入下式 s 1 − z − 1 T s\frac{1-z^{-1}}{T} sT1−z−1 可得 D ( z ) U ( z ) E ( z ) 21.2 − 20 z − 1 1.15 − z − 1 D(z) \frac{U(z)}{E(z)}\frac{21.2-20z^{-1}}{1.15-z^{-1}} D(z)E(z)U(z)1.15−z−121.2−20z−1 进行z反变换可得 u ( k ) 0.87 u ( k − 1 ) 18.43 e ( k ) − 17.39 e ( k − 1 ) u(k)0.87u(k-1)18.43e(k)-17.39e(k-1) u(k)0.87u(k−1)18.43e(k)−17.39e(k−1) 进一步探究采样频率对系统映射的影响matlab代码如下
numerator [20, 80];
denominator [1, 10];
G tf(numerator, denominator);G_discrete1 c2d(G, 0.01, foh);
G_discrete2 c2d(G, 0.001, foh);
G_discrete3 c2d(G, 0.0001, foh);figure;
hold on; bode(G, G_discrete1, G_discrete2, G_discrete3);所得bode图为 由bode图可知当采样频率为0.01时离散系统有较大影响当采样频率为0.001甚至更高时离散系统基本能反应连续系统的特性。
通过后向差分设计一个PID控制器C语言伪代码实现如下
// PID参数
#define KP 1.0f // 比例增益
#define KI 0.1f // 积分增益
#define KD 0.05f // 微分增益// 控制变量
float setpoint 100.0f; // 目标速度
float currentSpeed 0.0f; // 实际速度
float previousSpeed 0.0f; // 上一速度
float integral 0.0f; // 积分值
float lastTime 0.0f; // 上次计算时间
float deltaTime 0.1f; // 计算周期假设为0.1秒void PID_Controller() {float error setpoint - currentSpeed;integral error * deltaTime;float derivative (currentSpeed - previousSpeed) / deltaTime;float output (KP * error) (KI * integral) - (KD * derivative);// 更新电机控制信号假设控制信号范围为0-255if (output 255) {output 255;} else if (output 0) {output 0;}setMotorSpeed((uint8_t)output);previousSpeed currentSpeed;
}void readCurrentSpeed() {currentSpeed getMotorSpeedFromEncoder();
}int main(void) {while (1) {readCurrentSpeed(); PID_Controller(); Delay(100); }
}verilog实现如下输出限幅等功能未实现
module PID_Controller (input wire clk, // 时钟信号input wire rst, // 复位信号input wire [15:0] setpoint, // 目标值input wire [15:0] current_value, // 当前值output reg [15:0] control_output // 控制输出
);parameter [15:0] KP 16d2; // 比例增益
parameter [15:0] KI 16d1; // 积分增益
parameter [15:0] KD 16d1; // 微分增益reg [15:0] error; // 误差
reg [15:0] previous_value; // 上一时刻的当前值
reg [31:0] integral; // 积分值
reg [15:0] derivative; // 微分值always (posedge clk or posedge rst) beginif (rst) begincontrol_output 16d0;previous_value 16d0; integral 32d0; end else beginerror setpoint - current_value;integral integral error;derivative current_value - previous_value;control_output (KP * error) (KI * integral[15:0]) - (KD * derivative);previous_value current_value;end
end
endmodule
1.2 前向差分法
前向差分变换原理 d e ( t ) d t e ( k T T ) − e ( k T ) T \frac{de(t)}{dt}\frac{e(kTT)-e(kT)}{T} dtde(t)Te(kTT)−e(kT) 进行z变换可得 s z − 1 T s \frac{z-1}{T} sTz−1 前向差分性质如下
若D(s)稳定则D(z)不一定稳定。数字控制器D(z)的频率响应会产生较大畸变。
因此前向差分很少被使用。
2.双线性变换法
双线性变化法又被称为Tustin变换法推导过程如下 z e T s e T s / 2 − T s / 2 z e^{Ts}e^{\frac{Ts/2}{-Ts/2}} zeTse−Ts/2Ts/2 对e^(Ts/2)部分进行泰勒级数展开并取前两项近似 z 2 / T s 2 / T − s z \frac{2/Ts}{2/T-s} z2/T−s2/Ts 得到双线性变换法的计算公式为 s 2 T z − 1 z 1 s \frac{2}{T}\frac{z-1}{z1} sT2z1z−1 双线性变换的特点为
若D(s)稳定则D(z)也稳定。变换前后的频率响应发生畸变。不存在频率混叠现象。 对matlab函数c2d进行简要说明; c2d将模型从连续时间转换为离散时间 sysd c2d(sysc,Ts,method) 指定离散化方法 离散化方法指定为以下值之一 zoh - 零阶保持默认值。假定控制输入在采样时间周期 Ts 内是分段常量。foh - 三角形逼近修正一阶保持。假定控制输入在采样时间周期 Ts 内是分段线性值。impulse - 冲激不变离散化tustin - 双线性突斯汀方法。要使用频率预修正指定此方法以前称为 prewarp 方法请使用 c2dOptions 的 PrewarpFrequency 选项。matched - 零极点匹配法least-squares - 最小二乘法damped - 仅基于稀疏模型的 TRBDF2 公式的阻尼突斯汀逼近。 首先对比相同采样频率下使用后向差分与双线性变换的性能影响
numerator [20, 80];
denominator [1, 10];
G tf(numerator, denominator);G_discrete1 c2d(G, 0.015, foh);
G_discrete2 c2d(G, 0.015, tustin);figure;
hold on; bode(G, G_discrete1, G_discrete2);由bode图可知在该采样频率下双线性变换与差分变化作用效果近似。 将采样频率降低到0.15
numerator [20, 80];
denominator [1, 10];
G tf(numerator, denominator);G_discrete1 c2d(G, 0.15, foh);
G_discrete2 c2d(G, 0.15, tustin);figure;
hold on; bode(G, G_discrete1, G_discrete2);观察bode图此时使用双线性变化效果优于后向差分 使用chatGPT对比这两种方法 后向差分Backward Difference和双线性差分Bilinear Difference是数值分析中常用的差分方法它们在不同的场景下各有优势。下面分别分析这两种方法的适用场景及优劣。 后向差分的优势场景 稳定性要求高的系统 后向差分法是稳定的尤其适合处理刚性系统。刚性系统的特点是某些动态特性变化非常快这使得普通的显式方法难以稳定计算。后向差分能有效避免不稳定现象。 计算时间延迟的情况 在一些实时系统中后向差分法可以使用最新的已知数据点来估计当前状态这在需要延迟计算的系统中非常有用如控制系统中的实时反馈。 简单实现 对于线性时间不变系统后向差分的实现较为简单特别是在不需要复杂的求解算法时。 误差控制 后向差分通常能更好地控制截断误差尤其在时间步长较大的情况下避免了由大时间步带来的数值误差累积。 双线性差分的优势场景 高频动态响应 双线性差分法能够更好地处理高频动态系统尤其在需要高精度模拟频率响应特性的情况下能够较好地保留系统的动态特性。 非线性系统的处理 在处理非线性系统时双线性差分法的表现往往优于后向差分。因为它能更有效地捕捉系统的变化提供更准确的结果。 数值稳定性与精度的折中 双线性差分法在保持数值稳定性的同时能够提供更高的精度。特别是在需要优化精度的应用场景下如电子电路模拟、信号处理等双线性差分具有明显优势。 适应多种时间步长 双线性差分能够更好地适应不同的时间步长能够灵活应对多种动态情况因此在自适应算法中较为常用。 总结 后向差分适合于需要稳定性和较简单实现的场合尤其是在刚性系统和实时反馈控制中。双线性差分适合于高频动态响应、非线性系统以及需要高精度的应用场合。 简而言之后向差分已经适用于大部分场景针对特殊情况再考虑使用双线性差分。
C语言代码实现例子
#include stdio.hdouble Kp 1.0; // 比例增益
double Ki 0.5; // 积分增益
double Kd 0.1; // 微分增益// 采样周期
double Ts 0.01;// PID控制器状态
double integral 0.0; // 积分项
double prev_error 0.0; // 上一时刻的误差double PID_Controller(double setpoint, double measured_value) {double error setpoint - measured_value;integral error * Ts;double derivative (2 * (error - prev_error)) / Ts; // 双线性差分法计算微分double output Kp * error Ki * integral Kd * derivative;prev_error error;return output;
}verilog代码
module PID_Controller (input wire clk,input wire reset,input wire [15:0] setpoint, // 目标值input wire [15:0] measured_value, // 测量值output reg [15:0] control_signal // 控制信号输出
);parameter Kp 16d100; // 比例增益
parameter Ki 16d50; // 积分增益
parameter Kd 16d10; // 微分增益reg [15:0] integral;
reg [15:0] prev_error;
reg [15:0] error;
reg [15:0] derivative; always (posedge clk or posedge reset) beginif (reset) beginintegral 0;prev_error 0;control_signal 0;end else beginerror setpoint - measured_value;integral integral error;derivative (error - prev_error) * 2; control_signal (Kp * error Ki * integral Kd * derivative) 8; prev_error error;end
end
endmodule