24年电赛H题-自动行驶小车

  • 1、赛题回顾
  • 2、电路图设计
  • 3、系统程序设计
  • 3.1、PID设计
  • 4.2、编码器程序
  • 4、资料下载

1、赛题回顾

2024年全国大学生电子设计竞赛H题-自动行驶小车_#单片机


2024年全国大学生电子设计竞赛H题-自动行驶小车_#电赛_02


2024年全国大学生电子设计竞赛H题-自动行驶小车_#课程设计_03

2024年全国大学生电子设计竞赛H题-自动行驶小车_#自动行驶小车_04

2、电路图设计

2024年全国大学生电子设计竞赛H题-自动行驶小车_#自动行驶小车_05

3、系统程序设计

3.1、PID设计

pid_t motorA;
pid_t motorB;
pid_t angle;int left_encoder,right_encoder;
extern unsigned int Temp[2];
int A_turn,B_turn;void pid_init(pid_t *pid, uint32_t mode, float p, float i, float d)
{pid->pid_mode = mode;pid->p = p;pid->i = i;pid->d = d;
}void motor_target_set(int spe1, int spe2)
{if(spe1 >= 0){motorA_dir = 1;motorA.target = spe1;}else{motorA_dir = 0;motorA.target = -spe1;}if(spe2 >= 0){motorB_dir = 1;motorB.target = spe2;}else{motorB_dir = 0;motorB.target = -spe2;}
}void pid_cal(pid_t *pid)
{// 计算当前偏差pid->error[0] = pid->target - pid->now;// 计算输出if(pid->pid_mode == DELTA_PID)         // 增量式{pid->pout = pid->p * (pid->error[0] - pid->error[1]);pid->iout = pid->i * pid->error[0];pid->dout = pid->d * (pid->error[0] - 2 * pid->error[1] + pid->error[2]);pid->out += pid->pout + pid->iout + pid->dout;}else if(pid->pid_mode == POSITION_PID)  // 位置式{pid->pout = pid->p * pid->error[0];pid->iout += pid->i * pid->error[0];pid->dout = pid->d * (pid->error[0] - pid->error[1]);pid->out = pid->pout + pid->iout + pid->dout;}// 记录前两次偏差pid->error[2] = pid->error[1];pid->error[1] = pid->error[0];}void pid_out_limit(pid_t *pid)
{// 输出限幅if(pid->out>=MAX_DUTY)	pid->out=MAX_DUTY;if(pid->out<=-MAX_DUTY)	pid->out=-MAX_DUTY;
}void check(int target)
{if(target<0) {if(yaw_angle_int<0) yaw_angle_int=yaw_angle_int;else yaw_angle_int=yaw_angle_int-360;}else if(target>0){if(yaw_angle_int>0) yaw_angle_int=yaw_angle_int;else yaw_angle_int=yaw_angle_int+360;}
}void turn_pid(int base,int target)
{angle.now=yaw_angle_int;angle.target=target;pid_cal(&angle);motorA.now=left_encoder;motorA.target=base-angle.out;motorB.now=right_encoder;motorB.target=base+angle.out;pid_cal(&motorA);pid_cal(&motorB);pid_out_limit(&motorA);pid_out_limit(&motorB);Set_left_pwm((int)motorA.out);Set_right_pwm((int)motorB.out);}void speed_pid(int target)
{motorA.now=left_encoder;motorA.target=target;pid_cal(&motorA);motorB.now=right_encoder;motorB.target=target;pid_cal(&motorB);Set_left_pwm((int)motorA.out);Set_right_pwm((int)motorB.out);
}void track_pid(int temp)
{motorA.error[0]=temp;motorB.error[0]=temp;pid_cal(&motorA);pid_cal(&motorB);
}

4.2、编码器程序

//读取编码器计数值
int read_encoder1(void)
{int num;num = Encoder_count1; //读取计数值Encoder_count1 = 0;   //计数值清零return num;
}int read_encoder2(void)
{int num;num = Encoder_count2; //读取计数值Encoder_count2 = 0;   //计数值清零return num;
}// 外部中断
void GROUP1_IRQHandler(void)//Group1的中断服务函数
{if(GPIOA->CPU_INT.MIS & DL_GPIO_PIN_12) // PA12外部中断   A上升沿{if(gpio_get(GPIOA, DL_GPIO_PIN_13)==0)       //B 逻辑低{Encoder_count1 ++;}else{Encoder_count1 --;}GPIOA->CPU_INT.ICLR |= DL_GPIO_PIN_12; // 清除中断标志位}if(GPIOA->CPU_INT.MIS & DL_GPIO_PIN_13) // PA13外部中断   B相下降沿{if(gpio_get(GPIOA, DL_GPIO_PIN_12)==0)   // A 逻辑低{Encoder_count1 ++;}else{Encoder_count1 --;}GPIOA->CPU_INT.ICLR |= DL_GPIO_PIN_13; // 清除中断标志位}if(GPIOA->CPU_INT.MIS & DL_GPIO_PIN_24) // PA24外部中断   A相上升沿{if(gpio_get(GPIOA, DL_GPIO_PIN_15)==0)      	//B逻辑低{Encoder_count2 ++;}else{Encoder_count2 --;}GPIOA->CPU_INT.ICLR |= DL_GPIO_PIN_24; // 清除中断标志位}if(GPIOA->CPU_INT.MIS & DL_GPIO_PIN_15) // PA15外部中断   B相下降沿{if(gpio_get(GPIOA, DL_GPIO_PIN_24)==0)    //A逻辑低{Encoder_count2 ++;}else{Encoder_count2 --;}GPIOA->CPU_INT.ICLR |= DL_GPIO_PIN_15; // 清除中断标志位}if(GPIOA->CPU_INT.MIS & DL_GPIO_PIN_17) // PA14外部中断{delay_ms(10);mode++;set=0;mode = (mode + 1) % 5;GPIOA->CPU_INT.ICLR |= DL_GPIO_PIN_17; // 清除中断标志位}if(GPIOA->CPU_INT.MIS & DL_GPIO_PIN_27) // PA14外部中断{delay_ms(10);set = (set + 1) % 2;GPIOA->CPU_INT.ICLR |= DL_GPIO_PIN_27; // 清除中断标志位}
}