版权归如下公司,禁止非授权转载:
- 北京西普阳光教育科技股份有限公司(https://www.simpleware.com.cn)
- 维周机器人科技有限公司(http://www.vejoe.com)
文章目录
【实验目的】
- 熟悉编码器的种类及其工作原理;
- 熟悉编码器的输出形式,熟悉单片机如何通过编码器的输出得到电机的旋转方向和速率;
- 掌握STM32F10xx系列微控制器上编码器的接口配置与数据采集过程;
【实验原理】
编码器(encoder)是指将某一形式的信号或数据(通常特指电机转速)通过采集、编制,转换为可以用于传输、储存的信号形式的设备。编码器按采集方式可以分为接触式编码器和非接触式编码器两种;按工作原理可以分为:光电式、磁电式和触点电刷式编码器。光电式编码器通过采集光通过码盘刻孔产生的脉冲信号的频率进行转换,磁电式编码器通过霍尔元件感应电机转动时产生的磁场变化进行转换,触点电刷式编码器直接采集触点在码盘上的位置进行转换;还可以根据其计数模式分为增量式和绝对式编码器。增量式编码器记录通过采集位移信息产生的脉冲信号,近似于“速率”的概念,绝对式编码器记录位置信息,与过程无关,近似于“路程”的概念。
本实验采用的编码器为增量式编码器,增量式编码器通常有两个输出信号,分别为A相和B相(也有的编码器有A、B、Z三相输出,有编码器只有A相输出)。每一个信号都是由方波构成的脉冲序列,A相和B相之间的相位差为90度。单片机在接收到AB相输入后,可以根据收到相位的先后顺序确定电机的转向,根据脉冲序列的频率确定电机的转速,这种解码方式称为正交解码。值得注意的是,脉冲频率与电机转速成正比关系,而其具体比例系数会和码盘孔数、减速箱齿数等有关,而转速与行驶速率也存在一个比例系数,因此通常在使用中,会根据实地测试结果直接确定一个脉冲频率与行驶速率之间的经验系数。
STM32芯片中集成了强大的定时器模块,其工作状态主要有以下几种模式:输入捕获模式、PWM输入模式、强制输出模式、输出比较模式、PWM模式、单脉冲模式、编码器接口模式、调试模式等。在本实验中需要用到的是定时器模块的编码器接口模式。当定时器工作在编码器模式下时,定时器会采集两个指定的引脚输入信号,然后通过检测输入信号的跳变沿,确定输入脉冲的频率及其相位差,从而计算出电机旋转的方向以及速率。编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在0到TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0到ARR计数,或是ARR到0计数)。所以在开始计数之前必须配置TIMx_ARR。
图1 编码器模式下的计数器操作示意图
值得注意的是,仅仅完成跳变沿检测的功能,普通IO口就能办到。而定时器模块的编码器接口模式相比于普通IO口的优势在于可以抵抗一定的噪音,如图1所示,在输入信号有毛刺的情况下,计数器依然能够正常的工作,普通IO口想要办到类似的功能则需要人为添加一系列代码。
程序流程的简要说明图如图2所示:
图2 程序流程示意图
【实验环境】
硬件设备:
1、双轮自平衡机器人。如图3所示,在平衡车背面中间安装了HC-SR04超声波测距模块。
2、ST-Link下载器(包含USB线与下载线)。如图4所示。
操作系统:
Windows7/8/10,32bit/64bit
图3 双轮自平衡机器人
图4 ST-Link下载器与下载线
软件环境:
Keil 5
【实验步骤】
第一步 配置工程环境
(1)打开已经建立好的工程模板,在新建立的工程模板中已经添加五个文件夹,分别命名为USER、HARDWARE、SYSTEM、CORE、FWLib文件夹,如图5所示。其中USER文件夹存放的是主函数,HARDWARE文件夹存放的是本实验对应的硬件设备函数,SYSTEM存放的是本课程所有实验通用的函数,CORE文件夹存放的是启动文件,FWLib文件夹存放的是底层驱动函数。
图5工程模板对应的文件夹
(2)在HARDWARE文件夹下新建两个文件,分别为encoder.c和encoder.h。分别存放编码器的函数文件和头文件,如图6所示。
图6 在HARDWARE文件夹下建立encoder.c与encoder.h文件
第二步 编写定时器函数,完成定时器的配置和启用
(3)打开程序中的encoder.c文件,首先将encoder.h文件包含进来。其次对Encoder_Init_TIM2 函数进行编写,TIM2采集的是左侧的码盘返回值,选择要使用的时钟,配置引脚,启用编码器模式并配置参数。
#include "encoder.h"
#include "stm32f10x_gpio.h"
/****************************************************************
函数功能:把TIM2初始化为编码器接口模式
入口参数:无
返回值:无
****************************************************************/
void Encoder_Init_TIM2(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//使能定时器4的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//使能PA端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM