1、调试p,i,d;
http://www.360doc.com/content/14/0320/15/16303222_362183991.shtml
https://www.sohu.com/a/419217458_691475
看下动图和数据趋势;
首先,三个参数都等于0;
先调节p;
kp先调节。周期震荡。
初始值怎么定?
比如我调节速度,速度输入单位是r/s。这个大概是0-2.3r/s范围。但是实际是PWM控制。所以我的想法是,先大概找个范围。
PWM的范围是0–1000。实际转速范围是0—2.3r/s;

输入期望转速-------比较-----转换因子系数—速度PID------测速,返回到比较环节比较,同时输出。

期望假如是0.5r/s------------实际的是PWM,应该比较过后,速度和PWM的比例,我这里叫做转换因子。
这个比例应该是大概我猜测,就是1000/2=500。
所以用500作为P的初始化数据。后面先以100步长,加到1000–1300都可以。
狠下心,放大到KP=2000,看现象。再加Ki,,大概等于KP的0.5倍。试下。

看现象,按照上面的网址,动图的数据变化,调小,调大。。
2、借助SecureCRT,stm32和电脑通过串口进行通信,在这个软件里面,选择串口,然后这个工具可以用键盘在屏幕这里打入数据,单片机在串口中断中接收具体的信息,执行相关的动作。
2021-08-09 调试总结secureCRT,,,用法_#include
具体的操作步骤。
单片机向电脑这个软件,发送printf,定向。构建这个界面。这个界面自己定义,就是人机交互界面。
最好和人的操作习惯一致,交互性好。
这个不能有中文。

比如我这个界面
2021-08-09 调试总结secureCRT,,,用法_串口_02
怎么构建呢?
单片机端,一定要定义好printf重定向问题。stm32的正点原子的基本就可以了。
然后加入disp.h,disp.c文件。
里面有相关的函数。

disp.h

#ifndef __DISP_H
#define __DISP_H
#include "sys.h"
#include "usart.h"

void disp_clean(void);
void disp_cursor_reset(void);
void disp_gotoxy(int x,int y);
void disp_cursor_up(int y);
void disp_cursor_down(int y);
void disp_cursor_left(int x);
void disp_cursor_right(int x);
void disp_cursor_hide(void);
void disp_cursor_show(void);

#endif

disp.c

#include "disp.h"
#include "usart.h"
#include "stdio.h"

void disp_clean(void)
{
	printf("\033[2J");
}


void disp_cursor_reset(void)
{
		printf("\033[H");
}
void disp_gotoxy(int x,int y)
{
		printf("\033[%d;%dH",y,x);
}
void disp_cursor_up(int y)
{
	printf("\033[%dA",y);
}
void disp_cursor_down(int y)
{
	printf("\033[%dB",y);
}
void disp_cursor_left(int x)
{
	printf("\033[%dD",x);
}
void disp_cursor_right(int x)
{
	printf("\033[%dC",x);
}
void disp_cursor_hide(void)
{
	printf("\033[?25l");
}
void disp_cursor_show(void)
{
	printf("\033[?25h");
}

我是写了个界面显示的程序,main中初始化资源之后,显示初始页面。后面再串口中断中,接收到数据,就更新数据到界面,做一个反馈,不然串口有没有接收到都不知道。

在做PID实验的时候,在采样计算PID的时候,间隔100ms,刷新一次数据。比如转速,行程等。
注意,这里的坐标x,y是从1开始的。

void DispScreen(void)
{
	//12345678901234567890123456789012345678901234567890123
	//speed,,,Kp=12345.02,Ki=12345.02,Kd=12345.02,Tar=10.05;
	//Locat,,,Kp=12345.02,Ki=12345.02,Kd=12345.02,Tar=10.05;
	//PidMode=1
	//speed=12.02;WheelCir=100.25;
	disp_gotoxy(1,1);
	printf("speed,,,Kp=%.2f",Pid_Wheel1_Speed.Kp);
	disp_gotoxy(21,1);
	printf("Ki=%0.2f",Pid_Wheel1_Speed.Ki);
	disp_gotoxy(33,1);
	printf("Kd=%0.2f",Pid_Wheel1_Speed.Kd);
	disp_gotoxy(45,1);
	printf("Tar=%0.2f",Pid_Wheel1_Speed.target_val);
	
	disp_gotoxy(1,2);
	printf("locat,,,Kp=%.2f",Pid_Wheel1_Location.Kp);
	disp_gotoxy(21,2);
	printf("Ki=%0.2f",Pid_Wheel1_Location.Ki);
	disp_gotoxy(33,2);
	printf("Kd=%0.2f",Pid_Wheel1_Location.Kd);
	disp_gotoxy(45,2);
	printf("Tar=%0.2f",Pid_Wheel1_Location.target_val);
	
	
	disp_gotoxy(1,3);
	printf("pid_mode=%d",PID_mode);

  disp_gotoxy(1,4);
	printf("speed(r/s)=%.2f",WheelSpeed[0]);
	disp_gotoxy(1,5);
	printf("loc(cir)=%.2f",WheelCircles[0]);
	
	disp_gotoxy(1,6);
	printf("stepPar=%.2f",stepPar);
	
		disp_gotoxy(1,7);
	 printf("TarCir=%.2f",TarCir[0]);
}

