2020年电赛坡道小车
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、小车的总体构成
- 二、原理介绍及程序实现
- 1.红外传感器
- 2.舵机的转向实现
- 3.编码器
- 4.定时器的相关配置
- 5电机控速
- 总结
前言
该文章主要是记录本人在完成2020年电赛C题的过程中所遇到的问题以及完成情况。好了,废话不多说,直接进入主题。
一、小车的总体构成
首先,小车运用红外传感器进行循迹,通过在探测到黑线后,通过检测引脚上产生的电平信号转变成具有特定脉宽的PWM,从而控制舵机转动相应的角度。通过L298N驱动电机,同时霍尔编码器记录轮子转动时产生的脉冲数,通过PID控制算法进行闭环计算,使得小车达到以一个稳定的速度运动的状态。
二、原理介绍及程序实现
1.红外传感器
由于该模块在本项目中并未采用PID循迹,应用起来相对来说比较简单。所以在此就不再做相关的描述了。
2.舵机的转向实现
这是舵机转动相应的角度所需的脉宽。 注意:这是没有保护程序的舵机,有保护程序的舵机一次能转动大约相较于前一位置的脉宽正负0.2ms,超过这个幅度,舵机可能不会进行相应的转动
上代码:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOBRCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能TIM4//初始化GPIO口GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct); //初始化GPIOB//定时器配置Time_InitStruct.TIM_Prescaler=7199; //设置分频因子Time_InitStruct.TIM_Period=199; //设置计数周期Time_InitStruct.TIM_ClockDivision=TIM_CKD_DIV1; //不分频Time_InitStruct.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInit(TIM4,&Time_InitStruct); //初始化定时器4//PWM波输出配置TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1; //选择PWM1模式TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High; //输出极性高TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//输出使能比较TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable); //TIM4定时器自动重装载使能TIM_OC4Init(TIM4,&TIM_OCInitStruct); //TIM4输出通道4配置TIM_Cmd(TIM4,ENABLE); //启动定时器
在这里,结构体的定义就没有给出了。
通过对定时器分频因子和计数周期的设置,我们可以得到定时器产生的PWM周期,即(7199+1)*(199+1)/72000000=0.02s,即产生脉冲的周期为20ms,于是我们就可以通过调节高电平的脉宽来驱动舵机转动。
TIM_SetCompare4(TIM4,5);TIM_SetCompare4(TIM4,10);TIM_SetCompare4(TIM4,15);TIM_SetCompare4(TIM4,20);TIM_SetCompare4(TIM4,25);
通过对TIM4的通道4设置比较值即可达到目的。
3.编码器
stm32的定时器自带编码器模式。接下来就讲一下编码器计数的原理,通过对单一引脚的高低电平的检测,通过对上升沿或者下降沿(当然也可以同时在上升沿和下降沿进行捕获,后文会提出)进行计数。看图:
上面两种实质上是一样的,只是采样的边沿不一样。同时精度很低。一个周期只能进行一次计数。
下面这一种结合上升沿和下降沿采样进行计数。因为同时在上升沿和下降沿计数,所以其精度会比单一边沿计数提高一倍。看图:
从图中就可清晰看出,双边沿采样的的精度比前两种提高了。
接下来讲述一种精度更高的边沿计数方法,从编码器点击分别引入A,B相至单片机定时器引脚处,其中A、B相之间会有90度的相位差,也可以参考下面附上的草图。这时候我们可以结合另一相的高低电平状态和前两种计数方法来进行计数。以此来达到精度较高的计数,我们也称之为“四倍频计数”。接下来,具体讲述其计数方法。
上图为计数的点位。
下图为具体的计数点位:
即当A相检测到为上升沿时,此时如果B相的电平状态为高电平时,编码器进行向下计数(即获取的编码器数值减一)
当A相检测到为下降沿时,如果此时B相的电平状态为低电平,编码器进行向下计数。
当B相检测到为上升沿时,如果此时A相的电平状态为低电平,编码器也进行向下计数。
当B相检测到为下降沿时,如果此时A相的电平状态为高电平,编码器一样进行向下计数。
接下来是编码器进行向上计数的四种情形:
当A相检测到为上升沿时,如果此时B相的电平状态为低电平,编码器进行向上计数。
当A相检测到为下降沿时,如果此时B相的电平状态为高电平,编码器进行向上计数。
当B相检测到为上升沿时,如果此时A相的电平状态为高电平,编码器进行向上计数。
当B相检测到位下降沿时,如果此时A相的电平状态为低电平,编码器进行向上计数。
通过外部中断对此产生中断事件,判断另一相的状态,即可完成相应的计数。当然,stm32的定时器右相应的编码器模式:
使用这个即可完成编码器模式:TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
第一个参数为完成编码器模式的定时器,第二个参数为编码器计数模式,可有以下参数可供选择
TIM_EncoderMode_TI1 在定时器的连接Tl1的引脚进行计数(即我们前文提及的A相)
TIM_EncoderMode_TI2 在定时器的连接Tl2的引脚进行计数(即我们前文提及的B相)
TIM_EncoderMode_TI12 在定时器的连接编码器的引脚进行计数(即四倍频技术)
剩下的两个参数都配置为TIM_ICPolarity_Falling即可。
4.定时器的相关配置
在这里,就假定你们具有stm32定时器相关的配置的知识了,我就具体只给出相关配置的代码了。
上代码:
TIM_TimeBaseInitTypeDef TIM_InitStruct; //定时器结构体NVIC_InitTypeDef NVIC_InitStruct; //中断结构体RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); //时钟使能 TIM_InitStruct.TIM_Prescaler=719; //分频因子TIM_InitStruct.TIM_Period=9999; //计数周期TIM_InitStruct.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式TIM_InitStruct.TIM_ClockDivision=TIM_CKD_DIV1; //时钟不分频TIM_TimeBaseInit(TIM5,&TIM_InitStruct); //定时器5初始化TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE); //定时器溢出中断配置NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断组NVIC_InitStruct.NVIC_IRQChannel=TIM5_IRQn; //中断源NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //中断使能NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;NVIC_Init(&NVIC_InitStruct);TIM_Cmd(TIM5,ENABLE);
其次控制定时器PWM输出的配置已经在舵机那一部分讲解完毕了。
定时器的部分就到此结束了。
5电机控速
通过在定时器的溢出中断中定时获取编码器的计数再通过如下PID控制进而可以完成对电机的速度控制
void TIM5_IRQHandler(void) //定时器5的中断处理函数
{if(TIM_GetITStatus(TIM5,TIM_IT_Update) != RESET) //判断定时器的溢出中断标志位{TIM_ClearITPendingBit(TIM5,TIM_IT_Update); //清除溢出中断标志位Speed_T2=(TIM2->CNT-1000); //获取编码器计数Speed_T3=(TIM3->CNT-1000);Speed=(Speed_T2+Speed_T3)/2;TIM2->CNT=1000; //恢复至初始值TIM3->CNT=1000;}Speed_Contorl(Speed,Target); //PID输出
}
PID输出,具体可看PID算法原理,该播主讲述很详细,在此我就不在过多介绍。
float MUL;motor_Pid.motor_error=target-speed;motor_Pid.motor_sum_error+=motor_Pid.motor_error;if(motor_Pid.motor_sum_error>=30000)motor_Pid.motor_sum_error=30000;MUL=motor_Pid.p*motor_Pid.motor_error+motor_Pid.i*motor_Pid.motor_sum_error+motor_Pid.d*(motor_Pid.motor_error-motor_Pid.motor_last_error);motor_Pid.motor_last_error=motor_Pid.motor_error;MUL=0.05*MUL;return MUL;
总结
分想完毕,以此记录。
2020年电赛坡道小车相关推荐
- 2020年电赛题目,命题专家们怎么看?
关注.星标公众号,直达精彩内容 赛题解析概要 01 A题: 无线运动传感器节点设计 一.命题背景说明 二.题目涉及关键知识点介绍: ① 共模抑制的概念 ② 高精度ADC设计与应用 ③ 生物信号. ...
- 2020年电赛题目,命题专家权威解析!
关注.星标公众号,直达精彩内容 来源:德州仪器TI校园计划.大学生电子设计竞赛培训网 上次发了关于电赛题目前三道题目解析的视频:2020年电赛题目,命题专家们怎么看?,这篇带来剩余的四道赛题. 04 ...
- 2020研电赛开始,Xilinx万元大奖等你来!看AI+MPsoc平台如何选?
创意有你,未来可期! 第十五届中国研究生电子设计竞赛 Xilinx赛道 开赛了! 赛灵思万元专项大奖为大赛助力! 米尔MYD-CZU3EG入选官方指定开发平台 顶尖平台, 专业培训,商业孵化, 还 ...
- 2020年电赛 LMT70介绍和题目猜测
介绍 LMT70是一个高精度的温度传感器,没有内部寄存器,使用比较简单上电就有输出,比较麻烦的就是其封装比较小还是BGA的,焊接有点困难,建议将其做成一个小模块的形式,这样到时可以根据具体的题目进行扩 ...
- 【电赛训练】放大器非线性失真研究装置 2020年电赛E题
放大器非线性失真研究装置 一.题目要求 二.方案设计 由于笔者在自己队伍中主要负责软件编程,硬件部分在此不做详细展开. 这道题本身并不困难,就是一个固定频率波形的调制和ADC-DMA方式采样加FFT运 ...
- 2020年电赛省赛题目A——无线运动传感器节点设计
无线运动传感器节点设计 题目要求 设计方案分析 心电检测模块方案 ADS1292的A/D转换计算 心电信号的处理 体表温度分析计算 运动量分析计算 无线传输模块设计 显示屏的设计 电路设计 温度模块设 ...
- 如何准备电赛?19年电赛经验总结!
关注.星标公众号,直达精彩内容 写在前面的话 最近忙着各大厂的实习面试,趁着准备简历的功夫回顾了一下19年电赛的比赛经历,总体来说还算说得过去,现在把我参加电赛的经验分享出来,希望对之后的学弟学妹们有 ...
- 电赛猜题?我觉得没用,还不如做好这些!
01 前言 大家好,我是张巧龙,转眼又到22年电赛,这个公众号上有很多同学可能都参加过电赛,有毕业的已经工作的,也有没毕业的今年要参加. 我第一次接触电赛是在大一暑期,从参加电赛到指导学生参加电赛,转 ...
- 关于21年电赛,这些一定要熟悉!
▼点击下方名片,关注公众号▼ 知识点概要 仪器仪表:小信号放大.滤波器.程控放大.频率相位测量.锁相频率合成.峰值检波测量.功率放大.A/D,D/A,FFT等. 通信高频:振荡.混频.调制解调(AM. ...
最新文章
- https协议和Http协议的区别
- php new httprequest,php安装HTTP_Request2及引用介绍(通过HTTP_Request创建微软人脸识别的群组 为例)...
- 【若依(ruoyi)】自定义layer
- 基于51的串行通讯原理及协议详解(uart)
- JavaScript总结(四)
- 不相交轮换的乘积怎么求_浅谈两种求条件极值的方法
- Raki的读paper小记:Sources of Transfer in Multilingual Named Entity Recognition
- C#调用Matlab BP神经网络预测数据
- mov和mp4格式哪个好_录音软件哪个好用?8款好用的录音软件
- Echarts地图配置
- 机器人仿真软件小汇总
- 计算机电源高频干扰,在高频开关电源设计中怎样抑制电磁干扰?
- Python实战 | 送亲戚,送长辈,“ 月饼 ”可视化大屏来帮忙。
- PL/SQL 工具远程连接Oracle数据库方法,plsql免安装oracle客户端直接配置oci实战演示
- Shader学习笔记(三)学习Shader所需的数学基础
- php固定登录账号,PHP实现会员单一账号登录
- Pytorch中的detach用法
- 罗辑思维八里庄沙龙:Cloud Native 的演进(—)--从零开始了解云原生架构
- C#实现生产者与消费者关系
- 一生的读书计划——影响中国历史进程的中国名人
热门文章
- 在select后面嵌套子查询
- qq如何好友满了删除好友后还能收到好友消息?
- Facebook Live的高可用架构
- 当在 终端 中用 npm 安装 Vant 组件库时,发生“npm ERR code ERESOLVE ;npm ERRERESOLVE could not resolve;”报错时,该怎么办?
- linux防火墙文件更改重新加载,Linux防火墙设置
- Execution failed for task ':app:mergeDebugResources'
- 铁岭专科学校计算机,铁岭师范高等专科学校计算机教师
- 印度Kudankulam核电站被攻击事件—目前已知道的信息
- matlab绘制子图怎么,MATLAB画图之多子图画法(subplot和自己确定大小位置两种方法)...
- 电脑看不了视频?这样做,可以快速解决!