当前位置:网站首页>Analysis of fixed point PID code of FOC motor Library
Analysis of fixed point PID code of FOC motor Library
2022-04-23 06:47:00 【tilblackout】
Code from STM32 FOC Motor Library in pid_regulator.c.
PID Structure
typedef struct PID_Handle
{
int16_t hDefKpGain; /**< Default @f$K_{pg}@f$ gain */
int16_t hDefKiGain; /**< Default @f$K_{ig}@f$ gain */
int16_t hKpGain; /**< @f$K_{pg}@f$ gain used by PID component */
int16_t hKiGain; /**< @f$K_{ig}@f$ gain used by PID component */
int32_t wIntegralTerm; /**< integral term */
int32_t wUpperIntegralLimit; /**< Upper limit used to saturate the integral
term given by @f$\frac{K_{ig}}{K_{id}} @f$ * integral of
process variable error */
int32_t wLowerIntegralLimit; /**< Lower limit used to saturate the integral
term given by Ki / Ki divisor * integral of
process variable error */
int16_t hUpperOutputLimit; /**< Upper limit used to saturate the PI output */
int16_t hLowerOutputLimit; /**< Lower limit used to saturate the PI output */
uint16_t hKpDivisor; /**< Kp gain divisor, used in conjuction with
Kp gain allows obtaining fractional values.
If FULL_MISRA_C_COMPLIANCY is not defined
the divisor is implemented through
algebrical right shifts to speed up PI
execution. Only in this case this parameter
specifies the number of right shifts to be
executed */
uint16_t hKiDivisor; /**< Ki gain divisor, used in conjuction with
Ki gain allows obtaining fractional values.
If FULL_MISRA_C_COMPLIANCY is not defined
the divisor is implemented through
algebrical right shifts to speed up PI
execution. Only in this case this parameter
specifies the number of right shifts to be
executed */
uint16_t hKpDivisorPOW2; /**< Kp gain divisor expressed as power of 2.
E.g. if gain divisor is 512 the value
must be 9 as 2^9 = 512 */
uint16_t hKiDivisorPOW2; /**< Ki gain divisor expressed as power of 2.
E.g. if gain divisor is 512 the value
must be 9 as 2^9 = 512 */
int16_t hDefKdGain; /**< Default Kd gain */
int16_t hKdGain; /**< Kd gain used by PID component */
uint16_t hKdDivisor; /**< Kd gain divisor, used in conjuction with
Kd gain allows obtaining fractional values.
If FULL_MISRA_C_COMPLIANCY is not defined
the divisor is implemented through
algebrical right shifts to speed up PI
execution. Only in this case this parameter
specifies the number of right shifts to be
executed */
uint16_t hKdDivisorPOW2; /*!< Kd gain divisor expressed as power of 2.
E.g. if gain divisor is 512 the value
must be 9 as 2^9 = 512 */
int32_t wPrevProcessVarError; /*!< previous process variable used by the
derivative part of the PID component */
} PID_Handle_t;
- The beginning of variable naming :h Express half word,w Express word.
(1)hKpGain、hKiGain、hKdGain
- Code used in PID Gain parameters
(2)hDefKpGain、hDefKiGain、hDefKdGain
- Default PID Gain settings , Set to... During motor initialization hKpGain、hKiGain、hKdGain. I don't think it's necessary to use these three variables , The old version of ST The motor library does not have these parameters .
(3)wIntegralTerm
- Integral term
(4)wPrevProcessVarError
- The error of each time the differential term needs to be recorded
(5)wUpperIntegralLimit、wLowerIntegralLimit
- The maximum limit of the integral term 、 The minimum value of the integral term is limited
(6)hUpperOutputLimit、hLowerOutputLimit
- PID Maximum output limit 、PID Output minimum limit
(7)hKpDivisor、hKiDivisor、hKdDivisor
- PID The gain parameter of should be decimal , And fixed point PID The gain of is an integer , You need to divide by a ratio
(8)hKpDivisorPOW2、hKiDivisorPOW2、hKdDivisorPOW2
- CPU The efficiency of division is not very high , So the top PID The divisor of the gain is generally set to
, Corresponding
, This shifts arithmetic right in the code , This greatly improves the operation speed .
PID Function implementation
Some controls do not require differential terms , therefore ST take PID Functions are divided into PI Control functions and PID Control function . The code is simple , Please refer to the notes for details .
PI Control function
__weak int16_t PI_Controller( PID_Handle_t * pHandle, int32_t wProcessVarError )
{
int32_t wProportional_Term, wIntegral_Term, wOutput_32, wIntegral_sum_temp;
int32_t wDischarge = 0;
int16_t hUpperOutputLimit = pHandle->hUpperOutputLimit;
int16_t hLowerOutputLimit = pHandle->hLowerOutputLimit;
/* Calculate the proportional term */
wProportional_Term = pHandle->hKpGain * wProcessVarError;
/* Calculate the integral term */
if ( pHandle->hKiGain == 0 )
{
/* The integral gain is 0, Clear the previous integral term */
pHandle->wIntegralTerm = 0;
}
else
{
/* Integral gain is not 0, Calculate the integral of this error */
wIntegral_Term = pHandle->hKiGain * wProcessVarError;
/* Add the points accumulated before */
wIntegral_sum_temp = pHandle->wIntegralTerm + wIntegral_Term;
/* Judgment overflows */
if ( wIntegral_sum_temp < 0 )
{
if ( pHandle->wIntegralTerm > 0 )
{
if ( wIntegral_Term > 0 )
{
/* If this integral and the previous integral are positive , Its sum is less than 0, It means more than INT32_MAX */
wIntegral_sum_temp = INT32_MAX;
}
}
}
else
{
if ( pHandle->wIntegralTerm < 0 )
{
if ( wIntegral_Term < 0 )
{
/* If this integral and the previous integral are negative , Its sum is greater than 0, It means more than -INT32_MAX */
wIntegral_sum_temp = -INT32_MAX;
}
}
}
/* Judge whether the user-defined integral limit is exceeded */
if ( wIntegral_sum_temp > pHandle->wUpperIntegralLimit )
{
pHandle->wIntegralTerm = pHandle->wUpperIntegralLimit;
}
else if ( wIntegral_sum_temp < pHandle->wLowerIntegralLimit )
{
pHandle->wIntegralTerm = pHandle->wLowerIntegralLimit;
}
else
{
pHandle->wIntegralTerm = wIntegral_sum_temp;
}
}
/* Fixed point PID, You need to divide by a ratio */
#ifdef FULL_MISRA_C_COMPLIANCY
wOutput_32 = ( wProportional_Term / ( int32_t )pHandle->hKpDivisor ) + ( pHandle->wIntegralTerm /
( int32_t )pHandle->hKiDivisor );
#else
/* You need to ensure that the compiler processes this line of code by arithmetic shift right , Not logical shift right */
wOutput_32 = ( wProportional_Term >> pHandle->hKpDivisorPOW2 ) + ( pHandle->wIntegralTerm >> pHandle->hKiDivisorPOW2 );
#endif
/* Judge PID Whether the output result exceeds the user-defined range */
if ( wOutput_32 > hUpperOutputLimit )
{
/* Exceeds the user-defined maximum range , Assign the value exceeded this time to wDischarge */
wDischarge = hUpperOutputLimit - wOutput_32;
wOutput_32 = hUpperOutputLimit;
}
else if ( wOutput_32 < hLowerOutputLimit )
{
/* Exceeds the user-defined minimum range , Assign the value exceeded this time to wDischarge */
wDischarge = hLowerOutputLimit - wOutput_32;
wOutput_32 = hLowerOutputLimit;
}
else { /* Nothing to do here */ }
/* take wDischarge Assign to the integral term , For the next calculation */
pHandle->wIntegralTerm += wDischarge;
return ( ( int16_t )( wOutput_32 ) );
}
PID Control function
__weak int16_t PID_Controller( PID_Handle_t * pHandle, int32_t wProcessVarError )
{
int32_t wDifferential_Term;
int32_t wDeltaError;
int32_t wTemp_output;
if ( pHandle->hKdGain != 0 ) /* derivative terms not used */
{
/* The integral term calculates the difference between this error and the last error */
wDeltaError = wProcessVarError - pHandle->wPrevProcessVarError;
/* Calculate the differential term */
wDifferential_Term = pHandle->hKdGain * wDeltaError;
#ifdef FULL_MISRA_C_COMPLIANCY
wDifferential_Term /= ( int32_t )pHandle->hKdDivisor;
#else
/* WARNING: the below instruction is not MISRA compliant, user should verify
that Cortex-M3 assembly instruction ASR (arithmetic shift right)
is used by the compiler to perform the shifts (instead of LSR
logical shift right)*/
/* Fixed point PID, You need to divide by a ratio */
wDifferential_Term >>= pHandle->hKdDivisorPOW2;
#endif
/* Record the differential term of this time */
pHandle->wPrevProcessVarError = wProcessVarError;
/* Calculate the proportional term and integral term , Plus the differential term as the output */
wTemp_output = PI_Controller( pHandle, wProcessVarError ) + wDifferential_Term;
/* User defined scope limits */
if ( wTemp_output > pHandle->hUpperOutputLimit )
{
wTemp_output = pHandle->hUpperOutputLimit;
}
else if ( wTemp_output < pHandle->hLowerOutputLimit )
{
wTemp_output = pHandle->hLowerOutputLimit;
}
else
{}
}
else
{
/* The differential gain is 0, Only the proportional and integral terms are calculated */
wTemp_output = PI_Controller( pHandle, wProcessVarError );
}
return ( ( int16_t ) wTemp_output );
}
Parameter adjustment
You should adjust the inner ring first and then the outer ring . Here's a fixed point PID Actually, it should be adjusted first hKxDivisorPOW2 Size , If you don't adjust the division term well, adjust PID The gain of , How to adjust the parameters? Finally PID The output overflows .
版权声明
本文为[tilblackout]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230549282784.html
边栏推荐
- 往String原型上封装一个时间戳转日期的方法
- 查漏补缺(七)
- WMI技术介绍和应用
- Collection of practical tips for C language (continuously updated)
- C语言实现memcpy、memset、strcpy、strncpy、strcmp、strncmp、strlen
- [UDS unified diagnostic service] II. Network layer protocol (1) - overview and functions of network layer
- ES6面试题(参考文档)
- Node的数据库编程
- [UDS unified diagnosis service] i. diagnosis overview (1) - diagnosis overview
- 软件工程中的十三种文档
猜你喜欢

