STM32F103校内赛-自动车

        根据赛题自动车的要求,自动车需要电磁巡线,陀螺仪越障。主要是难点就是这两个,其他的就是C语言逻辑上的问题。当时还是比较编程序的能力还是比较菜,感觉很难,现在觉得还好。回归正题,当时首先解决最难的问题,就是电磁巡线,需要学习PID算法,这个后面详细介绍,但是我们只需要使用PID算法中的P就可以解决电磁巡线问题。简单的来说,使用当前的值减去过去的值,这个误差值乘一个Kp,得到的值加在车的左右速度上。

一、电磁巡线

        我们使用四路电感,两横两竖,之前也尝试过三路电感,但是三路电感在我们的车上效果不太行,而且四路电感比较简单,遇到直角弯,竖电感起作用控制转向,而且遇到环岛时多次调试也可以调出很好的效果。理论上是可以使用四路电感进出环岛的,而且我之前也是不调任何参数进出环岛的,车走的路径也是很丝滑,不过好景不长,第二天就BBQ了,很怪,我现在觉得是当时电磁的电流和车的电量等等很多不可控因素。最后的解决办法只能是当中间两个横电感数值变为原来的接近两倍,就执行左后速度不同的延时函数,有时候STM32F103的延时时间还不一样,应该是和电池的电量有一定的关系。

        对了,电磁巡线是需要使用32F1的ADC通道,采值需要滤波,但是学长交了我们好多种滤波方式,给了我们一个可以直接用的代码,后来我在此基础上学习了归化处理,归化处理就是把值的范围缩小到了0~100,这样ADC值就不会波动那么大了,倒是也不错。但是在我车上的效果不太行,我觉得是我当时比较菜吧。

先来解释一下ADC采值滤波算法,代码如下。

void ADC_init()
{
    ADC_InitTypeDef ADC_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;
​
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE);
        
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;       //添加口   需要修改的地方
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);  
    
    ADC_DeInit(ADC1);
    
    ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;                 //独立模式
    ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;                  //不开启扫描
    ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;               //数据右对齐
    ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;   //触发软件
    ADC_InitStruct.ADC_NbrOfChannel=3;                              //ADC的通道数目   着重注意一下需要修改
    ADC_InitStruct.ADC_ScanConvMode=DISABLE;
    
    ADC_Init(ADC1,&ADC_InitStruct);
    ADC_Cmd(ADC1,ENABLE);
        
    ADC_ResetCalibration(ADC1);                 //重置指定的ADC的校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC1));  //等待上一步操作完成
    ADC_StartCalibration(ADC1);                 //开始制定ADC的校准状态      
    while(ADC_GetCalibrationStatus(ADC1));       //等待上一步操作完成 
}
​
//获取ADC通道的数据
u16 Get_ADC(u8 ch)
{ 
    ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);  //开始采集 采集哪个口
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);
    while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}
​
//软件滤波
#define N 12
u16 Get_ADC_Average(u8 ch)
{
    u32 temp_value=0;
    u8 t;
    for(t=0;t<10;t++)   //滤波10次,可以修改
    {
        temp_value+=Get_ADC(ch);
    }
    return temp_value/10;  //滤波10次,可以修改
}

      我使用四路电感电磁巡线为例,代码如下。