单片机用disp函数,跳到光标中,然后printf打印数据。
在timer.c定时器中断中,计算PID,20ms计算一次PID,然后10*20=200ms刷新一次具体的数据。

2021-08-09 调试总结secureCRT,,,用法_初始化_03

单片机发送到电脑的过程,就介绍到这里。
主要要注意两点:
1、要重定向printf;
2、假如我上面的h和C文件;
3、自己定义一个交互性能好的界面;

单片机如何接受电脑键盘消息呢?
当然首先要串口连接。
下载这个SecureCRT软件。

我这里没有z做校验。就是单个字符,就认为受到了,所以有时候会卡了。这时候重新按下单片机的复位。再开始了。后面可以优化代码。

在串口中断函数中。接收到不同的电脑额键盘按键字符,就执行相关动作,然后再实时更新界面的数据。
这里有几个功能:
1、调节步长:0.01,.0.1,1,10,100;用键盘的UIOP[这5个按键;
2、将步长取反,变成负数,后面就能实现减步长了。加负数,就是减法了。这里用0按键;
3、调节PIDmode,用BNM,四个。=0,=1速度PID,=2位置PID,=3串级PID,=4自己用;
4、加速度PID的数据,就用小键盘的789,7调节KP,8调节KI ,9 KD;
5、调位置PID数据,用456;
6、调节目标值,速度目标值和位置目标值,用1,2;
7、开始PID计算,用d;
8、停止PID,用s;
9、复位单片机系统,用v.


还有he那多的键盘按键没用用到。太方便了。
但是有时候会掉线。

void USART1_IRQHandler(void)                	
{
	uint8_t data;//接收数据暂存变量
	uint8_t bufcopy[128];//最多只取前64个数据

	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{
       cmddat=USART_ReceiveData(USART1);  //将缓冲区的数据一个字节,赋值给cmddat,中转一下,不然下次数据进来,把缓冲区刷新了,数据就不见了
				switch(cmddat)
							{
									case 's' :						    // 前进forward
										  disp_gotoxy(1,10);
									    printf("cmd:q+w+s,	Action:stop PID,stop TIMER13");
											set_motor_rotate(1,0);
											PID_mode=0;
								
											TIM_Cmd(TIM13,DISABLE); //初始化	TIM_Cmd(TIM7,DISABLE); //关闭定时器7				   
											break;
									case 'd':						// 后退backxxx
										  disp_gotoxy(1,10);
											printf("cmd:q+w+d,	Action:Start PID,start TIMER13");
											TIM_Cmd(TIM13,ENABLE); //初始化
											break;
									
									case 'u':						//步长0.01
										 disp_gotoxy(1,10);
											printf("cmd:q+w+u,	Action:Change Step=0.01");
											stepPar=0.01f;
																	
									  break;
									
										case 'i':						//步长0.01
											 disp_gotoxy(1,10);
											printf("cmd:q+w+i,	Action:Change Step=0.1");
											stepPar=0.1f;
										 
											break;
									
										case 'o':						//步长0.01
										  disp_gotoxy(1,10);
											printf("cmd:q+w+o,	Action:Change Step=1.0");
											stepPar=1.0f;
										 
											break;				
										case 'p':						//步长0.01
										 disp_gotoxy(1,10);
											printf("cmd:q+w+p,	Action:Change Step=10.0");
											stepPar=10.0f;								 	
											break;	
										case '[':						//步长0.01
											disp_gotoxy(1,10);
											printf("cmd:q+w+[,	Action:Change Step=100");
											stepPar=100.0f;
								
											break;
															
										case '4':						//位置kP 参数加
										  Pid_Wheel1_Location.Kp +=stepPar;//pid->Kp
										  break;
										
										case '5':						//位置kP 参数加
										  Pid_Wheel1_Location.Ki+=stepPar;
										  break;
										
										case '6':						//位置kP 参数加
										  Pid_Wheel1_Location.Kd+=stepPar;
										  break;
										
										case '7':						//位置kP 参数加
										  Pid_Wheel1_Speed.Kp+=stepPar;
										  break;
										
										case '8':						//位置kP 参数加
										  Pid_Wheel1_Speed.Ki+=stepPar;
										  break;
										
										case '9':						//位置kP 参数加
										  Pid_Wheel1_Speed.Kd+=stepPar;
										  break;
											
										case '1':						//位置目标值参数加		 
                        Pid_Wheel1_Speed.target_val+=stepPar;
										  break;
											
										case '2':						//位置目标值参数加
										 Pid_Wheel1_Location.target_val+=stepPar;
										  break;	
										  case '0':						//位置目标值参数加
											stepPar=-stepPar;
										  break;
									
									 case 'b':						//位置目标值参数加
											PID_mode=1;
										  break;
									case 'n':						//位置目标值参数加
											PID_mode=2;
										  break;
									case 'm':						//位置目标值参数加
											PID_mode=3;
										  break;						
									case ',':						//位置目标值参数加
											PID_mode=4;
										  break;								
									case 'q':						//位置目标值参数加
											TarCir[0]+=stepPar;
										  break;						
									case 'v':						//位置目标值参数加
											NVIC_SystemReset();          // 复位系统
										  break;
								
									default:break;		
			
							}
							DispScreen();



		//data = USART_ReceiveData(USART1);   
		//Recv1[rx_cnt++]=data;//接收的数据存入接收数组 
		//protocol_data_recv(&data, 1);
		//if(Recv1[rx_cnt])

		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}