1.串口
1.1指令
根据ASCII码,将几块连续字符码分配给不同类型的指令。这里有三种指令。
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/J3R5QMK2ENGMSW7SP51.jpg)
变量定义
static int uart_receive=0; //蓝牙接收相关变量
static u8 Flag_PID,i,j,Receive[50]; //蓝牙接收相关变量
static float Data; //蓝牙接收相关变量
uart_receive=USART2->DR;
Usart2_Receive=uart_receive;
指令1,选择工作模式。
//*************************调试界面下方按键*************************************//
if(uart_receive>=97&&uart_receive<=105) //键值a至i
{
switch(uart_receive)
{
case 0x61: Debug_key=1; break; //指令a==直线模式
case 0x62: Debug_key=2; break; //指令b==圆周模式
case 0x63: Debug_key=3; break; //指令c==稳态模式
case 0x64: Debug_key=4; break; //指令d==清除
case 0x65: Debug_key=0; break; //指令e==自定义模式
case 0x66: Debug_key=0; break; //指令f==自定义模式
case 0x67: Debug_key=7; break; //指令g==读零
case 0x68: Debug_key=8; break; //指令h==自定义模式
case 0x69: Debug_key=0; break; //指令i==自定义模式
}
}
//*****************************************************************************//
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/334EFC6B0C4E6486D4C7146E3BC03208-scaled-1.jpg)
指令2,选择客户端控制模式。
//*******************控制界面下方按键选择控制方式********************************//
if(uart_receive>=73&&uart_receive<=75)
{
switch(uart_receive)
{
case 0x49: Control_way=1; break; //指令I==重力模式
case 0x4A: Control_way=2; break; //指令J==遥感模式
case 0x4B: Control_way=3; break; //指令K==按键模式
}
}
//*****************************************************************************//
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/45CBDB0F1C8AA617926720A0D0896460-scaled-1.jpg)
指令3,把圆分成八份,每π/4一个方向指令。
//***********************控制界面下方方向控制************************************//
if((uart_receive>=65&&uart_receive<=72)||(uart_receive==90))
{
switch(uart_receive)
{
case 0x41: Flag_Direction=1; break; //指令A==向前
case 0x42: Flag_Direction=2; break; //指令B==右前
case 0x43: Flag_Direction=3; break; //指令C==向右
case 0x44: Flag_Direction=4; break; //指令D==右后
case 0x45: Flag_Direction=5; break; //指令E==向后
case 0x46: Flag_Direction=6; break; //指令F==左后
case 0x47: Flag_Direction=7; break; //指令G==向左
case 0x48: Flag_Direction=8; break; //指令H==左前
default: Flag_Direction=0; break; //指令Z==停止
}
}
//*****************************************************************************//
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/90F76A6960DF3F84A7C545DA29634E04-scaled-1.jpg)
1.2调参
为了表示浮点数,显示的数值都是放大了 100 倍的。比如显示的 10000,实际该参数是 100。
调参代码
//*************************调节界面9通道参数*************************************//
if(Usart2_Receive==0x7B) Flag_PID=1; //指令{ == 起始位
if(Usart2_Receive==0x7D) Flag_PID=2; //指令 }== 停止位
if(Flag_PID==1) Receive[i]=Usart2_Receive , i++;//记录参数
if(Flag_PID==2) //解析数据
{
if(Receive[3]==0x50) PID_Send=1; //指令P==获取设备参数
else if(Receive[3]==0x57) Flash_Send=1; //指令W==掉电保存参数
else if(Receive[1]!=0x23) //指令#==更新PID参数
{
for(j=i;j>=4;j--)
{
Data+=(Receive[j-1]-48)*pow(10,i-j);
}
switch(Receive[1])
{
case 0x30: Basic_Amplitude=Data/100;break; //0==振幅
case 0x31: Position_KP=Data/100 ;break; //1==X方向KP
case 0x32: Position_KD=Data/100 ;break; //2==X方向KD
case 0x33: Position_Kp=Data/100 ;break; //3==Y方向Kp
case 0x34: Position_Kd=Data/100 ;break; //4==Y方向Kd
case 0x35: break;//Data_Period=Data/100;break; //5==预留可调周期
case 0x36: break;//Data_Phase=Data/100;break; //6==预留可调相位差
case 0x37: break;//Data_delta=Data/100;break; //7==预留可调振幅比例
case 0x38: break; //8==预留
}
}
//相关标志位清零
Flag_PID=0;
i=0;
j=0;
Data=0;
memset(Receive, 0, sizeof(u8)*50);
}
//*****************************************************************************//
通信协议
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/image.png)
示意图
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/3ED65FC0C26488148DE04ECF7CD28E28.jpg)
2.运动学分析、算法
控制原理:陀螺仪测量角度,角度转换为二维位置坐标,以设定的X,Y轴运动拟合函数为期望值,通过位置式PID修订电机PWM实现控制。
关键词:角度,坐标,PID,简谐运动,李萨如图形
2.1单摆
简谐运动
定义:物体受力大小与位移成正比,而方向相反
示意图(手写笔记)
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/54B169C61B4513B6B35EACCF748178E7.jpg)
2.2李萨如图形
定义:李萨如图形由在互相垂直的方向上的两个频率成简单整数比的
简谐振动所合成的规则的、稳定的闭合曲线;
要点:互相垂直 · 简谐运动 · 频率成整数比
拟合函数代码
Target_X=Amplitude_x*sin(Alpha); //X方向目标值函数
Target_Y=Amplitude_y*sin(Alpha+Phase); //Y方向目标值函数
手写笔记
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/A77089660E3ED6EEA8E8B1533602AFD9.jpg)
2.3测量(X,Y轴投影)
测量代码
Measure_X=(float)tan((Roll-ZHONGZHI_B)/180*2*PI)*Height;
Measure_Y=(float)tan((Pitch-ZHONGZHI_A)/180*2*PI)*Height;
运算需将角度转弧度
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/image-1.png)
示意图
![](https://ywhao.bitworkshop.cn/wp-content/uploads/2022/07/92A382DE67357D456704FCADF8F31ADA.jpg)
2.4PID算法
代码
Motor_X=Position_PID_X(Measure_X,Target_X);
Motor_Y=Position_PID_Y(Measure_Y ,Target_Y);
PID封装函数
/**************************************************************************
函数功能:位置式PID控制器
入口参数:编码器测量位置值,目标值
返回值 :电机PWM
根据位置式离散PID公式
pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
e(k)代表本次偏差
e(k-1)代表上一次偏差
∑e(k)代表e(k)以及之前的偏差的累计值;其中k为1,2,,k
pwm代表输出
**************************************************************************/
int Position_PID_X (float value,float Target)
{
static float Bias,Pwm,Integral_bias,Last_Bias;
Bias=value-Target; //计算偏差
Integral_bias+=Bias; //求出偏差的积分
Pwm=Position_KP*Bias+ //PID控制器比例项
Position_KI*Integral_bias+ //PID控制器积分项
Position_KD*(Bias-Last_Bias); //PID控制器微分项
Last_Bias=Bias; //保存上一次偏差
return Pwm; //输出PWM
}
int Position_PID_Y (float value,float Target)
{
static float Bias,Pwm,Integral_bias,Last_Bias;
Bias=value-Target; //计算偏差
Integral_bias+=Bias; //求出偏差的积分
Pwm=Position_Kp*Bias+ //PID控制器比例项
Position_Ki*Integral_bias+ //PID控制器积分项
Position_Kd*(Bias-Last_Bias); //PID控制器微分项
Last_Bias=Bias; //保存上一次偏差
return Pwm; //输出PWM
}
Comments NOTHING