int adc1=0,adc2=0,adc3=0,adc4=0; //adc赋值0 
int ad_VAL1=0,ad_VAL2=0,ad_VAL3=0,ad_VAL4=0;  //归一化前adc的值
double Kp1=2.15;     //竖电感Kp
double Kp2=2.5;     //横电感Kp
int ErrorA,ErrorB;  //竖电感,横电感
int Error1,Error2;  //竖电感之差,橫电感之差
​
int  AD_val_1_min=0;
int  AD_val_1_max=3800;
int  flag=1;
extern int c;
extern int  red_flage;
extern int  blue_flage;
void xunji()
{
    adc1=Get_ADC_Average(ADC_Channel_0);  //右竖电感 adc1
    adc2=Get_ADC_Average(ADC_Channel_1);  //右横电感 adc2
    adc3=Get_ADC_Average(ADC_Channel_2);  //左横电感 adc3
    adc4=Get_ADC_Average(ADC_Channel_3);  //左竖电感 adc4
    
    if(adc1 >AD_val_1_max)  //限adc1最大值
    {
         adc1 =AD_val_1_max;
    }
    if(adc2 >AD_val_1_max)  //限adc2最大值
    {
         adc2 =AD_val_1_max;
    }
    if(adc3 >AD_val_1_max)  //限adc3最大值
    {
         adc3 =AD_val_1_max;
    }
    if(adc4 >AD_val_1_max)  //限adc4最大值
    {
         adc4 =AD_val_1_max;
    }
    
    Error1 = adc1-adc4;  //竖电感值之差
    Error2 = adc2-adc3;  //横电感值之差
    ErrorA = Error1*Kp1; //竖电感*Kp1
    ErrorB = Error2*Kp2; //横电感*Kp2
​
    left_front (750+ErrorA+ErrorB);  //左前轮
    front_right(700-ErrorA-ErrorB);  //右前轮
    beh_left   (750+ErrorA+ErrorB);  //左后轮
    beh_right  (700-ErrorA-ErrorB);  //右后轮
​
//归一化算法
    ad_VAL1=100*(adc1 - AD_val_1_min)/(AD_val_1_max-AD_val_1_min);  //归一化后adc1的值
    ad_VAL2=100*(adc2 - AD_val_1_min)/(AD_val_1_max-AD_val_1_min);  //归一化后adc2的值
    ad_VAL3=100*(adc3 - AD_val_1_min)/(AD_val_1_max-AD_val_1_min);  //归一化后adc3的值
    ad_VAL4=100*(adc4 - AD_val_1_min)/(AD_val_1_max-AD_val_1_min);  //归一化后adc4的值
   
        if(adc2>2700 &&ad_VAL2>71 && flag==1&&red_flage==1)  //右进环岛1 右转 左轮加速
        {
            left_front  (900);
            front_right (0);
            beh_left    (900);
            beh_right   (0);
            delay_ms(1500);
            flag=2;
​
        }
        if(adc3>2500 &&ad_VAL3>65 && flag==1&&blue_flage==1)  //左进环岛1 左转 右轮加速
        {
            left_front  (-100);
            front_right (700);
            beh_left    (-100);
            beh_right   (700);
            delay_ms(1500);
            delay_ms(1100);
            flag=2;
        }
        if(flag==2&&adc2>2700 &&ad_VAL2>71&&c==1) //出环岛条件
        {flag=3;}   
        if(flag==2&&adc3>2500 &&ad_VAL2>65&&c==1) //出环岛条件
        {flag=3;}
}

        陀螺仪在我们比赛的难度不是很大,当时还没有搞清楚难点的时候就是用陀螺仪加延时函数就调好了,后来学长看了,教了我们一下,我们主要是用俯仰角和偏航角,横滚角应该是没变化的,所以需要定义这两个角度的误差值和PID中的Kp,然后再加几个if条件和标志位,就可以完成自动车任务了。自动车的功能大概就这么多,其实也很简单。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能电磁车在直角弯道行驶的代码通常涉及路径规划、电机控制和车辆动态模型的结合。以下是一个简化版的概述: 1. **环境感知与路径规划**: - 使用传感器(如超声波、摄像头或激光雷达)获取当前车辆的位置和周围障碍物的信息。 - 应用算法(如A*、Dijkstra或RRT)计算出从当前位置到目标点的最优路径,特别是处理直角转弯部分。 ```python def plan_path(current_pos, target_pos): # 在这里实现路径规划算法 path = calculate_trajectory(current_pos, target_pos) return path ``` 2. **车辆模型**: - 建立车辆运动模型,考虑电机力矩、轮子直径、摩擦系数等因素。 - 利用车辆动力学方程(例如双轴模型或四轮独立驱动模型)计算所需电机转速。 ```python def calculate_motor_speeds(path, vehicle_params): # 在这里实现车辆动力学计算 motor_speeds = calculate_from_vehicle_model(path, vehicle_params) return motor_speeds ``` 3. **电机控制**: - 根据计算出的电机速度控制电磁铁,调整磁场强度来驱动车辆转弯。 ```python def control_motors(motor_speeds, electromagnetic_coils): # 控制电磁铁,根据电机速度调整磁场 control_coils(emagnetic_coils, motor_speeds) ``` 4. **实时更新与反馈**: - 在实际运行中,持续监控车辆状态,并根据实时反馈调整路径规划和电机控制。 ```python def main_loop(): while True: current_pos = get_current_position() # 获取当前位置 path = plan_path(current_pos, target_pos) # 计划路径 motor_speeds = calculate_motor_speeds(path, vehicle_params) # 计算电机速度 apply_motors(motor_speeds) # 执行电机控制 check_performance() # 评估性能并调整策略 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值