工赛物流搬运车制作-记录

工赛物流搬运车制作-记录

记录我这次参加第七届工赛的小车制作过程,本次制作得比较low,下次制作回头看看这次思路并加强加固。

1. 设计思路
本次设计小车的运动,用到了 陀螺仪保持车身+ 四路激光测距粗劣定位 + 灰度精确定位 详情请看b站国一的那位大佬;我也是借鉴;

2. 材料
F103Vet6 二维码模块 openmv 麦克纳姆轮 编码电机 四个灰度 四路激光2m测距 mpu6050 四个舵机

3. 先让轮子动起来
因为用的是编码电机,所以先了解什么编码电机的运作。本人能力有限所借鉴了下面这位大佬的文章进行修改成四个电机的PID控制速度。
电机的pwm:pwm
电机的测速:测速
电机的pid控制:PID
如果需要请自行到他的公众号下载

下面是我修改的代码

	Get_Motor_Speed(&SpeedNowA,&SpeedNowB,&SpeedNowC,&SpeedNowD);   //计算电机速度
    pid_Task_A.speedNow  = SpeedNowA;
    pid_Task_B.speedNow  = SpeedNowB;
    pid_Task_C.speedNow  = SpeedNowC;
    pid_Task_D.speedNow  = SpeedNowD;
    //执行PID控制函数
    Pid_A_Ctrl(&motorA);  
    Pid_B_Ctrl(&motorB);
    Pid_C_Ctrl(&motorC);
    Pid_D_Ctrl(&motorD);
/**************************************************************************
函数功能:计算左右轮速
入口参数:int *leftSpeed,int *rightSpeed
返回  值:无
		//计算左右车轮线速度,正向速度为正值 ,反向速度为负值,速度为乘以1000之后的速度 mm/s
		//一定时间内的编码器变化值*转化率(转化为直线上的距离m)*200s(5ms计算一次) 得到 m/s *1000转化为int数据

		一圈的脉冲数:
			左:1560
			右:1040
		轮子半径:0.03m
		轮子周长:2*pi*r
		一个脉冲的距离:0.000120830m
		速度分辨率:0.0120m/s 12.0mm/s
**************************************************************************/

void Get_Motor_Speed(int *ASpeed,int *BSpeed,int *CSpeed,int *DSpeed)
{
	static int WheelEncoderNowA    = 0;
	static int WheelEncoderNowB    = 0;
	static int WheelEncoderNowC    = 0;    
	static int WheelEncoderNowD    = 0;
    
	static int WheelEncoderLastA   = 0;
	static int WheelEncoderLastB   = 0;
	static int WheelEncoderLastC   = 0;
	static int WheelEncoderLastD   = 0;	
	
	//记录本次左右编码器数据
	WheelEncoderNowA += getTIMx_DetaCnt(TIM2);
	WheelEncoderNowB += getTIMx_DetaCnt(TIM3);
	WheelEncoderNowC += getTIMx_DetaCnt(TIM4);
	WheelEncoderNowD += getTIMx_DetaCnt(TIM5);    
		
	//5ms测速    	
	*ASpeed   = (WheelEncoderNowA - WheelEncoderLastA)*1000*200*0.00015103;  
	*BSpeed   = (WheelEncoderNowB - WheelEncoderLastB)*1000*200*0.00015103;
	*CSpeed   = -(WheelEncoderNowC - WheelEncoderLastC)*1000*200*0.00015103;  
	*DSpeed   = (WheelEncoderNowD - WheelEncoderLastD)*1000*200*0.00015103;    

	//记录上次编码器数据
	WheelEncoderLastA = WheelEncoderNowA;                    
	WheelEncoderLastB = WheelEncoderNowB; 
    WheelEncoderLastC = WheelEncoderNowC;  
    WheelEncoderLastD = WheelEncoderNowD;  

}
/*******************************************************************************
 * 函数名:Pid_Ctrl(int *leftMotor,int  *rightMotor)
 * 描述  :Pid控制
 *******************************************************************************/
