使用STM32CubeMX实现增量式PID调节电机速度(霍尔编码器)

前言

趁你们不注意,我突然更!!


目录

  • 前言
  • 一、直流减速电机与霍尔编码器
  • 1.1、编码器介绍与选择
  • 1.2、编码器参数
  • 1.3、编码器测速原理
  • 1.3.1、方向判断
  • 1.3.2、速度获取
  • 二、STM32cubeMX库配置编码器模式
  • 2.1、连线分析
  • 2.2、cubeMX设置
  • 2.2.1、cubeMX初始化
  • 2.2.2、高级定时器编码器模式(CH1,CH2通道)
  • 2.2.3、串口DMA
  • 2.2.4、PWM输出
  • 2.2.5、GPIO控制电机方向
  • 2.2.5、LED
  • 2.2.6、基本定时器
  • 2.2.6、配置中断优先级
  • 三、离散PID简介
  • 3.1、位置式
  • 3.2、增量式
  • 四、代码及其讲解
  • 后记
  • 一、直流减速电机与霍尔编码器

    1.1、编码器介绍与选择

    是一种可以测量目标机械运动或者目标位置的传感器或装备,分为线性编码器和旋转编码器,我们这里测的是电机速度,很明显,电机是旋转的,所以是旋转编码器

    一般旋转编码器又有两种类型

  • 增量编码器:增量式旋转编码器在电机旋转时输出脉冲。 要使用增量编码器确定轴
    位置, 您必须知道起始位置并使用外部电路来计算输出脉冲数。
  • 绝对编码器:绝对旋转编码器输出对应于旋转角度的数字代码。 无需计算脉冲了解电
    机轴的位置。 您只需要读取编码器的数字输出。
  • 我来翻译一下,增量编码器就是通过是输出脉冲让后让单片机计数脉冲数来算速度,绝对编码器就是直接输出角度变化的数字量。

    打开淘宝搜,很明显,增量编码器占一大半儿,所以我们用增量编码器

    增量编码器还可以分:

  • 光电:我来翻译一下这张图的意思,LED灯光穿过这个码盘的孔后就会输出一个脉冲,让后单片机计数脉冲就行了,不同的码盘通常转一圈发送的脉冲数也不一样,一般是300-500个脉冲。

  • 霍尔:由霍尔开关集成传感器和磁性转盘组成, 霍尔式转速传感器结构如下图所示。 将磁性转盘的输入轴与被测转轴相连, 当被测转轴转动时, 磁性转盘便随之转动, 固定在磁性转盘附近的霍尔开关集成传感器便可在每一个小磁铁通过时产生一个相应的脉冲, 检测出单位时间的脉冲数,便可知道被测对象的转速。一般霍尔编码器的精度比较低。

  • 1.2、编码器参数

    根据题目可知,我买的是直流减速电机和霍尔编码器。
    如图

    参数表:
    红色是我买的型号,蓝色是很重要的参数。

    翻译:

  • 电压控制好,这玩意儿挺贵的,别给烧了昂。
  • 磁环式就是霍尔磁环式。
  • 精度就是每圈可以发送的脉冲数。
  • 霍尔
  • 1.3、编码器测速原理

    编码器使用的是“正交”这一原理将信号(光束)分为两个平行的,称为A和B。且他们通过编码器盘时相差90°。
    偏移后会出现这种情况

    1.3.1、方向判断

    鲁迅说过:运动是相对的。
    我们知道了A和B的输出相差90°,所以我们只要检测两个脉冲信号的相对位置就能检测出其方向

    1.3.2、速度获取

    首先知道精度CPR
    在一个规定时间 t 内单片机获取脉冲总数 Num 。
    F是一个周期测量的脉冲数,由图一个周期四个脉冲,对于32来讲,F一般是4或者2。

    速度v 就相当于

    v = (Num/(CPR*F))/t

    因为时直流减速电机,所以还得除以减速比,但是这里就先不除了。我的电机减速比为1:10。
    所以算出的v再除以10。

    二、STM32cubeMX库配置编码器模式

    2.1、连线分析

    我所购买的编码电机的连线

    我这里用的时野火的 指南者STM32F103VET6开发板。
    STM32F103的高级定时器拥有编码器功能,所以我们直接匹配高级定时器的编码器功能的引脚!
    电机驱动我们使用TB6612模块,不知道TB6612怎么用?请看这里

    所以单片机上需要设置的引脚有:
    1、高级定时器编码器模式(CH1,CH2通道)
    2、串口(调PID不要串口真的大丈夫?)
    3、通用或高级定时器的PWM输出模式
    4、两个GPIO控制电机转方向
    5、板载用来LED测试BUG
    6、基本定时器计算时间
    六色战队(不是)

    2.2、cubeMX设置

    2.2.1、cubeMX初始化

    配置RCC外部晶振

    改为72Mhz

    仿真更改

    2.2.2、高级定时器编码器模式(CH1,CH2通道)


    编码器计数有三种模式
    通道CH1计数
    通道CH2计数
    通道CH1、CH2双通道计数

    编码器A相—CH1 简称CHA
    编码器B相—CH2 简称CHB

    此处需要说一点,上图种绿框部分通道x计数模式并不是如它英文Rising Edge一样的上升沿计数的意思,而是计数模式的意思,这里算是cubeMX的小问题。

    他的真实含义是相对信号的电平计数模式。
    什么是相对信号?其实就是CHA相对CHB的的电平或者CHB相对CHA的电平。

    Rising Edge模式下CH1通道是遇到虚线出数值发生一次变化,左边为每次遇到虚线加一,右边为每次遇到虚线减一。即一个周期编码器计数两次。(Falling Edge模式加减相反)

    知道Rising Edge什么意思了,CHB的就略过了,可以直接看下图理解。

    TI1是CHA,TI2是CHB
    计数规则如下图:

    由图,TI1是一个周期CH1通道捕获两次脉冲,TI2是一个周期CH2通道捕获两次脉冲。
    TI1和TI2就是两个同时捕获,一个周期可以捕获4次脉冲
    精度更大更爽!!!
    所以我们用TI1和TI2有效边缘检测!!!

    CH1和CH2双通道捕获计数:
    由图一个周期捕获四次脉冲,所以我们得除4,也就是上面的公式中 F = 4

    2.2.3、串口DMA

    配置串口DMA的目的1是为接收速度数据调整速度,2是为了方便调BUG和参数


    2.2.4、PWM输出

    频率f = TimCLK/((PSC+1)x(ARR+1))

    占空比 = (Pulse+1)/(ARR+1)

    Pulse的值可以在代码中调
    TIMx->CCRx = N;

    2.2.5、GPIO控制电机方向

    GPIO不多说,不知道的建议先学一下32。

    2.2.5、LED


    配置LED

    2.2.6、基本定时器


    是能基本定时器,频率为200HZ,每隔5ms进入一次中断


    使能中断

    2.2.6、配置中断优先级


    配置中断优先级
    TIM3为编码器捕获
    TIM7为定时器中断

    三、离散PID简介

    PID分为位置式和增量式,位置式是普通的PID,增量式可以理解为式位置式的微分形式
    由于编程系统时离散的,所以我们用离散的PID。
    也就是说
    累加代替积分
    前后相减代表微分

    3.1、位置式

    通过直接改变输出来保证被控制量(一般为控制位置)的稳定。
    大概意思就是:
    就拿无人机来说明,当无人机距离所设定高度比较远时,电机转速变大,当无人机接近所设定位置时电机速度逐渐减小。
    公式为:

    3.2、增量式

    通过改变输出的增减来保证被控制量(一般为控制速度)的稳定
    其实就是:
    我们要控制电机的速度,不是通过直接改变PWM的值,而是改变每次PWM的增减来控制速度的稳定。
    公式为:

    这里只对PID做简要概述,具体可以看
    PID教学

    四、代码及其讲解

    生成代码后
    我们设置三个全局变量

    int Timer = 0;			//时间
    uint8_t speed = 0;		//当前PWM
    short TargetSpeed = 10; //目标速度
    

    在主函数前初始化我们的设置

    	TIM1->CCR1 = speed;           //写入PWM
    	Motor_1(GPIO_PIN_SET);		  
    	Motor_2(GPIO_PIN_RESET);	  //给电机一个电压,让他转起来!!
    
    	/*打开PWM输出*/
    	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
    	/*打开定时器中断*/
    	HAL_TIM_Base_Start_IT((TIM_HandleTypeDef *)&htim7);
    	/*开启串口DMA接收,默认DMA为循环模式,千万不要放在循环里!!*/
    	HAL_UART_Receive_DMA(&huart1,(uint8_t*)&TargetSpeed,sizeof(TargetSpeed));
    	/*打开编码器捕获*/
    	HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);
    

    我们之前设置每5ms进入一次中断
    并在中断中进行PWM输出的的计算

    /*中断回调函数*/
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	short fSpeed;
    	short ERROR;
    	static uint8_t i = 0;
     	
     	/*判断当进入定时器7中断时*/
    	if(htim->Instance == TIM7)
    	{
    		fSpeed = GetSpeed();			//获取当前速度	
    		speed += PID_Cal(fSpeed,&ERROR);//当前PWM数值加上增量式PID计算所得
    		
    		//限制PWM最大范围
    		if(speed>100)speed = 100;
    		else if(speed<1)speed = 1;
    		
    		//将PID计算后的PWM写入系统
    		SetMotorVoltageAndDirection(speed);
    
    		/* 每隔(5*100)ms打印一次速度数据 */
    		i++;
    		if(i >= 100)
    		{
    			i = 0;
    			Led_Toggle();
    			printf("速度数据为%d\n",fSpeed);
    			printf("目标速度为%d\n",TargetSpeed);
    			printf("误差为%d\n",ERROR);
    		}
    	}
    	
    	if(htim->Instance == TIM3)
    	{
    		
    	}
    }
    

    离散PID计算与速度获取控制函数

    Contral.c
    
    #include "main.h"
    #include "dma.h"
    #include "tim.h"
    #include "usart.h"
    #include "gpio.h"
    
    #include "Contral.h"
    #include <stdio.h>
    #include <math.h>
    
    /*PID参数*/
    #define kp 0.86
    #define ki 0.012
    #define kd 0.005
    
    
    /******************************
    	功能:每5ms在定时器中执行一次,
    				获取电机速度SPEED
    	返回值:电机速度SPEED
    	形参:无
    *******************************/
    short GetSpeed()
    {
    	short SPEED = 0;
    //	static short last = 0;
    	SPEED = (short)(__HAL_TIM_GET_COUNTER(&htim3)*100)/(4*16*10);
    	__HAL_TIM_SET_COUNTER(&htim3,0);
    	return SPEED;
    }
    
    
    /******************************
    	功能:每5ms在定时器中执行一次,
    				计算pwm返回值
    	返回值:电机速度SPEED
    	形参:无
    *******************************/
    short PID_Cal(short Speed,short *error)
    {
    	short Error = TargetSpeed - Speed;
    	static short Error_last = 0,Error_prev = 0;
    	short pwm_add=0;
    	*error = Error;
    	pwm_add = kp*(Error - Error_last) + ki*Error + kd*(Error-2.0f*Error_last+Error_prev);
    	
    	Error_prev = Error_last;	  	    // 保存上上次误差
      Error_last = Error;	              // 保存上次偏差
    	
    	
    	return pwm_add;
    }
    /******************************
    	功能:判断电机正反转,
    			并将计算所得的PWM数值
    			写入单片机中
    	返回值:无
    	形参:无
    *******************************/
    void SetMotorVoltageAndDirection(int Pwm)
    {
    	if(Pwm<0)
    	{
    		Motor_1(GPIO_PIN_RESET);
    		Motor_2(GPIO_PIN_SET);
    	}
    	else if(Pwm>0)
    	{
    		Motor_1(GPIO_PIN_SET);
    		Motor_2(GPIO_PIN_RESET);
    	}
    	Pwm = fabs(Pwm);
      TIM1->CCR1 = Pwm;
    }
    

    让后你就可以开心的调参了~~~~
    调参口诀:


    后记

    陈你们不注意,突然更新!!!!
    这不给一键三连????

    老样子:
    度娘网盘:https://pan.baidu.com/s/1f7Jwmn6I8JZgZ3HuCw4MLQ
    提取码:z5a4

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32CubeMX实现增量式PID调节电机速度(霍尔编码器)

    发表评论