在stm32的pid控制中一般分为两种方式,一种是位置式pid,一种是增量式pid。

位置式pid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "stdlib.h"
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "string.h"
#include "OLED_Data.h"
#include <stdio.h>
#include "RP.h"
#include "Key.h"
#include "../Inc/LED.h"
#include "../Inc/Timer.h"
#include "PWM.h"
#include "Motor.h"
#include "../Inc/Encoder.h"
#include "Serial.h"

uint8_t KeyNum;
uint8_t j;
uint16_t RP[4];
int8_t PWM;
int16_t Speed;
int16_t Location;
float Target,Actual,Out; //目标值;实际值;输出值(调节的力度)
float Kp,Ki,Kd;
float Error0,Error1,ErrorIntgral; //上次误差,本次误差,误差积分
int main(void)
{
OLED_Init();
OLED_Update();
LED_Init();
Timer_Init();
Key_Init();
RP_Init();
Motor_Init();
Encoder_Init();
Serial_Init();
while (1) {

for (int i = 0; i < 4; i++) {
RP[i]=RP_GetValue(i);
}
Kp=RP[0]/4095.0*2;
Ki=RP[1]/4095.0*2;
Kd=RP[2]/4095.0*2;
Target=RP[3]/4095.0*300-150;
OLED_Printf(0, 16, OLED_8X16, "Kp:%4.2f", Kp); //显示Kp
OLED_Printf(0, 32, OLED_8X16, "Ki:%4.2f", Ki); //显示Ki
OLED_Printf(0, 48, OLED_8X16, "Kd:%4.2f", Kd); //显示Kd

OLED_Printf(64, 16, OLED_8X16, "Tar:%+04.0f", Target); //显示目标值
OLED_Printf(64, 32, OLED_8X16, "Act:%+04.0f", Actual); //显示实际值
OLED_Printf(64, 48, OLED_8X16, "Out:%+04.0f", Out); //显示输出值

OLED_Update(); //OLED更新,调用显示函数后必须调用此函数更新,否则显示的内容不会更新到OLED上
Serial_Printf("%f,%f,%f\n",Target,Actual,Out);
Delay_ms(10);

}
}


void TIM1_UP_IRQHandler(void) {
static uint16_t Count;
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) {
Key_Tick();
Count++;
if (Count>=40) {
Count=0;
Actual=Encoder_Get();//获得实际速度值
Error1=Error0;
Error0=Target-Actual;
if (Ki!=0) {
ErrorIntgral+=Error1;
}
else {
ErrorIntgral=0;
}
/*PID计算*/
Out=Kp*Error0+Ki*ErrorIntgral+Kd*(Error0-Error1);
if (Out>100) {
Out=100;
}
if (Out<-100) {
Out=100;
}
Motor_SetPWM(Out);
}
// Speed=Encoder_Get();
// Location+=Speed;
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}

增量式pid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "stdlib.h"
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "string.h"
#include "OLED_Data.h"
#include <stdio.h>
#include "RP.h"
#include "Key.h"
#include "../Inc/LED.h"
#include "../Inc/Timer.h"
#include "PWM.h"
#include "Motor.h"
#include "../Inc/Encoder.h"
#include "Serial.h"

uint8_t KeyNum;
uint8_t j;
uint16_t RP[4];
int8_t PWM;
int16_t Speed;
int16_t Location;
float Target,Actual,Out; //目标值;实际值;输出值(调节的力度)
float Kp,Ki,Kd;
float Error0,Error1,Error2; //本次误差,上次误差,上上次误差
int main(void)
{
OLED_Init();
OLED_Update();
LED_Init();
Timer_Init();
Key_Init();
RP_Init();
Motor_Init();
Encoder_Init();
Serial_Init();
while (1) {
for (int i = 0; i < 4; i++) {
RP[i]=RP_GetValue(i);
}
Kp=RP[0]/4095.0*2;
Ki=RP[1]/4095.0*2;
Kd=RP[2]/4095.0*2;
Target=RP[3]/4095.0*300-150;
OLED_Printf(0, 16, OLED_8X16, "Kp:%4.2f", Kp); //显示Kp
OLED_Printf(0, 32, OLED_8X16, "Ki:%4.2f", Ki); //显示Ki
OLED_Printf(0, 48, OLED_8X16, "Kd:%4.2f", Kd); //显示Kd

OLED_Printf(64, 16, OLED_8X16, "Tar:%+04.0f", Target); //显示目标值
OLED_Printf(64, 32, OLED_8X16, "Act:%+04.0f", Actual); //显示实际值
OLED_Printf(64, 48, OLED_8X16, "Out:%+04.0f", Out); //显示输出值

OLED_Update(); //OLED更新,调用显示函数后必须调用此函数更新,否则显示的内容不会更新到OLED上
Serial_Printf("%f,%f,%f\n",Target,Actual,Out);
Delay_ms(10);

}
}


void TIM1_UP_IRQHandler(void) {
static uint16_t Count;
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) {
Key_Tick();
Count++;
if (Count>=40) {
Count=0;
Actual=Encoder_Get();//获得实际速度值
Error1=Error0;
Error2=Error1;
Error0=Target-Actual;

/*PID计算*/
Out+=Kp*(Error0-Error1)+Ki*Error0+Kd*(Error0-2*Error1+Error2);
if (Out>100) {
Out=100;
}
if (Out<-100) {
Out=100;
}
Motor_SetPWM(Out);
}
// Speed=Encoder_Get();
// Location+=Speed;
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}