电赛笔记电机控制

Posted 内 鬼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了电赛笔记电机控制相关的知识,希望对你有一定的参考价值。

本篇博文主要使用HAL库和CubeMX进行代码示例,毕竟电赛时间那么紧张,写STP库的时间都够CubeMX重开一局了

直流电机控制

根据电机学,直流电机转速
n = U − I R K ϕ n=\\frac{U-IR}{K\\phi} n=KϕUIR
其中U为电枢端电压,I为电枢电流,R为电枢电路总电阻,Φ为每极磁通量,K为电机结构参数

直流电动机的转速控制方法有两种

  • 励磁控制法:对励磁磁通进行控制
  • 电枢控制法:对电枢电压进行控制

励磁控制阀在低速状态下收到磁极饱和限制,在高速时受换向火花和换向器结构强度的限制,动态响应较差,因此很少使用;大多数应用场合都使用电枢电压控制法,在保证励磁恒定的情况下使用单片机或相关电子器件输出PWM来直接实现直流电动机调速

直流电机调速

直流电机的调速思路就是“力大砖飞”,在电机控制线两端加适当电压,电压越高转速越快。可以通过功率半导体器件产生恒定的电压供给电机;对于数字器件而言很难控制电压精准保持在某一模拟值,因此使用PWM进行调速。

无论是模拟方法还是数字方法,都需要使用功率半导体器件,只不过使用方式有所不同。模拟电路通过线性放大的驱动方式,输出波动小、线性好,对临近电路干扰小,但存在效率低和散热问题;而数字电路通过耦合器件发出PWM使功率器件输出方波加在电机两端,通过改变方波的占空比来实现调节电机转速,往往对临近电路存在干扰,但是更易于实现。

基于PWM调速的电路往往包含三个部分

驱动电路

一般使用晶体管或场效应管构成的半桥、全桥、三相桥电路,或直接使用护照那用的电机驱动功率IC。

常见的电机驱动芯片有L298N、ULN2003等

半桥拓扑采用推挽输出,需要保证两晶体管不同时开合

全桥拓扑又称H桥,需要确定一个死区时间,在同一时间只有两个对称的桥臂晶体管导通,绝对不能让四路晶体管同时导通

三相桥需要更严谨的时间控制,如果出现桥臂同时导通的情况很可能导致炸管

三者适用的功率逐次增大

还要注意电机两端应跨接续流二极管

隔离电路

一般来说直流电机的驱动电压都在6V及以上,而常见的MCU供电、输出电压都在3.3V-5V,因此二者之间通常需要隔离

隔离器件可以是光耦、数字隔离器等

通常由于隔离设备的驱动能力不足,还需要在输出端加入三极管、场效应管放大电路或图腾柱推挽输出电路。比较方便的解决方案是直接使用达林顿管对电机进行控制,但是需要考虑达林顿管的耐压和发热

控制电路

大多数MCU都具有PWM输出功能,高性能的MCU往往还会配备控制死区时间、可以快速调节占空比、实现多路PWM同步/反相的高级控制功能;低端MCU也往往可以通过延时程序配合GPIO输出实现不精确的PWM功能

改变占空比的基本控制方法有:

  • 定宽调频法:保持PWM占空比不变,改变输出频率
  • 定频调宽法:保持PWM频率不变,改变占空比
  • 调频调宽法:不常用,同时改变频率和占空比

基于stm32f407的HAL库实现

首先需要设置CubeMX或自己编写的外设初始化代码,配置好PSC寄存器和ARR寄存器,保证恒定的PWM频率

如果使用CubeMX只要可视化地调节选项即可;如果自己编写可以参考如下代码

htim1.Instance = TIM1; //选择定时器实例
htim1.Init.Prescaler = 0; //这里设置PSC寄存器值
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; //这里设置定时器模式
htim1.Init.Period = 65535; //这里设置ARR寄存器值
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //这里设置分频值
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //这里设置是否使能自动重装计数器

使用定时器前需要先开启PWM通道

HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_x);
//函数原型如下
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)

然后通过在应用程序内修改比较值来实现定频调宽法

__HAL_TIM_SetCompare(&htimx, TIM_CHANNEL_x, PWM_CompareValue);
//宏函数原型如下
#define __HAL_TIM_SetCompare            __HAL_TIM_SET_COMPARE
#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \\
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\\
   ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)))
//__HAL_TIM_SetCompare是老版本HAL库用法,新版本里为了统一宏函数,使用了lagency.h文件来对__HAL_TIM_SetCompare进行重定向,它和新版本的函数__HAL_TIM_SET_COMPARE等效