深蓝学院激光slam 理论与实践 第三章激光雷达去畸变 作业习题
![[UDS unified diagnosis service] i. diagnosis overview (2) - main diagnosis protocols (K-line and can)](/img/ec/9b783b6dca5684684485e3b9fc6846.png)
[UDS unified diagnosis service] i. diagnosis overview (2) - main diagnosis protocols (K-line and can)

cuda工程更换环境(电脑)后遇到的一系列编译问题

QT icon application
![[UDS unified diagnostic service] II. Network layer protocol (2) - data transmission rules (single frame and multi frame)](/img/4f/315a9b4cd85ebaad39cfa985dea45b.png)
[UDS unified diagnostic service] II. Network layer protocol (2) - data transmission rules (single frame and multi frame)

基于VGG卷积神经网络的图像识别代码实现
![[UDS unified diagnostic service] IV. typical diagnostic service (2) - data transmission function unit](/img/22/c501c79176a93345dc72ff150c53c3.png)
[UDS unified diagnostic service] IV. typical diagnostic service (2) - data transmission function unit

MOS管特性和导通过程

基于Keras的时装分类案例

HDU-Tunnel Warfare
随机推荐
Palindromic Primes
记第一次使用阿里字体图标库
微信小程序之改变数组中某值,对象中某值的方法
Qt 给应用程序加图标
C51/C52 特殊功能寄存器表
Using printf in MFC
SQLite3 encrypted version
查漏补缺(九)---程序篇
POJ-The Unique MST
Node的数据库编程
往String原型上封装一个时间戳转日期的方法
Eigen 学习总结
查漏补缺(八)
js根据名字将数组对象中名字相同的项组成一个相同的数组
FOC电机库 定点PID代码分析
锚点定位——如何设置锚点居页面顶部距离,锚点定位并距离顶部一定偏移
浮点数双精度,单精度以及半精度知识总结
[UDS unified diagnosis service] i. diagnosis overview (3) - ISO 15765 architecture
C语言结构体指定初始化
C language advanced notes 3
, Corresponding
, This shifts arithmetic right in the code , This greatly improves the operation speed .