电机驱动及编码器测速(基于STM32F103C8T6HAL库)

硬件:STM32F103C8T6、电机驱动模块tb6612、25GA370带编码器测速盘直流减速电机。

1.电机驱动

1.1 电机驱动模块tb6612

(1)电机驱动模块tb6612简介

电机驱动需要使用电机驱动模块,电机驱动模块把3.3V的电机信号转换成12V的电机的驱动信号。

上面两个驱动模块主要区别是橙色部分的钽电容,红色驱动模块耐压值16V,除以1.5为工作电压等于10.6V;黑色模块耐压值35V,除以1.5还有23.3V。因此红色模块驱动12V电机可能有一定概率导致钽电容损坏,可以自己更换一个电容,如果不换也可以直接剪掉,这个模块也能使用,只是不能滤波了,效果差一些。

钽电容耐压值_钽电容耐压值代码-CSDN博客

(2)电机驱动模块tb6612使用

stm32学习探究:利用TB6612驱动直流电机-CSDN博客

1.2 硬件电路及引脚配置

(1)硬件电路

(2)HAL库引脚配置

两个电机(平衡小车左右两个电机):PA11和PA8使用定时器生成PWM波 ,使用定时器来生成;PB12~PB15用来控制电机方向

PWM频率:,让f的10kHz,分频PSC=0,ARR=7199。

占空比设置:,全速运行设置Paulse=7200。

1.3 驱动程序编写

(1)创建motor.c和motor.h文件

(2)motor.h

cpp 复制代码
#ifndef _MOTOR_H
#define _MOTOR_H

#include "stm32f1xx_hal.h"
void Load(int moto1,int moto2);    


#endif

(3)motor.c

cpp 复制代码
#include "motor.h"

extern TIM_HandleTypeDef htim1;


/*取绝对值函数*/
int abs(int p)
{
	if(p>0)
		return p;
	else
		return -p;
}

/*电机加载函数*/
void Load(int moto1,int moto2)			//-7200~7200,参数表示左右两个电机转速(占空比),100%为7200
{
	if(moto1<0)
	{
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);       //一高一低电机才能转动
	}
	else
	{
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
	}
	__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,abs(moto1));         //加载占空比
	if(moto2<0)
	{
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
	}
	__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,abs(moto2));
}

(3)main.c

①打开 PWM

cpp 复制代码
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);

②电机装载速度

cpp 复制代码
Load(-1000,1000);

这款电机满转速330,设置为1000时候转速大概为46转每分钟。

CN1反接(AO1接AM2,AO2接AM1), CN2正接(BO1接BM1,BO2接BM2);因为两个电机左右对称,为了方便程序的编写,其中一个反接时候才能向前。

2.编码器测速

这一节要在上一节的基础上进行。

编码器计数原理与电机测速原理------多图解析 - 知乎 (zhihu.com)

减速比1:30的意思是我们的电机主轴转1圈的话,编码器磁环的轴转30圈。如果电机主轴转1圈的话,输出330个脉冲。

2.1 引脚配置

编码器引脚必须是PA0和PA1、PB6和PB7。

时钟来源是编码器,本事就不是特别快,所以不需要再进行分频。

编码器原理就是统计一段时间内的脉冲信号个数,然后换算到1s下对应脉冲信号个数,就是相应频率。

选择这种模式,A相和B相只要有上升沿都会触发 计数器里面+1,所以比只选择T1或者T2,计数值是快1倍的,这样才小转速情况下也可以读到较大值。

2.2 驱动编写

(1)添加encoder.c和encoder.h

(2)Encoder.h

cpp 复制代码
#ifndef __ENCODER_H__
#define __ENCODER_H__

#include "stm32f1xx_hal.h"
int Read_Speed(TIM_HandleTypeDef *htim);


#endif

(3)Encoder.c

stm32中编码器模式读出"负数"的问题_为什么stm32读取编码电机数值为负值-CSDN博客

cpp 复制代码
#include "encoder.h"


int Read_Speed(TIM_HandleTypeDef *htim)
{
	int temp;
	temp=(short)__HAL_TIM_GetCounter(htim);   //读取编码器的值,这里一定要用short进行转换,因为我们的计数器是16位的,向下计数,-1对应65535,不进行转换会出错
	__HAL_TIM_SetCounter(htim,0);             //定时器寄存器清零
	return temp;
}

(4)main.c

cpp 复制代码
HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);        //初始化定时器编码器功能
HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_ALL);

我们10ms获得一次编码器值,为了获得准确得时间,使用系统滴答定时器获得编码器值:

cpp 复制代码
uint32_t sys_tick;    
int Encoder_Left,Encoder_Right;

添加编码器获取函数:

cpp 复制代码
/*每个10ms读取一次编码器值*/
void Read(void)
{
	if(uwTick-sys_tick<10)           //uwTick是一个全局变量,默认情况下每个1ms递增一次
		return;
	sys_tick=uwTick;                 //sys_tick和uwTick之间值刚好相差10时更新sys_tick的值,然后读取编码器值
	Encoder_Left=Read_Speed(&htim2);
	Encoder_Right=-Read_Speed(&htim4);    //和电机原因一样
}

关于 uwTick:

uwTick从0加到满能够使用40多天才会溢出。

相关推荐
GalaxySinCos1 小时前
09 51单片机之LED点阵屏
单片机·嵌入式硬件·51单片机
针不戳202209262 小时前
PFC是什么
嵌入式硬件·学习·硬件工程
点灯小铭2 小时前
基于51单片机射频RFID卡考勤上课上班人数计数系统设计
单片机·嵌入式硬件·毕业设计·51单片机·课程设计
苏格拉真没有底3 小时前
MCU 软件断点注意事项!!!
单片机·嵌入式硬件
Shang131130487914 小时前
THCV215一种高速视频数据收发器,采用低电压差分信号(LVDS)技术支持高速串行数据传输,支持1080p/60Hz高分辨率传输
单片机·嵌入式硬件·高速视频收发器·thcv215·高速视频数据收发器
ShiMetaPi8 小时前
紫光同创Logos2+RK3568JHF开发板:国产异构计算平台的破局者
嵌入式硬件·fpga开发·鸿蒙系统·树莓派
No0d1es13 小时前
202506 电子学会青少年等级考试机器人五级器人理论真题
单片机·嵌入式硬件·青少年编程·机器人·电子学会·五级·理论综合
范纹杉想快点毕业15 小时前
C 语言主控开发与显控开发能力体系及技术栈详解,STM32、QT、嵌入式、边缘系统显示
stm32·单片机·tcp/ip·microsoft·fpga开发·51单片机·wpf
不会先思考16 小时前
C5.3:发射极偏置和LED驱动电路
嵌入式硬件·模拟电路·三极管·发射极偏置电路·bjt
LJWWD17 小时前
AI小智单片机esps32-s3烧录教程
单片机·嵌入式硬件