1.Basic requirements
1 ) The basic transportation unit is a trolley. There are 4 types of transported objects , with no limit on volume and weight. Participating teams need to divide the end areas where different types of objects need to be transported. They can, but are not limited to, inform the transport unit of the types of objects currently transported through key input and other methods.
2 ) The transport unit waits for loading of transport objects at the starting point, and the green light flashes at a frequency of 2hz . Startup is not allowed until the object is loaded.
3 ) After the object is loaded, the timing starts. The transport unit needs to be guided along the black lines on the road to deliver items. The transport unit stops after reaching the parking line at the end point, the timer is paused, and the white light flashes at a frequency of 2hz , waiting for the object to be unloaded.
4 ) After the transported object is removed, the timing continues. The transport unit needs to follow the guide line on the road and finally return to the starting point. The timer is paused, which means the delivery is completed, and it is waiting for the delivery of the next object.
5 ) Repeat requirements 1-4 to complete the transportation process of the four objects by the transportation unit. The mission is over.
2. Raise requirements
1 ) The transportation unit can display the status of the transportation unit, the type of transportation object, and the time of the task through the LCD/OLED screen.
2 ) The camera module enables the transport unit to distinguish objects. / Inform the transport unit of the type of objects to be transported through the voice module.
3 ) On the basis of completing the basic requirements, carry out diversified, practical and innovative development
The control system uses the i.MX RT1064 minimum system board as the core control. OpenArt mini is used
to identify the types of objects being transported, as well as the tracking and intersections of the car. Corresponding to the question requirements, one
infrared to detect whether the transported objects are placed; four channels Encoder speed and position closed loop, gyroscope angle
closed loop; motor driver uses H-bridge DRV8701, external NMOS, strong driving capability; the white and
green are implemented using OpenArt mini onboard RGB lights; status, handling type, running time Adopts
1.3' OLED screen display.
Therefore, this design can easily cope with
the identification . The inertial navigation of the car makes the running path accurate and reliable, and displays the status and type of transportation in real time,
as well as the time spent after each transportation.
This design uses the NXP cross-border processor i.MX RT1064 as the main control. The chassis is a four-wheel drive wheat wheel chassis.
All four motors have encoder closed-loop control. A six-axis gyroscope ICM20602 is used for angle closed-loop control,
tracking camera and recognition. The cameras all use OpenArt mini, the motor driver uses DRV8701, and the object
detection uses infrared tubes.
Due to the closed-loop control, small error fixed point start and stop, small error angle steering can be achieved. OpenArt
mini can run the neural network model to identify and classify the objects being transported, so there is no need to press keys to enter
the type of transportation. Through inertial navigation, the uncertainty caused by infrared tracking is avoided
Tips: The design schematic diagram of the module in the work needs to be accompanied by a schematic diagram, preferably with a physical diagram. Each module needs to be explained. If no design is required, please indicate the source of acquisition.
Tip: Write some design instructions for PCB here, such as: PCB layout, wiring, line width, spacing and other design considerations
Complementary filtering solution of 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;
Car behavior logic (only one route is listed):
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));
All reference designs on this site are sourced from major semiconductor manufacturers or collected online for learning and research. The copyright belongs to the semiconductor manufacturer or the original author. If you believe that the reference design of this site infringes upon your relevant rights and interests, please send us a rights notice. As a neutral platform service provider, we will take measures to delete the relevant content in accordance with relevant laws after receiving the relevant notice from the rights holder. Please send relevant notifications to email: bbs_service@eeworld.com.cn.
It is your responsibility to test the circuit yourself and determine its suitability for you. EEWorld will not be liable for direct, indirect, special, incidental, consequential or punitive damages arising from any cause or anything connected to any reference design used.
Supported by EEWorld Datasheet