直流电机编码器测速

编码器(直接了解怎么接线)

电机转动的时候编码器通过编码电机的A相和B相输出两个正交的方波,对电机进行测速和识别电机的方向。AIN1 AIN2 BIN1 BIN2引脚控制正反转,PWM引脚控制占空比;AO1、BO1接电机的正极,AO2、BO2接电机的负极。

让电机转起来,只用设置AIN1、AIN2和PWMA

生成一个1khz的PWM波,启动NVIC。抢占优先级设置为1,1ms一个周期。

AIN1和AIN2设置为GPIO输出模式

直接写一个函数放在main.c里。

初始化定时器,启动定时器和PWM

在while里直接调用moto()函数,设置CCR占空比的值,再用value获取CCR的值显示在OLED上面

OK,电机完美的转起来了

接下来就是编码器测速了

1、编码器概述

将角位移或者角速度转换成一连串点数字脉冲的旋转式传感器

2、单片机如何采集编码器数据

测量A相和B相的上升沿和下降沿,A相或者B相的方波频率就可以得到旋转  速度,方向要看AB两相;可以通过A相上升沿的时候判断B相是什么电平,低电平就是正转(CNT自增)。ARR一般设置为65535,PSC直接给0,不分频。

3、编码器接口(Encode Interface)

可以接受增量的 (正交)编码器的信号,根据旋转编码器旋转产生的正交信号脉冲,自动控制CNT自增和自减,从而只是编码器的位置、旋转方向和旋转速度。两个输入引脚借用了输入捕获的通道一和通道二。编码器接口就相当于一个带方向控制的外部时钟。

4、四倍频技术

开启了两个通道技术,就是倍频技术的四倍频。

比较不幸运的是,电机的编码器坏了,可以正常转动但是编码器芯片一上电就烫。通过用示波器测AB相的波形,和万用表测AB两相转动电机得出,编码器是真的坏了,不过让我也更加深刻了解了这个电机。

cubemx设置

A、B两相是输出了方波,定时器的编码器接口可以获取电机的旋转位移和方向。在cubemx里直接设置Combined Channels为Enconder Mode,PSC不分频,设置为0,ARR就设置为65535。

后面再设置一个100ms定时中断一次读取TIM4编码器模式记录的脉冲值TIM1,PSC设置为720-1,ARR设置为10000-1,打开NVIC中的TIM1 update interrupt。)(好像给10ms电机有点受不了)

还有一个PWM波设置,我用TIM2的CH2生成了一个1khz的PWM波,在Channel2里选择PWMGeneration CH2,PSC为72-1,ARR为1000-1,NVIC启动全局中断。PWM设置同上。

代码部分

main.c

/* USER CODE BEGIN 2 */
	
	HAL_TIM_Base_Start_IT(&htim1);//以中断方式启动定时器1
	HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_1);//通道一,启动生成PWM
	
	HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);//开启TIM2编码器模式
	
	HAL_TIM_Base_Start_IT(&htim3);//开启TIM3的定时器中断
	__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,200);//设置CCR的值
	
	OLED_Init();
	OLED_Clear();
	OLED_Init();
	
	OLED_ShowString(1,1,"com:");
	OLED_ShowString(2,1,"cnt:");
	OLED_ShowString(3,1,"speed:");
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	moto(0);//正转
	value=__HAL_TIM_GetCompare(&htim1,TIM_CHANNEL_1);
	OLED_ShowString(1,1,"com:");
	OLED_ShowString(2,1,"cnt:");
	OLED_ShowString(3,1,"speed:");
	OLED_ShowNum(1,5,value,4);
	OLED_ShowNum(2,5,encoder_counter,5);//在特定位置显示脉冲数
	OLED_ShowFNum(4,1,n,4,2);//在特定位置显示4位整数+2位小数的电机转速
	  
//	  cnt=(short)__HAL_TIM_GET_COUNTER(&htim2);  //单独用这一行就可以得到编码器的计数值	  
//	  OLED_ShowNum(2,5,cnt,5);
  }
  /* USER CODE END 3 */

enconder.c(这里面就是获得编码器的计数值和中断回调计算速度的函数,之前直接在中断回调函数里调用OLED显示函数回乱显示,然后我就把显示全放到主函数里了)


#include "enconder.h"
#include "tim.h"

extern float  n;//转速,单位为:转/秒
extern int16_t encoder_counter;//STM32编码器模式读取的总脉冲数

/**
 * @function: void GET_NUM(void)
 * @description: 使用STM32编码器模式,读取编码器产生的脉冲值
 * @param {*} 
 * @return {*}
 */
void GET_NUM(void)
{
	encoder_counter=(short) __HAL_TIM_GET_COUNTER(&htim2);
	__HAL_TIM_SET_COUNTER(&htim2,0);
}

/**
 * @function:void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 * @description: 定时器中断回调函数,0.1S中断一次并计算转速,将电机转速以及编码器产生的脉冲数显示在OLED屏上
 * @param {TIM_HandleTypeDef *htim} 
 * @return {*}
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim==&htim3)
	{
		 GET_NUM();//得到所记录的脉冲数
//		 OLED_ShowNum(2,5,encoder_counter,5);//在特定位置显示脉冲数
		 n=(float)encoder_counter/60000/0.1;//转速为n,r/s。CNT/(t0*60000)
		 //编码器单圈500脉冲,减速后单圈为15000脉冲每圈,可以通过stm32编码器模式4倍频至60000脉冲每圈。定时器中断是10ms执行一次
//		 OLED_ShowFNum(4,1,n,4,2);//在特定位置显示4位整数+2位小数的电机转速
	}
}

enconder.h

#ifndef ENCODER_ENCODER_H_
#define ENCODER_ENCODER_H_

#include "stm32f1xx_hal.h" //HAL库文件声明
#include <main.h>
#include "OLED.h"

extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim2;

void GET_NUM(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

#endif /* ENCODER_ENCODER_H_ */

遇到的问题

开始获取编码器的脉冲计数,电机一圈转下来先是正数,再是负数。本来正常转一圈应该是60000的,我觉得这个计数有问题。

OLED显示函数里使用signednum传数。

总结

总的来说编码器测数,就是先用一个定时器生成PWM波,然后另一个定时器用来计数,捕获A、B相的脉冲。知道脉冲以后,再使用一个定时器来计算当前电机的速度,编码器的计数就相当于电机的位移,定时的时间就是时间,速度就等于位移除以时间。

下面是我打算做平衡小车的引脚配置,跟上面文章里的不一样。放这方便我后面写闭环。

STM32

TB6612

电机接口

OLED

蓝牙模块

MPU6050

PB12

AIN1

PB13

AIN2

PA8

PWMA(TIM1_CH1)

PA15

BIN1

PA12

BIN2

PA11

PWMB(TIM1_CH4)

                       

AO1

M+

AO2

M-

BO1

M+

BO2

M-

PA0

A相(motor1)(TIM2_CH1)

PA1

B相(motor1)(TIM2_CH2)

PB6

A相(motor2)(TIM4_CH1)

PB7

B相(motor2)(TIM4_CH2)

PA4

SCL

PA5

SDA

PA9

RXD(uart1_rx)

PA10

TXD(uart1_tx)

PB10

SDA(I2C2—SCL)

PB11

SCL(I2C2—SDA)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值