五、单片机部分
我们的整体思路就是将任务拆分、细化。把抓取、放置,以及转盘区、粗加工区、暂存区的逻辑等进行封装,最后整合逻辑。通过编码器电机测距到达指定地点,陀螺仪调整小车偏差角度(走直)和小车转向。
将物料抓取上车
switch(state)
{
case 0://爪子打开
mission_finish = 0;
if(round_catch_high ==1)//如果在圆盘进行抓取时,爪子张到最大,方便于摄像头识别
Catch_SetCompare(20 );
else Catch_open(0);//否则正常张开即可
TB6612_up_dispose(0);
TIM_Cmd(TIM6, ENABLE);
if(round_catch_high == 0)//如果不是进行圆盘抓取则在等待一秒后进入下一个环节
{
if(TIM6_1000ms>1)
{
TIM6_1000ms = 0;
TIM6_100ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 1;
}
}
else //圆盘抓取的准备事项完成了也可以进入下个标志位了,这里写的有点乱你们看着改,反正不改也能用
state = 1;
break;
case 1://下降到位
if(round_catch_high == 0)//如果不是进行圆盘抓取
{
if(limit_switch() == 1)//如果触碰到底下的限位开关
{
Catch_open(1);//立刻抓取
TB6612_up_dispose(0);//升降梯停止运行
front_length = 0;//重新初始化底下的值,设定此点位为0点,方便后期电梯PID运算不会出错
TIM2 -> CNT=0;//清0电梯编码器的计数值
if(TIM6_100ms>5)//等待500毫秒
{
TIM6_100ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 2;//如果不是进行圆盘抓取则跳过下面两步直接跳入2
}
else TIM_Cmd(TIM6, ENABLE);
}
else TB6612_up_dispose(-16000); //向下运行
}
else//如果进行圆盘抓取
{
ZHUAZI_middle();//下降到圆盘抓取位置
if(TIM6_100ms>10)//等待1秒后进行抓取
{
Catch_open(1);//爪子抓取
TIM6_100ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 23;
}
else TIM_Cmd(TIM6, ENABLE);
}
break;
case 23://抓取完成后上升到顶部
if(TIM6_100ms>4)//此为稍微延迟让爪子抓稳
ZHUAZI_UP();
if(TIM6_100ms>8)//给400ms时间上升然后跳入下个标志位
{
TIM6_100ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 24;
}
else
TIM_Cmd(TIM6, ENABLE);
break;
case 24:
TB6612_up_dispose(0);
LobotSerialServoMove(ID1, 400, 200); //滑轨底部舵机旋转一定的角度(并未到达物料盘),防止物料盘转动打到物料
delay_ms(50);
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 2;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 2://
ZHUAZI_UP(); //继续上升到顶
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 3;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 3:
TB6612_up_dispose(0);//电梯停止运行
LobotSerialServoMove(ID2, ID2_mission, 200); //物料盘旋转到对应位置
LobotSerialServoMove(ID1, 785, 200); //爪子旋转到物料盘的对应位置
delay_ms(50);
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 4;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 4:
ZHUAZI_put(); //放置到对应的物料盘位置
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 5;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 5://放置仓库
Catch_open(0); //打开爪子防止
TB6612_up_dispose(0);//电梯停止运行
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 6;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 6://放置成功
ZHUAZI_UP();//电梯归位顶部
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 7;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 7://
TB6612_up_dispose(0);//到顶部时停止运行
LobotSerialServoMove(ID1, 100, 200); //爪子转回抓取位置
delay_ms(50);
if(TIM6_1000ms>2)
{
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
state = 8;
}
else TIM_Cmd(TIM6, ENABLE);
break;
case 8 :
mission_finish =1;//单次抓取任务结束,重置标志位以进行下次执行
break;
}
}
将物料放置到圆环上与此类似,我就不放代码啦
转盘区
到达转盘后,我们先通过识别物料,根据色块中心调整好车身距离,再去根据获取到的抓取顺序进行抓取。
void openmv_tiaozheng(void)
{
static int openmv_tiaozheng_flag = 100;
/* ---------------------------------- 爪子打开 ---------------------------------- */
Catch_SetCompare(20 );
printf("%d,%d,%d,%d\r\n",openmv_tiaozheng_flag,find_cir,R_X,R_Y);
switch(openmv_tiaozheng_flag)
{
case 100:
find_cir = 2;
{
catching = 1;
LobotSerialServoMove(ID1, 100,200); //转到正前方的位置方便识别调整
delay_ms(50);
if(TIM7_1000ms>1)
{
TIM7_1000ms = 0;
TIM7_100ms = 0;
TIM_Cmd(TIM7, DISABLE); TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
openmv_tiaozheng_flag = 0;
}
else TIM_Cmd(TIM7, ENABLE);
}
/* --------- 根据颜色顺序进行精准追踪中点,因为转盘的顺序为红绿蓝,
所以识别红色离开后检测到绿色到来就必定能锁定转盘中心的位置 --------- */
/*find_cir是识别颜色标志位,当发送识别任务函数send_mission_to_open(1)
发送给OPENMV时,如果OPENMV识别到红色,find_cir = 1,若未识别到则为2;
send_mission_to_open(X) X:1为红色 2为绿色 3为蓝色 */
case 0: //识别到红色
send_mission_to_open(1);//发送标志位让OPENMV识别红色
delay_ms(50);
/* ---------------------------- 首先识别到红色,跳入下个标志位,等待红色离开 --------------------------- */
if(find_cir == 1)
{
openmv_tiaozheng_flag = 1;
}
break;
/* ------------------------ 然后等待红色离开,红色离开后开始跳入下个标志位等待绿色进入视野 ----------------------- */
case 1: //识别到红色离开也就是识别到绿色(find_cir = 2是未识别到红色)
delay_ms(50);
if(find_cir == 2)
{
openmv_tiaozheng_flag = 2;
}
break;
/* ---------------------------- 绿色进入视野开始识别绿色并且追踪 ---------------------------- */
case 2: //识别绿色,开始追踪绿色,确定中心点
catching = 0;
send_mission_to_open(2);//开始追踪绿色
if(find_cir == 1)
{
OPENMV_YUANPANPID_CTRL();//车辆调整
if(TIM7_100ms>25)//调整两秒
{
TIM7_100ms = 0;
TIM_Cmd(TIM7, DISABLE);
openmv_tiaozheng_flag = 3;
send_mission_to_open(7);/等待更新任务
}
else TIM_Cmd(TIM7, ENABLE);
}
/* ---------------------- 若一直未识别到则一直关闭定时器等待识别两秒后跳入下个标志位 --------------------- */
else if(find_cir == 2)
TIM_Cmd(TIM7, DISABLE);
break;
/* ----------------------- 追踪完成,发送7则是不识别任何东西,等待下次更新任务 ----------------------- */
case 3:
catching = 1;//开始抓取标志位,抓取物块
send_mission_to_open(7);/等待更新任务
find_cir =2;//手动更新为2,防止出现意外。
if(TIM7_1000ms>3)//等待三秒后进入下个任务,此为防止任务过快出现BUG
{
openmv_tiaozheng_flag = 100;//重置到最开头便于下次重新调用此函数
clear_OPENMV_PID();//清空PID防止下次调用PID时有数值残留导致运行错误
clear_Encoder_PID();//清空PID防止下次调用PID时有数值残留导致运行错误
/* --------------------- first_end标志位:第一圈跑完的话此标志位置1,否则置0 -------------------- */
if(first_end == 0)// 如果第一圈未跑完,则进行第一圈的抓取任务
quanju_mission_zt = 101;
else // 如果第一圈跑完了,则进行第二圈的抓取任务
quanju_mission_zt_second = 101;
TIM_Cmd(TIM7, DISABLE); TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
TIM7_1000ms = 0;
TIM7_100ms = 0;
}
else TIM_Cmd(TIM7, ENABLE);
break;
}
}
调整好距离后,就是识别-抓取,识别-抓取。
int catch_yuanpan_finish;//catch_yuanpan_finish是抓取任务结束后置0,所以正在抓取中则置1 ;
void catch_yuanpan(void)
{
static int yuanpan_flag = 0;
switch(yuanpan_flag)
{
case 0 :
round_catch_high = 1;//圆盘抓取的点是距离地面高的位置,所以此标志位置1,方便电梯判断高度
catching = 1;//正在抓取标志位置1
LobotSerialServoMove(ID1, 100,200); //旋转底盘展开机械臂,使摄像头正对转盘上方,因为车子的垂直投影有大小限制,在行走的过程中,我们使机械臂处于收缩状态。
delay_ms(50);
Catch_SetCompare(20 );//爪子张开
if(TIM6_1000ms>2)
{
clear_Encoder_PID(); //到达转盘清除编码器计数
TIM6_1000ms = 0;
TIM_Cmd(TIM6, DISABLE);
yuanpan_flag = 1;
}
else
{
TIM_Cmd(TIM6, ENABLE);
send_mission_to_open(mission_1);//识别1号的物料颜色
}
break;
/********************识别第一种 *********************/
case 1 :
catching = 1;
catch_yuanpan_finish = 0;//catch_yuanpan_finish是抓取任务结束后置0,所以正在抓取中则置1 ;
send_mission_to_open(mission_1);//识别1号物料
ZHUAZI_middle();//爪子下降到旋转圆盘的高度
Catch_SetCompare(20 );//爪子张开
if(find_cir ==1 )//识别到对应颜色200ms以上则跳入下个标志位进行抓取
{
if(TIM6_100ms>2)
{
TIM6_100ms = 0;
TIM_Cmd(TIM6, DISABLE);
yuanpan_flag = 2;
}
else TIM_Cmd(TIM6, ENABLE);
}
else if(find_cir == 2)//没识别到则一直等待识别
{
TIM6_100ms = 0;
TIM_Cmd(TIM6, DISABLE);
}
;
break;
case 2 : //开始抓取物料
catch_to_car(mission_1);//放置到车上物料盘
if(mission_finish ==1)
{
yuanpan_flag = 3;
send_mission_to_open(mission_2);//识别2号物料
};
break;
/********************识别第一种 *********************/