目录
概述
1 理论介绍
2 实现原理
2.1 旋转式编码器原理
2.2 系统实现框图
2.3 测速原理
2.4 计算速度值
3 STM32Cube配置项目
3.1 软件版本信息
3.2 配置项目
4 代码实现
4.1 电机速度控制
4.2 速度计算函数
4.3 功能实现
5 测试
概述
本文主要介绍测试电机速度方法(T测试方法)的实现原理与功能实现,笔者使用STM32F103芯片作为主控,并使用光电编码器作为测速装置,基于定时器和PWM实现电机速度测试和速度控制功能。还应该STM32Cube搭建项目实现测速的功能。
1 理论介绍
T 法:又叫做周期测量法。这种方法是建立一个已知频率的高频脉冲并对其计数,计数时间由捕获到的编码器相邻两个脉冲的间隔时间 T 决定,计数值为 M1。设编码器单圈总脉冲数为 C,高频脉冲的频率为 F0,则转速 n 的计算公式为:
公式中的参数介绍:
C: 编码器单圈总脉冲数
F0: 高频脉冲频率
M1: 编码器相邻两个脉冲的间隔时间计数
从公式可以看出,在电机高转速的时候,编码器脉冲间隔时间 TE 很小,使得测量周期内的高频脉冲计数值 M1 也变得很少,导致测量误差变大,而在低转速时, TE 足够大,测量周期内的 M1 也足够多,所以 T 法和 M 法刚好相反,更适合测量低速。
2 实现原理
2.1 旋转式编码器原理
旋转编码器内部大都由码盘、光电检测装置和信号处理电路等部分构成。码盘上刻了若干圈线槽,线槽等距并且可透光,当码盘旋转时就会周期性的透过和遮挡来自光电检测装置的光线,这样检测装置就会周期性的生成若干电信号。但是这些电信号通常比较微弱,需要加入一套处理电路对信号进行放大和整形,最后把信号整形为脉冲信号并向外输出。
旋转式编码器的原理示例图:
2.2 系统实现框图
系统使用STM32F103作为主控芯片,TIMER-8定时器用于产生两路PWM信号驱动电机;使用IO 输入中断捕捉编码器的脉冲信号;TIMER-7产生高频信号用于统计两个编码器脉冲之间的高频脉冲个数。
2.3 测速原理
参数介绍:
M0: 两个编码器脉冲之间的时间间隔
F0: 高频脉冲的个数
测速原理描述:
Step-1: 当M0上升沿时开启F0的计数
Step-2: 当M0第二次发生上升沿中断时,停止计数
2.4 计算速度值
已知参数:
轮胎直径(R): 6.8 (cm)
码盘细分数(一个周长):20个间隔
一个M0时间内测试到F0的:CNT
F0的周期为: T(us)
计算公式如下:
V = (R/20)/(T*CNT)(cm/s)
3 STM32Cube配置项目
3.1 软件版本信息
软件名称 | 版本信息 |
---|---|
STM32Cube | STM32CubeMX 6.11 |
STM32 HAL | STM32Cube_FW_F1_V1.8.5 |
3.2 配置项目
1)配置编码器IO,使能输入IO中断( External interrupt )
2)配置定时器计数中断,中断间隔时间为10us ( MCU系统工作时间为72M)
3)定时器Timer-8产生PWM,其周期为10ms
Timer-8的参数:
PWM的参数:
配置参数完成后,就可以生成项目代码:
4 代码实现
4.1 电机速度控制
通过改变PWM的占空比来调整电机的转速,具体实现代码如下:
void pwm_ctrl_Init( void )
{HAL_TIM_Base_Stop( &htim8 );HAL_TIM_PWM_Start( &htim8, TIM_CHANNEL_1); // PC6 HAL_TIM_PWM_Start( &htim8, TIM_CHANNEL_2); // PC7HAL_TIM_SetPWM_Pulse( 1500, TIM_CHANNEL_1);HAL_TIM_SetPWM_Pulse( 0, TIM_CHANNEL_2);
}
4.2 速度计算函数
通过第二章节的原理可知,码盘间隔、轮胎直径、测试定时器频率已知。根据这些参数就能计算电机的转速。
#define PI 3.14159
#define R 6.8 // unit: cm
#define DIV_CNT 20
#define CYCLE_TIME 20 // us
#define CYC_INTEV ((PI*R)/DIV_CNT) //cm
#define PARA CYC_INTEV*(1000000/CYCLE_TIME)#if 1#define pr_debug(fmt, args...) printf("DEBUG: " fmt, ##args)
#else#define pr_debug(fmt, args...)
#endifstatic uint32_t mfreq_cnt = 0;
static bool enable_cnt = false;float calculate_speeds( uint32_t cnt )
{float speeds;speeds = PARA/cnt;pr_debug("run count: %d, speeds: %0.3f cm/s\r\n", cnt, speeds);return speeds;
}
4.3 功能实现
代码48行: 重新EXTI中断函数
代码52行: 判断码盘的脉冲
代码56行: 记录第一次的脉冲位置
代码62行: 记录第二次的脉冲位置
代码63行: 禁止计数
代码64行: 计算速度
代码71行:定时器计数函数,该函数被HAL_TIM_PeriodElapsedCallback调用
源代码:
#define PI 3.14159
#define R 6.8 // unit: cm
#define DIV_CNT 20
#define CYCLE_TIME 20 // us
#define CYC_INTEV ((PI*R)/DIV_CNT) //cm
#define PARA CYC_INTEV*(1000000/CYCLE_TIME)#if 1#define pr_debug(fmt, args...) printf("DEBUG: " fmt, ##args)
#else#define pr_debug(fmt, args...)
#endifstatic uint32_t mfreq_cnt = 0;
static bool enable_cnt = false;float calculate_speeds( uint32_t cnt )
{float speeds;speeds = PARA/cnt;pr_debug("run count: %d, speeds: %0.3f cm/s\r\n", cnt, speeds);return speeds;
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{static uint16_t trg_cn = 0;if( GPIO_Pin == INPUT_TRIGGER_Pin){switch( trg_cn ){default:case 0:mfreq_cnt = 0;trg_cn = 1;enable_cnt = true;break;case 1:enable_cnt = false;calculate_speeds(mfreq_cnt);trg_cn = 0;break;}}
}void HAL_TimerCnt( void )
{if( enable_cnt ){mfreq_cnt++;}
}
5 测试
1)测试1
电机转速控制PWM 占空比配置为:1500/10000。测试得到的速度如下:
2)测试2
电机转速控制PWM 占空比配置为:5000/10000。测试得到的速度如下: