标题:
STM32 PID练习代码 风洞控制系统 通过超声波测距小乒乓球位置PID调节空心杯
[打印本页]
作者:
黑客帝国
时间:
2020-3-25 09:38
标题:
STM32 PID练习代码 风洞控制系统 通过超声波测距小乒乓球位置PID调节空心杯
STM32F1 通过超声波测距小乒乓球位置 PID控制调节空心杯电机转速 从而使小球到达设定的位置。供参考移植
制作出来的实物图如下:
IMG_20190719_144928.jpg
(6.46 MB, 下载次数: 39)
下载附件
2020-3-25 09:43 上传
单片机源程序如下:
#include "stm32f10x.h"
#include "hcsr04.h"
#include "pwm.h"
#include "delay.h"
#include "usart.h"
#include "remote.h"
#include "lcd.h"
#include "timer.h"
#include "key.h"
#include "math.h"
#include "motor.h"
float X,Err_X,Err_X_Last,Err_X_Sum;
float Aim_X;
int pwm = 0;
float distance;
u32 time = 0;
u16 count = 0;
u16 count1 = 0;
float X_Pos[100];
float X_pwm[100];
float Kp = 0,Ki = 0.2,Kd = 140;
float data[2];
u8 Key,Key_Last;
u8 Q_n;
void LCD_Display(void);
void Q_1(void);
void Q_2(void);
void Q_3(void);
void Q_4(void);
void Q_5(void);
void Q_6(void);
void Q_7(void);
int main()
{
u16 i = 0;
delay_init(); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
LCD_Init(); //LCD初始化
HC_SR04_al1_Init();
PWM_Init(3000-1,2-1); //2分频 12KHZ
Remote_Init(); //红外接收初始化
TIM5_Init(200-1,7200-1);//20ms进入一次
KEY_Init();
Motor_Init();
TIM_SetCompare1(TIM3,0);
POINT_COLOR=RED; //设置字体为红色
LCD_ShowString(30,50,200,16,16,"X:");
LCD_ShowString(30,70,200,16,16,"PWM:");
LCD_ShowString(30,90,200,16,16,"Time:");
LCD_ShowString(30,110,200,16,16,"Kd:");
LCD_ShowString(30,130,200,16,16,"Ki:");
Motor_Drive(Start);
//TIM_Cmd(TIM5,DISABLE);
while(1)
{
distance = Senor_Using_3();
if(distance >= 60) distance = 4;
//printf("%f\r\n",distance);
/*
Key = KEY_Scan(0);
switch(Key)
{
case KEY0_PRES: Ki += 0.1; break;
case KEY1_PRES: Ki -= 0.1;break;
case WKUP_PRES: break;
}
*/
//TIM_SetCompare1(TIM3,pwm);
Key = Remote_Scan();
if(Key)
{
switch(Key)
{
case 104:pwm = 0;time = 0;count1 = 0; Q_n = 1;delay_ms(500);break;
case 152:pwm = 0;time = 0;count1 = 0; Q_n = 2;delay_ms(500);break;
case 176:pwm = 0;time = 0;count1 = 0; Q_n = 3;delay_ms(500);break;
case 48:pwm = 0;time = 0;count1 = 0; Q_n = 4;delay_ms(500);break;
case 24:pwm = 0;time = 0;count1 = 0; Q_n = 5;delay_ms(500);break;
case 122:pwm = 0;time = 0;count1 = 0; Q_n = 6;delay_ms(500);break;
case 16:pwm = 0;time = 0;count1 = 0; Q_n = 7;delay_ms(500);break;
case 162:pwm = 0;time = 0;count1 = 0;Q_n = 0;delay_ms(500);break;
}
}
delay_ms(10);
//data[0] = X;
//data[1] = Aim_X;
//Send_wave((u8 *)data);
LCD_Display();
}
}
void LCD_Display(void)
{
LCD_ShowNum(86,50,X,3,16); //显示键值
LCD_ShowNum(86,70,pwm,4,16); //显示按键次数
LCD_ShowNum(86,90,time,4,16); //显示稳定时间
LCD_ShowNum(86,110,Kd,4,16); //显示稳定时间
LCD_Showfloat(86,130,Ki,4,16);
}
void PID_Control()
{
pwm = 1520 + Kp*Err_X + Ki*Err_X_Sum + Kd*(Err_X - Err_X_Last);
//pwm += Kp*Err_X*0.02;
}
void TIM5_IRQHandler()
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET)
{
X = distance - 4;
Err_X = X - Aim_X;
Err_X_Sum += Err_X;
data[0] = X;
data[1] = Aim_X;
//Send_wave((u8 *)data);
//误差和限幅
if(Err_X_Sum >= 1500) Err_X_Sum = 1500;
if(Err_X_Sum <= -1500) Err_X_Sum = -1500;
switch(Q_n)
{
case 0: pwm = 0;break;
case 1: Q_1();break;
case 2: Q_2();break;
case 3: Q_3();break;
case 5: Q_5();break;
case 6: Q_6();break;
case 7: Q_7();break;
}
if(pwm > 2600) pwm = 2600;
Err_X_Last = Err_X;
TIM_SetCompare1(TIM3,pwm);
}
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);//清除中断标志
}
void Q_1()
{
Aim_X = 15.0;
Kp = 80;
Ki = 0.3;
Kd = 200;
PID_Control();
if(X >= 10&&X <= 20)
{
count++;
if(count == 50)
{
count = 0;
time++;
}
}
else
{
count = 0;
time = 0;
}
//TIM_SetCompare1(TIM3,pwm);
}
void Q_2()
{
Aim_X = 12.0;
Kp = 80;
Ki = 0.5;
Kd = 200;
PID_Control();
if(X >= 10&&X <= 20)
{
count++;
if(count == 50)
{
count = 0;
time++;
}
}
else
{
count = 0;
time = 0;
}
}
void Q_3()
{
u8 key;
if(count1 == 0)//第一次的PID参数和位置的初始化
{
Aim_X = 20.0;
Kp = 80;
Ki = 0.3;
Kd = 200;
}else
{
count1 = 1;
}
count1++;
PID_Control();
key = KEY_Scan(0);
if(key == KEY0_PRES)
{
Aim_X -= 1.0;
Ki = 0.8;
time = 0;
}
else if(key == KEY1_PRES)
{
Aim_X += 1.0;
Ki = 0.8;
time = 0;
}
if(fabs(Err_X) <= 1.0)
{
count++;
if(count == 50)
{
count = 0;
time++;
}
}
}
void Q_5()
{
if(count1 == 0)//第一次的PID参数和位置的初始化
{
pwm = 0;
}else
{
count1 = 1;
if(pwm == 2600)
{
count++;
if(count == 50)
{
count = 0;
time++;
}
}
pwm += 20;
}
count1++;
}
void Q_6()
{
if(count1 == 0)//到达AB段维持3秒
{
Aim_X = 8.0;
Kp = 80;
Ki = 0.5;
Kd = 260;
PID_Control();
if(pwm > 2200) pwm = 2200;
if(fabs(Err_X) < 0.5)
{
count++;
if(count == 50)
{
count = 0;
time++;
if(time >= 3)
{
count1 = 1;
time = 0;
}
}
}
}
if(count1 == 1)//到达CD段维持3秒
{
Aim_X = 25.0;
Kp = 80;
Ki = 0.5;
Kd = 220;
PID_Control();
if(X >= 20&&X <= 30)
{
count++;
if(count == 50)
{
count = 0;
time++;
if(time >= 3)
{
count1 = 2;
time = 0;
}
}
}
else
{
count = 0;
time = 0;
}
}
if(count1 == 2)//再次到达AB段维持3秒
{
Aim_X = 8.0;
Kp = 80;
Ki = 0.5;
Kd = 260;
PID_Control();
if(pwm > 2200) pwm = 2200;
if(fabs(Err_X) < 0.5)
{
count++;
if(count == 50)
{
count = 0;
time++;
if(time >= 3)
{
count1 = 3;
time = 0;
}
}
}
}
if(count1 == 3)//再次到达CD段维持3秒
{
Aim_X = 25.0;
Kp = 80;
Ki = 0.4;
Kd = 200;
PID_Control();
if(X >= 20&&X <= 30)
{
count++;
if(count == 50)
{
count = 0;
time++;
if(time >= 3)
{
count1 = 4;
time = 0;
}
}
}
else//不稳则计时清零
{
count = 0;
time = 0;
}
}
if(count1 == 4)//冲出重围
{
if(pwm == 2600)
{
count++;
if(count == 50)
{
count = 0;
time++;
}
}
pwm += 20;
}
}
void Q_7()
{
if(count1 == 0)//第一次的PID参数和位置的初始化
{
pwm = 0;
}else
{
count1 = 1;
if(distance<=41)
{
Aim_X = 15.0;
Kp = 80;
Ki = 0.4;
Kd = 220;
PID_Control();
}
else
{
pwm = 0;
}
if(X >= 10 && X <= 20)
{
count++;
if(count == 50)
{
count = 0;
time++;
}
}
else
{
time = 0;
count = 0;
}
}
count1++;
}
复制代码
所有资料51hei提供下载:
风洞系统.7z
(231.54 KB, 下载次数: 122)
2020-3-25 16:39 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
jiangkeqin_sy
时间:
2020-4-1 09:39
好东西
作者:
ahG
时间:
2021-5-12 22:39
大哥,怎么接线啊 看你的超声波的引脚看的我懵逼了
作者:
kekekeya
时间:
2021-7-14 20:13
楼主 请问一下 你风机的型号是什么
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1