特别地,HAL库允许直接修改CCR来改变定时器比较值

htimx.Instance->CCRn = PWM_CompareValue;

步进电机控制

步进电机是一种将电脉冲转化为角位移的电机机构。当它收到一个脉冲信号,就会按照设定的方向转动一个固定的角度,该角度称为电机的步距角。可以通过控制脉冲个数来控制角位移量;可以通过控制脉冲频率实现步进电机的调速

步进电机的转子一般为多极分布,定子上嵌有多相星形连接的控制绕组,每输入一次电脉冲信号,转子就旋转一步。步进电机的种类很多,可大致分成:

  • 反应式
  • 永磁式
  • 混合式

还可以按相数分为单相、两相、三相三种

如果给处于错齿状态的相通电,则转子会向磁导率最大、磁阻最小的位置转动,也就是趋于齿运动

一个步进电机中往往还会加入减速装置来让其达到更高的精度,获得更高的转动力矩。

基于stm32f407的HAL库实现

首先使用CubeMX或自行编写初始化代码对外设进行配置 ,主要配置的参数如下所示

htim8.Instance = TIM8; //选择合适的定时器
htim8.Init.Prescaler = 500; //配置预分频器
htim8.Init.CounterMode = TIM_COUNTERMODE_UP; //设置计数模式
htim8.Init.Period = 2000; //配置重装载值
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

sConfigOC.Pulse = 1000; //设置预定频数

使用以下函数开启PWM输出

HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_x);

一般来说使用步进电机的基本方式是精准控制其行进步数,可以通过中断回调函数实现功能

HAL_TIM_PWM_Start_IT(&htim8, TIM_CHANNEL_1); //初始化时开启中断

HAL_TIM_PWM_Stop_IT(&htim8, TIM_CHANNEL_1); //要设置频率参数前必须关闭中断
TIM8->PSC = 71; //将目标定时器8修改为72分频
//在之后的回调函数里再次打开中断

通过定义中断回调函数即可实现步数控制功能

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM8)
	{
		if(count < 100)
		{
			count++; //计算步数
		}
		else
		{
            count = 0;
			HAL_TIM_PWM_Stop_IT(&htim8, TIM_CHANNEL_1); //再次打开中断
		}
	}
}

可以通过输出不同引脚的信号到电机控制器来控制步进电机的正反转

基于步进电机专用控制IC的实现

为了更简便、精准地控制步进电机,常使用MCU搭配专用的电机控制IC来驱动电机——TI生产的DRV8824/8825以及更为常见的A4988都可以用来驱动常见的两相步进电机。一般根据datasheet中的典型应用设计出专用于控制步进电机的模块电路来实现控制功能。除了一般的正反转外,模块还提供了步进细分功能。下面分别以DRV8825A4988步进电机驱动模块为例说明

步进电机的步进细分控制是由驱动器精确控制步进电机的相电流来实现的,细分会让电机运转更加平滑;换句话说,细分控制就是让驱动电路在输出脉冲的同时控制输出电压来实现电机的平滑启动和步进停止

  • DRV8825模块

    DRV8825是TI的集成步进电机驱动芯片。芯片内部集成了2个H桥和1/32微步进分度器,可以驱动一个双极型电机或两个直流有刷电机。输入电压范围8.2~45V,可以提供1.75A的驱动电流, 芯片在24V、25°C的工作状态下可提供2.5A的峰值电流。芯片还集成了短路、过热、欠压及交叉传导保护电路,能够检测故障状况并迅速切断H桥,从而保护电机

    适用的电机类型:DRV8825驱动电机的类型主要与电机工作电流有关,理论上工作电流小于2A的步进电机都可以驱动。基于安全考虑,芯片上不加散热片,电流最好控制在1.5A以下;如果加散热片,电流峰值可到2.5A。

    模块接线如下:

    其中需要数字、模拟部分分别接地,一般来说VMOT旁边的GND是功率地,另一个GND则是数字地。同时功率电源需要接入100uF的旁路电容来减轻对数字部分的影响

    ENABLE引脚用于控制该模块是否启用,默认该引脚拉低,模块始终启用;RESET负责复位模块;SLEEP用于控制进入低功耗睡眠模式,当不使用电机时可以下拉该引脚来将功耗降到最低;三个引脚都是低电平有效,所以正常使用时都应接VCC(数字电源)

    FAULT引脚(FLT)用于指示故障,一旦由于过电流保护或热关断,IC内部禁用H桥FET时,该引脚就会输出低电平,一般来说该引脚会在模块内部与SLEEP引脚短路,起到自动故障复位的效果

    STEP引脚用于驱动电机转动,需要输入PWM波,频率越高,电机转动越快

    DIR引脚用于控制电机转动方向,高电平正转,低电平反转

    步进电机可以对应连接1B-1A-2A-2B、2B-2A-1A-1B、1A-1B-2B-2A、2A-2B-1B-1A,主要取决于需要的转动方向,总之只要同一相的两根线接到对应相的驱动引脚即可;特别地,如果电机不能正常运行,抖动严重,有可能是驱动板没有焊接好或某一相断开或两相接错导致缺相、错相;如果步进电机没有按照正确的顺序进行连接,可能导致无法工作或转动方向异常;如果步进电机扭力不足乃至丢步,可以尝试加大DRV8825的输出电流。驱动板上一般会搭配一个精密电位器用于调节输出电流,尝试调节该电位器来获取更好的输出效果,精密电位器与输出电流限制的计算公式为:限制电流 = 电位器电压 * 2,单位A

    通过控制M0、M1、M2的接地和接VCC(数字电源),可以根据下表来实现不同精密度的步进细分控制

    M0M1M2细分类型
    LowLowLowFull step
    HighLowLow1/2 step
    LowHighLow1/4 step
    HighHighLow1/8 step
    LowLowHigh1/16 step
    HighLowHigh1/32 step
    LowHighHigh1/32 step
    HighHighHigh1/32 step
  • A4988模块

    相关控制方法与DRV8825基本一致,引脚也同理,两者最大的差别在于驱动电流和价格

    A4988价格更低,但是峰值驱动电流只有2A,内阻典型值为320Ω,最大耐压35V,所以DRV8825可以用来取代A4988,但是A4988不能取代DRV8825

