智能车入门(非常基础)

引言

由于自己刚刚结束完第19届智能汽车校赛,又因是第一次参加这个比赛,踩了不少的坑但是觉得对自己意义还是很大的。觉得这是一个对自己提升非常大的比赛,确实学到了很多东西,虽然完赛了但是没有进入到省赛感觉挺遗憾的(还是因为自己能力不够),想的是总结一下在智能车比赛中学到的知识和更主要是记录自己的比赛经历。注意!由于我是双非院校所以校赛只是跑一个圆环道(分为直道和几个半径不同的弯道),但从报名的160多支队伍也仅有21支队伍完赛,所以本文非常非常非常基础,仅仅是向纯新手说明需要准备哪些东西,路过大佬也可以提一提建议。

总体的框架:

硬件部分

由于我没有到显示屏,所以没介绍,强烈建议搞个显示屏调试分析,对了还可以加一个无线调试模块很方便。

车模

这个车模的舵机感觉总是转向的时候有很强的阻尼感而且声音也很大,电机的转速也不是特别快,整体重量也挺重的,但是如果只是想完赛的话这个车模是足够的。如果想要更好的成绩就得换一个好的车模,在比赛的时候把玩了一下其他队伍的逐飞车模,vocal那是真的好,整个车模很轻,舵机转向很轻快,而且电机转的巨快,确实是一分钱一分货。

核心板

.核心板用的stm32h750vbt6,性能完全溢出了,可以用f4代替甚至f1都行,但是750这种芯片也有个问题就是例程非常少,出现了问题的话只能是自己去排查问题比较麻烦,而f4芯片csdn上例程较多且性能也比较强悍

驱动板

由于我驱动板买的是成品所以没有对驱动板电路进行仔细研究,具体可以搜一下资料,tb6612芯片的资料网上还是挺丰富的,强烈建议你们队里的硬件员参考实物和电路原理图动手搓出来,可以提升自己的动手能力,因为在我们学校的校赛驱动板是自制的话可以减15秒时间,非常重要,我们组就是吃了这个亏,因为我不是硬件员,所以我不细说。

主板

主板上一般用排母来制作核心板底座或屏幕底座,排公来引出引脚,还可以加一些按键,加蜂鸣器来判断特殊的元素,需要有降压模块。

传感器

我用的是龙邱的电磁传感器,主要是这个传感器和车模不是配对的,所以需要自己琢磨琢磨怎么安装到自己的车模上,安装上去后还要看看舵机转向时会不会碰到传感器固定板。

电池

需要用到两块电池,一个是供核心板供电的电池,应该7.5v就够了(我用的是驱动板引脚引出的5v2A供电,图方便酿成大祸了属于是,这个方案也可以,但是最好是独立供电),还有一块是12v电池给驱动板供电。

干簧管

干簧管很简单,在商品的详情页有很丰富的介绍。

软件部分(文末有完整工程文件)

以下的文字部分只是简单介绍原理,具体实现过程可以在工程文件里查看,由于我写的很基础,所以更加高级的算法可自行研究,工程文件里面也有cubemx的配置。

adc采集及处理

差和比算法

原理:在两个电感的情况下,当左边的电感靠近中心磁线的时候返回来的电压值会变大,所以当左边的电压值比右边的电压值大的时候判定车的姿态为靠近赛道右端需要左转。

最基本的公式为(left-right)/(left+right),我用的是基本的算法,读者可以试试更高级的算法看看有什么不同。

归一化算法

归一化的目的是把原本12位的电压值数据归一到0到100之间,使得后面调试分析会更加方便,需对每一个电感进行取最大值和最小值然后进行归一化,对称的电感传感器上的放大倍数应相同,但是我没感觉到归一化算法可以适应新的赛道(求大佬解答),因为比赛的时候起晚了没时间去赛道上提前跑,直接用的训练时候的数据跑的一样。

限幅滤波

对每一个电感给定一个最大值和一个最小值,adc数据采样过程中如果数据大于最大值或小于最小值这个数据就会被赋值为最大值或最小值。

均值滤波

例如就是把十次采集到的adc数据相加最后再除以10

中位均值滤波

原理是通过冒泡排序后得到的一个数据通过采样其中位值或者把中间的几个数据进行均值计算。

舵机及电机的控制

商家一般都会给舵机和电机的使用demo。

