1、简单易用,可快速上手
2、流畅支持300个器件或1000个焊盘以下的设计规模
3、支持简单的电路仿真
4、面向学生、老师、创客
1、全新的交互和界面
2、流畅支持超过3w器件或10w焊盘的设计规模,支持面板和外壳设计
3、更严谨的设计约束,更规范的流程
4、面向企业、更专业的用户
标准版 智能物流系统 copy
简介:该比赛是2022年”电信杯“电子设计大赛的”智能物流系统“,由华南理工大学无线电爱好者协会举办,共六个广州高校参与的比赛。 此次开源项目为一等奖作品。
开源协议: CC-BY 3.0
工程来源: 克隆自 智能物流系统
1. 基本要求
1)基本运输单元为小车。运输物体种类为4种,体积、重量不限。参赛队伍需自行划分好不同种类的物体需要运送的终点区域,可以但不限于通过按键输入等方式告知运输单元目前所运送的物体的种类。
2)运输单元在起点处等候运输物体的装载,绿灯以2hz频率闪烁。在物体装载前不允许启动。
3)物体装载后,计时开始。运输单元需沿着路上黑线的引导实现物品的配送。运输单元到达终点的停车线后停下,计时暂停,白灯以2hz频率闪烁,等待物体卸载。
4)待运送物体取下之后,计时继续。运输单元需要沿着路面上的引导线最终返回出发点,计时暂停,代表此次运送完成,并且等待下一个物体的运送。
5)重复要求1-4,完成运输单元对四种物体的运送过程。任务结束。
2. 提高要求
1)运输单元可以通过LCD/OLED屏幕显示出运输单元的状态,运输物体的种类,任务进行的时间。
2)通过摄像头模块使得运输单元实现对物体的区分。/通过语音模块告知运输单元待运送物体的种类。
3)在完成基本要求的基础上,进行多样性、实用性、创新性的开发
控制系统选用 i.MX RT1064 最小系统板作为核心控制,使用 OpenArt mini
进行搬运物体种类的识别以及小车循迹和路口的识别,对应题目要求设置一路红
外传感器检测是否放置所搬运的物体;四路编码器速度、位置闭环,陀螺仪角度
闭环;电机驱动使用 H 桥 DRV8701,外置 NMOS,驱动能力强劲;题目中白色、绿
色信号灯使用 OpenArt mini 板载 RGB 灯实现;状态、搬运种类、运行时间采用
1.3’OLED 屏显示。
因此,本设计可以轻松应对题目中对于赛道的识别、对于搬运物体种类的识
别,小车惯性导航使得运行路径准确可靠,实时显示状态和搬运种类、每次搬运
后更新所用时间
本设计采用 NXP 跨界处理器 i.MX RT1064 作为主控,底盘为四驱麦轮底盘,
四个电机均有编码器闭环控制,采用六轴陀螺仪 ICM20602 进行角度闭环控制,
循迹摄像头及识别摄像头均采用 OpenArt mini,电机驱动使用 DRV8701,物体检
测使用红外对管。
由于采用闭环控制,可实现小误差定点启停,小误差角度转向。使用 OpenArt
mini 可通过运行神经网络模型,对所搬运物体进行识别分类,故无需按键输入
搬运种类。通过惯性导航,避免了红外循迹带来的不确定性
提示:说明作品中模块的设计原理图,需要配上原理图,最好是有实物图一起,每个模块都需要说明,如不需要设计的,请说明获取来源。
提示:这里写PCB的一些设计说明,如:PCB的布局、布线、线宽、间距等设计注意事项
icm20602的互补滤波解算:
ins_update();
static float angle_last[3]={0};
float increase[3] = {0,0,0};
#ifdef pitch_roll
increase[0] = gyro_vector.x*dt;
if(fabs(increase[0])<0.02) increase[0]=0;
angle[0] = R*(angle_last[0]+increase[0])
+ (1-R)*RadtoDeg*atan(acc_vector.x/acc_vector.z);
angle_last[0] = angle[0]; //处理pitch
increase[1] = gyro_vector.y*dt;
if(fabs(increase[1])<0.0) increase[1]=0;
angle[1] = R*(angle_last[1]+increase[1])
+ (1-R)*RadtoDeg*atan(acc_vector.y/acc_vector.z);
angle_last[1] = angle[1]; //处理roll
#endif
increase[2] = -gyro_vector.z*dt;
// increase[2] = -icm_gyro_z*dt*Gyro_Gain;
if(fabs(increase[2])<0.02) increase[2]=0;
angle[2] = angle_last[2]+increase[2];
angle_last[2] = angle[2]; //处理yaw
//控制转弯角度范围在0-360°以内
if(angle_last[2]>360)
angle_last[2]-=360;
else if(angle_last[2]<0)
angle_last[2]+=360;
小车行为逻辑(只列举了一条路线):
if(Ready&&!Task_finish&&SmallClass!=0&&SmallClass!=15)
{
switch(SmallClass)
{
case 1: {sprintf(str1,"orange",SmallClass);}
case 2: {sprintf(str1,"apple",SmallClass);}
case 3: {sprintf(str1,"banana",SmallClass);}
case 4: {sprintf(str1,"grape",SmallClass);}
}
while(gpio_get(C29));
Top_camera_sendData(2);systick_delay_ms(50);
Top_camera_sendData(2);systick_delay_ms(50);
switch(SmallClass)
{
case 1:{
time_Stop = false;
oled_p8x16str(1,2,str1);
oled_p8x16str(1,0,"transit");
int distance = Centimeter_to_encoder(75);
motol_Settarget_point_move(0,distance,100);
while(!go_End);
turn_angle(90);
while(turn);
distance = Centimeter_to_encoder(55);
motol_Settarget_point_move(0,distance,100);
while(!go_End);
oled_fill(0);
oled_p8x16str(1,2,str1);
oled_p8x16str(1,0,"wait uninstall");
sprintf(str2,"time = %5d",time1);
oled_p8x16str(1,4,str2);
Top_camera_sendData(1);systick_delay_ms(50);
Top_camera_sendData(1);systick_delay_ms(50);
time_Stop = true;
while(!gpio_get(C29))
systick_delay_ms(50);
turn_angle(-90);
time_Stop = false;
Top_camera_sendData(2);systick_delay_ms(50);
Top_camera_sendData(2);systick_delay_ms(50);
oled_fill(0);
oled_p8x16str(1,4,str2);
oled_p8x16str(1,2,str1);
oled_p8x16str(1,0,"transit");
while(turn);
distance = Centimeter_to_encoder(55);
motol_Settarget_point_move(0,distance,100);
while(!go_End);
turn_angle(182);
while(turn);
distance = Centimeter_to_encoder(75);
motol_Settarget_point_move(0,distance,100);
while(!go_End);
turn_angle(0);
while(turn);
sprintf(str2,"time = %5d",time1);
oled_fill(0);
oled_p8x16str(1,2,str1);
oled_p8x16str(1,4,str2);
oled_p8x16str(1,0,"finish");
time_Stop = true;
Task_finish = true;
gpio_set(D4,0);
break;
average = (getEncoder(&left_front_pid,left_front_encoder,0)+getEncoder(&left_rear_pid,left_rear_encoder,0)+getEncoder(&right_front_pid,right_front_encoder,0)+getEncoder(&right_rear_pid,right_rear_encoder,0))/4;
position_point.x_point += average*sinf(angle_PI);
position_point.y_point += average*cosf(angle_PI);
encoder_vector[num].L_S = target_left_front_position-left_front_pid.encoder; //取出编码器值并且进行低通滤波+均值滤波
encoder_vector[num].L_X = target_left_rear_position-left_rear_pid.encoder;
encoder_vector[num].R_S = target_right_front_position-right_front_pid.encoder;
encoder_vector[num].R_X = target_right_rear_position-right_rear_pid.encoder;
L_SE = (int)LowPassFilter_apply(&low_filter_L_S,(encoder_vector[0].L_S+encoder_vector[1].L_S+encoder_vector[2].L_S)/3);
L_XE = (int)LowPassFilter_apply(&low_filter_L_X,(encoder_vector[0].L_X+encoder_vector[1].L_X+encoder_vector[2].L_X)/3);
R_SE = (int)LowPassFilter_apply(&low_filter_R_S,(encoder_vector[0].R_S+encoder_vector[1].R_S+encoder_vector[2].R_S)/3);
R_XE = (int)LowPassFilter_apply(&low_filter_R_X,(encoder_vector[0].R_X+encoder_vector[1].R_X+encoder_vector[2].R_X)/3);
//计算pid
L_S=Position_PID_bias(&left_front_pid,L_SE);
L_X=Position_PID_bias(&left_rear_pid,L_XE);
R_S=Position_PID_bias(&right_front_pid,R_SE);
R_X=Position_PID_bias(&right_rear_pid,R_XE);
//车身偏差修正
error = (angle[2]-Target_angle)*100;
if(error> 18000)
error = (angle[2]-360-Target_angle)*100;
else if(error<-18000)
error = (angle[2]+360-Target_angle)*100;
int left_front = Motolxianfu(L_S,11000);
int right_front = Motolxianfu(R_S,11000);
int left_rear = Motolxianfu(L_X,11000);
int right_rear = Motolxianfu(R_X,11000);
if(left_front<abs(error)||right_front<abs(error)||left_rear<abs(error)||right_rear<abs(error))
error = 0;
#ifdef DIR_MOTOL
if(left_front>0) {gpio_set(D0,1);}
else {gpio_set(D0,0);}
if(left_rear>0) {gpio_set(D2,1);}
else {gpio_set(D2,0);}
if(right_front<0) {gpio_set(D12,1);}
else {gpio_set(D12,0);}
if(right_rear<0) {gpio_set(D14,1);}
else {gpio_set(D14,0);}
pwm_duty(PWM1_MODULE3_CHB_D1,abs(left_front-error));
pwm_duty(PWM2_MODULE3_CHB_D3,abs(left_rear-error));
pwm_duty(PWM1_MODULE0_CHB_D13,abs(right_front+error));
pwm_duty(PWM1_MODULE1_CHB_D15,abs(right_rear+error));
展开
加载中...
是否需要添加此工程到专辑?