舵机控制

舵机也称伺服电机、伺服驱动器,它接受一定的控制信号,输出一定的角度,适用于需要角度不断变化并可以保持的控制系统

舵机实际上是一个独立的闭环控制系统,通过其内部的机械或电路反馈控制其角度

工作过程如下:

  1. 控制器向舵机发出控制信号
  2. 内部电路判断转动方向
  3. 驱动电路控制无核心马达转动
  4. 动力通过减速齿轮传送到摆臂
  5. 位置检测器回传摆臂数据
  6. 如果未达到指定位置则继续运动,否则停止

其中位置检测器一般使用可变电阻,当舵机转动时电阻值会跟着改变,由此可以判断舵机是否达到指定位置

舵机控制方法

标准舵机由电源、地线、控制线三条连接线,电源电压通常为4-6V,一般使用5V供电即可,但是需要电源带载能力够强。控制线一般输入方波信号,周期一般为20ms(频率50Hz)即可,具体情况应查看舵机生产商的说明。通过改变方波的占空比来改变舵机的角度,舵机角度和脉冲宽度成正比

舵机一般可以提供相当强的扭力,所以可以选择大扭力舵机用在机械臂等需要高强度的地方

基于stm32f407的HAL库实现

数字舵机依靠PWM进行控制。对于180°的舵机,一般周期为20ms(频率为50Hz),脉宽为500–2500us。其中为1500us使得舵机转轮处于中间位置,即90°位置,如果在500-1500us和1500–2500us之间则分别会朝着0–90°和90–180°的方向旋转。给定固定占空比,舵机则会转到相应的角度,计算公式如下:

占 空 比 D = 1 90 ∗ 角 度 θ + 0.5 占空比D =\\frac{1}{90} *角度\\theta + 0.5 D=901θ+0.5
对应HAL库实现如下

void Servo_Control(uint16_t angle) //angle为角度值,0~180
{
	float temp;
	temp = (1.0 / 90.0) * angle + 0.5;//占空比值 = 1/9 * 角度 + 5
	__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_n, (uint16_t)temp);
}

使用下面的代码使能定时器时基单元和PWM输出

HAL_TIM_Base_Start(&htimx);
HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_n);

使用下面的代码关闭定时器时基单元和PWM输出

HAL_TIM_Base_Stop(&htimx);
HAL_TIM_PWM_Stop(&htimx, TIM_CHANNEL_n);

还可以直接通过改变CCR寄存器的值来控制舵机

TIMx->CCRn = 10;

以上是关于电赛笔记电机控制的主要内容,如果未能解决你的问题,请参考以下文章

《机电传动控制》学习笔记05-1

机电传动控制第五周学习笔记

2021年电赛F题智能送药小车(国二)开源分享

学习笔记2

Python基于OpenMV的色块自动追踪与云台控制(代码电赛可用直接上手)

Python基于OpenMV的色块自动追踪与云台控制(代码电赛可用直接上手)