void Pid_A_Ctrl(int *AMotor)
{
    Pid_A_Which(&pid_Task_A);
	*AMotor  += pid_Task_A.Adjust;

}

void Pid_B_Ctrl(int *BMotor)
{
    Pid_B_Which(&pid_Task_B);
	*BMotor  += pid_Task_B.Adjust;

}

void Pid_C_Ctrl(int *CMotor)
{
    Pid_C_Which(&pid_Task_C);
	*CMotor  += pid_Task_C.Adjust;

}

void Pid_D_Ctrl(int *DMotor)
{
    Pid_D_Which(&pid_Task_D);
	*DMotor  += pid_Task_D.Adjust;

}

差不多是这样子;总结当时我改时出现的问题
1.因为接线接错 后面的两个轮子总是不能转困扰了我一个星期,后面从新差杜邦线接对了就转了,那个恨啊!
2.PID没有调好车子打歪;
3.四个编码器 我用了 TIM2 3 4 5; TIM8 用来输出PWM了,TIM1给了舵机;没有装陀螺仪前一直用通用TIM6和7来调试;

4.下面进入陀螺仪的调试
陀螺仪也是根据上面那位大佬的文章进行改编
陀螺仪陀螺仪
用上陀螺仪后 就不用TIM6 和7 进行调试了 因为都是5ms的定时

void EXTI15_10_IRQHandler(void) 
{    
	EXTI_ClearITPendingBit(EXTI_Line12);                            //===清除LINE12线路挂起位  
    getAngle(&yaw,&yaw_acc_error);                                   //获取角度 
    yaw_acc_error += FIVE_MS_ERROR;	                                 //===yaw漂移误差累加
	Get_Motor_Speed(&SpeedNowA,&SpeedNowB,&SpeedNowC,&SpeedNowD);   //计算电机速度
    pid_Task_A.speedNow  = SpeedNowA;
    pid_Task_B.speedNow  = SpeedNowB;
    pid_Task_C.speedNow  = SpeedNowC;
    pid_Task_D.speedNow  = SpeedNowD;
    //执行PID控制函数
    Pid_A_Ctrl(&motorA);  
    Pid_B_Ctrl(&motorB);
    Pid_C_Ctrl(&motorC);
    Pid_D_Ctrl(&motorD);
    }

得到的数值是 0到360° YAW 这个变量 一上机开始是0° 后面我改了数值让他开机是180°
在这个函数的最后一句 加上180就可以了

/**************************************************************************
函数功能:读取MPU6050内置DMP的姿态信息
入口参数:无
返回  值:无
**************************************************************************/
void Read_DMP(void)
{	
	unsigned long sensor_timestamp;
	unsigned char more;
	long quat[4];

	dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more);		
	if (sensors & INV_WXYZ_QUAT )
	{    
		 q0=quat[0] / q30;
		 q1=quat[1] / q30;
		 q2=quat[2] / q30;
		 q3=quat[3] / q30;
//		 Pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; 	
		 Roll= atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
		 Yaw = atan2(2 * (q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3)*57.3+180;                      //yaw           这里加上180是为了上机后的数值为180°
	}
}

正式因为这一句我没有注意导致我比赛开始后车子走着走着变歪了 我一开始加的是181°

现在得到的数值后就开始 进行对车身进行保持PID算法让他整场下来保持车身
下面是我用的是 位置式

void balance(int yaw)//roll(横滚角)(回复力)、角速度(阻尼力)
{
    float Balance_Kp=20,Balance_Ki=6,Balance_Kd=1.5;//kp 10 ki 5 kd 0.8 
	float Bias=0,Last_Bias=0,Sun_Bias=0; 
    Bias=yaw-ZHONGZHI;                //计算偏差  
    Sun_Bias+=Bias;   
	Pwm=Balance_Kp*Bias+Balance_Ki*Sun_Bias+Balance_Kd*(Bias-Last_Bias);  //===计算平衡控制的电机PWM  PD控制   kp是P系数 kd是D系数
	if(Pwm>690)Pwm=690;        //按比例 容忍输出整体的%9 也就是10度左右 
	if(Pwm<-690)Pwm=-690; 
    Last_Bias=Bias;
    
}

