电路
看起来你想用 C 模拟的模拟电路看起来像这样
Ci
|------| |--------------|
| Rp |
|----/\/\/\/\-----------|
| Rd Cd |
Rf |----/\/\/\---| |-------|
Vin o----/\/\/\---| |
| |\ |
| | \ |
|----|- \ |
| \ |
| \-------------|---------o Vout
| /
| /
|+ /
----| /
| |/
|
|
___|___ GND
_____
___
_
LEGEND:
Vin is the input signal.
Vout is the Output.
Rp controls the propotional term ( P in PID)
Ci controls the Integral term ( I in PID)
Rd and Cd controls the differential term ( D in PID)
Rf is the gain control, which is common to all of the above controllers.
我强烈建议您使用this source 的电路进行学习。
尽管设置起来有点乏味,但从数学上来说分析起来要简单得多,因为您可以直接将其与标准数学形式而不是理想形式联系起来。
最后,Vout 用于控制电机或任何需要控制的东西。而Vin是过程变量电压。
在 C(海?)中弄湿你的脚之前
我假设您正在从某种模数转换器读取信号。如果不是,那么您将不得不将信号模拟为输入。
如果我们使用标准格式,
假设循环运行时间足够小(一个缓慢的过程),我们可以使用下面的函数来计算输出,
PIDoutput = Kp * err + (Ki * int * dt) + (Kd * der /dt);
在哪里
Kp = Proptional Constant.
Ki = Integral Constant.
Kd = Derivative Constant.
err = Expected Output - Actual Output ie. error;
int = int from previous loop + err; ( i.e. integral error )
der = err - err from previous loop; ( i.e. differential error)
dt = execution time of loop.
最初的“der”和“int”为零。如果您在代码中使用延迟函数将循环频率调整为 1 KHz,那么您的 dt 将为 0.001 秒。
现在前馈系统的输出是,
FeedForwardOutput = Kf * Vin;
在哪里
Kf = 前馈系统的比例常数。
因此,我们使用 PID 控制器的前馈系统的总输出将是,
Output = FeedForwardOutput + PIDoutput;
查看link 以进一步了解带有 PID 控制器的前馈系统。
用 C 绘图
我发现this 用 C 语言编写了出色的 PID 代码,虽然它没有涵盖它的所有方面,但它仍然是一个很好的代码。
//get value of setpoint from user
while(1){
// reset Timer
// write code to escape loop on receiving a keyboard interrupt.
// read the value of Vin from ADC ( Analogue to digital converter).
// Calculate the output using the formula discussed previously.
// Apply the calculated outpout to DAC ( digital to analogue converter).
// wait till the Timer reach 'dt' seconds.
}
如果我们采用一个缓慢的过程,那么我们可以使用较低的频率,这样 dt >>> 单循环的代码执行时间(远大于 )。在这种情况下,我们可以取消计时器并使用延迟功能。