当前位置:网站首页>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
边栏推荐
猜你喜欢
CUDA环境安装
基于VGG卷积神经网络的图像识别代码实现
Principle and characteristic analysis of triode
CUDA project encountered a series of compilation problems after changing the environment (computer)
el-table添加序号
C [document operation] PDF files and pictures are converted to each other
QT add qserialport class to realize serial port operation
[UDS unified diagnostic service] III. application layer protocol (1)
[UDS unified diagnostic service] IV. typical diagnostic service (2) - data transmission function unit
说说ts的心里话
随机推荐
基于SSD的物体检测案例实现
深蓝学院激光slam 理论与实践 第三章激光雷达去畸变 作业习题
微信小程序之 js 时间戳/1000 转换 秒,六个小时后,一天后,本周五 选项计算时间
[stepping on the pit] MELD in win11 wsl2 cannot be used normally. Problem repair
QT icon application
查漏补缺(九)---程序篇
[UDS unified diagnosis service] IV. typical diagnosis service (1) - diagnosis and communication management function unit
Analysis and setting of dead time
The use of volatile in C language
C语言代码规范
2022LDU寒假训练-程序补丁
cartographer_node 编译没问题,但是运行直接挂掉的bug
20220222回归职场
Qt 添加QSerialPort类 实现串口操作
[learn] HF net training
[UDS unified diagnostic service] IV. typical diagnostic service (5) - function / component test function unit (routine function unit 0x31)
MOS tube characteristics and conduction process
Makefile foundation, common functions and general makefile
微信小程序之点击取消,返回上页,修改上页的参数值,let pages=getCurrentPages() let prevPage=pages[pages.length - 2] // 上一页的数据
VHDL-任意分频器(50%占空比)