当前位置: 首页 > article >正文

电机驱动及编码器测速(基于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 = \frac{HCLK}{(PSC+1)(ARR+1))},让f的10kHz,分频PSC=0,ARR=7199。

占空比设置:\frac{Paulse}{ARR+1},全速运行设置Paulse=7200。

1.3 驱动程序编写 

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

(2)motor.h

#ifndef _MOTOR_H
#define _MOTOR_H

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


#endif

(3)motor.c

#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

HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);

②电机装载速度

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

#ifndef __ENCODER_H__
#define __ENCODER_H__

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


#endif

 (3)Encoder.c

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

#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

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

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

uint32_t sys_tick;    
int Encoder_Left,Encoder_Right;

 添加编码器获取函数:

/*每个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多天才会溢出。 

 


http://www.kler.cn/a/293480.html

相关文章:

  • centos7上安装mysql
  • 计算机毕业设计必看必学35755flask旅游景区热度可视化平台原创定制程序,java、PHP、python、小程序、文案全套、毕设成品等
  • C语言第九周课——经典算法
  • Java复习42(PTA)
  • yolov7论文翻译
  • xrandr源码分析
  • ARM32开发——GD32F4 DMA功能查询
  • windows手工杀毒-寻找可疑进程之线程
  • 如何在Selenium中使用Chrome DevTools进行交互
  • python的sqlalchemy使用@contextmanager来定义上下文管理器
  • shell脚本编程(正则表达式与grep +awk+sed+expect详解)
  • OpenCV中的颜色映射函数
  • [pytorch] --- pytorch基础之损失函数与反向传播
  • VUE3父子组件传参
  • Requests库对session的支持
  • PHP 项目流水线部署与错误问题解决
  • U盘数据危机应对:详解文件或目录损坏无法读取的恢复之道
  • SpringMVC启动与请求处理流程解析
  • 将网页保存为PDF---不分页
  • GIT | git提交注释自动添加信息头
  • echarts动态切换数据渲染(vue3 + echarts)
  • 5G移动网络运维实验(训)室解决方案
  • 逻辑回归与线性回归的目标函数和应用场景比较
  • 坐牢第三十六天(QT)
  • iOS——Block与内存管理
  • Kafka 实战演练:创建、配置与测试 Kafka全面教程