在陀螺仪中断中用到这个函数,把测量得到的 YAW放到这个函数中就能得到PWM调节量
电机虽然用的是增量式 但是陀螺仪用位置式也可以调节
把得到的PWM调节加入电机 就可以保持车身了

/***********************************************************************************
** 函数名称 :void Pid_Which(struct pid_uint *pl, struct pid_uint *pr)
** 函数功能 :pid选择函数	      
***********************************************************************************/


void Pid_A_Which(struct pid_uint *pA)
{
	/**********************A轮速度pid*************************/
	if(pA->En == 1)
	{									
		pA->Adjust = -PID_common(pA->speedSet, pA->speedNow, pA)+Pwm;		
	}	
	else
	{
		pA->Adjust = 0;
		reset_Uk(pA);
		pA->En = 2; 
	}


}   

void Pid_B_Which(struct pid_uint *pB)
{
	/***********************B轮速度pid*************************/
	if(pB->En == 1)
	{
		pB->Adjust = -PID_common(pB->speedSet, pB->speedNow, pB)-Pwm;		
	}	
	else
	{
		pB->Adjust = 0;
		reset_Uk(pB);
		pB->En = 2; 
	}


} 

void Pid_C_Which(struct pid_uint *pC)
{
	/***********************C轮速度pid*************************/
	if(pC->En == 1)
	{
		pC->Adjust = -PID_common(pC->speedSet, pC->speedNow, pC)+Pwm;		
	}	
	else
	{
		pC->Adjust = 0;
		reset_Uk(pC);
		pC->En = 2; 
	}


} 

void Pid_D_Which(struct pid_uint *pD)
{

	/***********************D轮速度pid*************************/
	if(pD->En == 1)
	{
		pD->Adjust = -PID_common(pD->speedSet, pD->speedNow, pD)-Pwm;		
	}	
	else
	{
		pD->Adjust = 0;
		reset_Uk(pD);
		pD->En = 2; 
	} 


}

总结
以上就是保持车身的过程,其中遇到了很多问题还未解决
1.车身在行走过程中会慢慢变歪一点 可能是 我的PID未调节好和用的方法不对
2.也可能是中断中放了太多函数
3.在调试过程中 我遇到了几个自己粗心的问题 已经解决 就是 初始化函数一定要有逻辑 比如延时函数一定要放在最前面 不然有些初始化过程中需要用到延迟函数 ,但是延迟函数又没有开始初始化,程序会卡死。任何函数初始化一定要遵循逻辑,不然都运行不起来。

以上是车身保持,程序就不发出来了,学过32的都可以根据那位大佬的程序修改出来
下一篇激光测距

  • 4
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据引用,2023物流是指从2020年12月开始进行程训练大,到2021年10月24日在上海嘉定体育中心进行全国总决的一个项目。这个项目持续了11个月。 根据引用,有一个关于物流的视频,可以在哔哩哔哩上找到。这个视频展示了出发前两天的小情况。 根据引用,该项目在2020年最后一天到2021年第一天通宵写代码,并且意料之外地获得了江苏省特等奖。随后,准备国时更换了mcu,重新从零开始制作。在国中,出现了任务逻辑上的错误,导致颜色搬运出错,丢失了几乎一半的比分数。但幸运的是,还是成功进入了社区。在社区中,经历了8小时的关小黑屋,通宵写任务逻辑代码。最终,取得了一定的成绩。 总结来说,2023物流是一个长达11个月的程训练大项目,其中经历了省、国和社区等多个阶段。尽管遇到了一些挑战和错误,但仍然取得了一定的成绩。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [中国大学生程实践与创新能力竞程训练大)——智慧物流搬运 ① 前言](https://blog.csdn.net/ycznjust/article/details/120960096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值