舵机:我用的舵机的控制时基是20ms,1.5ms是居中,0.5ms和1.5ms是向左和向右的最大角

电机:控制频率是100khz,但是这个车模的电机转速有点慢。

下面有工程文件链接,具体舵机和电机的cubemx的配置可以看最下面。

pwm很好的介绍文章:https://blog.csdn.net/as480133937/article/details/103439546?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170687804416800182769277%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170687804416800182769277&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-103439546-null-null.142^v99^pc_search_result_base6&utm_term=pwm&spm=1018.2226.3001.4187

pid控制

我用的是舵机pd控制,因为后面没有时间,且没有上坡就没有用到编码器功能。

pd控制:    pid.Output=(pid.Kp*pid.ErrorAb+pid.Kd*(pid.ErrorAb-pid.ErrorLast))

关于pd调参中的p:p很简单,不能过弯或不能及时过弯则增大p,震荡太大或过弯过早则减小p。

关于d:这个不知道咋调,过大和过小都不能减小震荡,感觉只能一个适合的值才能减小震荡,大佬可能来解答以下,由于没有弄无线调参,所以调参的时候非常痛苦。

结语

最后来说说自己踩的坑吧:

电磁传感器摆放的位置:

不能太过贴近地面,我之前就是把电磁传感器的杆子放的和地面齐平,然后在直道上跑的时候总是来回震荡的非常大,刚开始不知道是什么原因,后面把杆子抬到一定的高度后发现剧烈震荡的现象消失了,可能是贴近地面受到的电磁干扰会很大?求大佬解答。

使用串口打印时的软件设置:

使用串口打印数据的时候需打开微库

关于dma传输adc数据

当时我用dma传输adc数据的时候,dma传输的目标数组一直都是零,在debug里面复位后那一瞬间是有adc数据的,但是开始运行程序的时候数组里的数据就会瞬间变为零,就是非常奇怪,检查了非常多遍的dma和adc的配置,都是没有问题的,但就是没有数据。但adc的功能是没有问题的,我试了不用dma运输的方法去测adc的值是正常的,说明是dma运输的问题。然后请了咸鱼的一位大佬也没有,可能是数组的地址不对导致dma访问不到。但是在后来我胡乱折腾的时候,发现了原因是mpu的问题,这个问题我也不懂,反正关了这个东西后,dma就可以正常的搬运adc数据到目标数组里面了。有懂的大佬可以帮忙解答一下。

结语的结语

这是我第一个付出了很久的时间来做而且顺利完赛的比赛,如上所诉,这些只是非常基础的东西,但是对于基础不好的我来说还是弄的非常非常的久,每一件小事都弄了很久,因为基本上所有的东西都是我自己做的,所以还是有一点小小的成就感的,但还是没进西部赛还是感到很遗憾,因为以后没机会打比赛了,要准备考研了,最后希望自己越来越好吧,溜了溜了。第一次写文章,如写的不好请多多见谅。

工程文件链接:

链接:https://pan.baidu.com/s/1Eb6gyXLtTfrESkqu8CI7ng 
提取码:abcd

  • 32
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32F103智能的ADC采样Keil程序示例: ```c #include "stm32f10x.h" void ADC_Configuration(void); void GPIO_Configuration(void); int main(void) { ADC_Configuration(); GPIO_Configuration(); while(1) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 启动ADC转换 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待转换完成 uint16_t adcValue = ADC_GetConversionValue(ADC1); // 获取ADC转换结果 // 在此处处理ADC转换结果 } } void ADC_Configuration(void) { ADC_InitTypeDef ADC_InitStructure; RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 设置ADC时钟为PCLK2的6分频 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 使能ADC1时钟 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不使用外部触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; // 转换通道数量 ADC_Init(ADC1, &ADC_InitStructure); // 配置ADC1 ADC_Cmd(ADC1, ENABLE); // 使能ADC1 ADC_ResetCalibration(ADC1); // 复位校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待校准器复位完成 ADC_StartCalibration(ADC1); // 开始校准 while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成 } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 配置PA0为模拟输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入模式 GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置GPIOA } ``` 这段代码实现了初始化ADC和GPIO,并在主函数中进行了ADC的单次采样,获取结果后可以在`// 在此处处理ADC转换结果`处对采样结果进行处理。注意,在STM32中,ADC转换结果的范围为0~4095,需要根据具体应用进行换算和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值