【极海 APM32M3514 电机通用评估板测评】电机驱动
本文介绍了极海 APM32M3514 电机通用评估板实现无刷电机驱动的测试流程,包括软硬件介绍、驱动原理、代码等。
1.介绍
本节介绍了无刷电机、驱动原理、软硬件配置以及关键代码。
无刷电机
无刷直流电机不使用机械的电刷装置,采用方波自控式永磁同步电机,以霍尔传感器取代碳刷换向器,以钕铁硼作为转子的永磁材料,性能上相较一般的传统直流电机有很大优势。

优点
高效率、低能耗、低噪音、低干扰、超长寿命、高可靠性、可伺服控制、无级变频调速。
缺点
价格一般比有刷电机略贵,维护较复杂,扭矩较小。
应用
广泛应用于航模、车模、精密仪器仪表等产品;洗衣机、电风扇、空调冰箱(压缩机)等家用电器;水泵、电动门、风机等工业需求;人工心脏、血液等医疗设备;滑板车、助力车、遥控车等玩具产品。
驱动原理
直流无刷电机(brushless motor)由 本体 和 换相装置 组成。

直流无刷电机的本体由定子和转子组成,将一半直流电机的电驱绕组放置于定子,将永磁体置于转子(这与传统直流永磁电机的结构相反);
换相装置由位置传感器、控制电路以及工具逻辑开关共同构成,通过改变输入到无刷电机定子线圈上的电流波交变频率和波形,在绕组线圈周围形成一个绕电机几何轴心旋转的磁场,该磁场驱动转子上的永磁磁钢转动。
无刷电子调速器是决定使用性能的关键。
2.软件
打开无感 FOC 示例工程 APM32M3514_FOC_V1.0

左侧显示工程文件夹布局,调整 parameter.h 中的参数即可实现电机驱动。
USER
- main.c:主函数入口,负责初始化电机参数、底层外设、中断优先级、while 循环及低速状态机环路的切换;
- APM32M3514_int.c:所有的中断处理函数,重点包括 TMR1 中断函数、ADC 中断处理函数;
- user_function.c:包括电机参数的初始化配置、参数复位等处理函数;
- parameter.h:包括了所有的需要配置参数信息;
HARDWARE
外设驱动层主要负责 APM32M3514 芯片的外设驱动函数及配置,主要包括 GPIO 、P WM 、ADC 、OPA 、COMP 、M0CP 协处理器等。
MOTOR_CONTROL
电机控制驱动层主要负责电机的控制运行逻辑及核心处理算法调用。
Geehy_MCLIB
电机算法层包括坐标变换、矢量控制等相关函数,数学库,滑模观测器等库函数。
3.硬件
介绍了测试所需硬件设备,包括电机供电电源、无刷电机,以及电机的相关参数。
无刷电机
测试所用无刷电机的型号为 GBM2804H-100T

尺寸

规格
| 规格 | 参数 | 规格 | 参数 |
| 型号 | GBM2804H-100T | 空载电流 (A) | 0.099 |
| 电压范围 (Lipo) | 2-4S | 轴的内径 (mm) | 5.0 |
| 线圈圈数 | 100T | 轴的直径 (mm) | 7.0 |
| 最大电流 (A) | 5 | 最大功率 (W) | 72.5 |
| 电机尺寸 | 35mm(OD)x15mm | 引线长度 (mm) | 黑色 JR 接头排线 300mm |
| 定子尺寸 | 28mm(OD)x4mm | 电机结构 | 12N14P |
| KV 值 | 147 | 堵转扭矩 N.M/V | 0.065/3S |
| 线圈内阻 (Ω) | 11.2 | 电机重量含线 | 40.8g |
电机电源
采用 12V (2A) 直流电源作为无刷电机的供电电源

4.代码
主函数代码
#include "main.h"
#include "dev_include.h"
#include "hardware.h"
#include "systick.h"
#include "user_function.h"
#include "StateMachine.h"
#include "parameter.h"
Motor_TypeDef Motor_type;
int16_t M1FaultID, M1FaultID_Record;
/*******************************************************************************
* Function Name : Interrupt_Init
* Description : Interrupt priority initialization
*
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void Interrupt_Init(void)
{
/* Configure one bit for preemption priority */
SCB->AIRCR = (uint32_t)0x05FA0500;
/* Enable the ADC Interrupt */
NVIC_EnableIRQ(ADC_COMP_IRQn);
NVIC_SetPriority(ADC_COMP_IRQn,1);
NVIC_EnableIRQ(TMR1_BRK_UP_TRG_COM_IRQn);
NVIC_SetPriority(TMR1_BRK_UP_TRG_COM_IRQn,0);
/* enable uart2 irq */
NVIC_EnableIRQ(USART2_IRQn);
NVIC_SetPriority(USART2_IRQn,2);
/* enable DMA4_5 irq */
NVIC_EnableIRQ(DMA_CH4_7_IRQn);
NVIC_SetPriority(DMA_CH4_7_IRQn,2);
NVIC_EnableIRQ(SysTick_IRQn);
NVIC_SetPriority(SysTick_IRQn,2);
TMR1->STS &= (uint16_t)0xFFFE;
TMR1->STS &= (uint16_t)0xFF7F;
}
uint8_t NewDIRKey;
int main(void)
{
__disable_irq();
/* config peripherals */
MC_SystemClockInit();
/* M0CP */
M0CP_Firmware_Init();
RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_M0CP);
RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_M0CP);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_M0CP);
M0CP_HardInit();
*(volatile unsigned int*)(0x40024000+0x10) = 0;
/* TIMER1 */
Drv_Pwm_Init(PWM_PERIOD,DEAD_TIME);
PWM_CompareConfig(PWM_PERIOD, PWM_PERIOD, PWM_PERIOD);
/* ADC */
Drv_Adc_Init();
/* OPA */
OPA_Init();
/* COMP */
COMP_Init();
/* GPIO */
IO_Init();
/* SYSTICK */
Systick_Init(SystemCoreClock / 1000);
/* Initialize motor control parameters */
Init_Parameter(&Motor_type);
/* Initialize interrupts */
Interrupt_Init();
/* Wait until ADC is ready */
while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
ADC_StartConversion();
WWDTInit();
__enable_irq(); //Enable all interrupts
TMR_EnablePWMOutputs(TMR1);
while (1)
{
//Reads key from demoboard.
NewDIRKey = GPIO_ReadInputBit(GPIOC,GPIO_PIN_13); //PC13 Direction button
if(NewDIRKey == BIT_RESET)
{
/*-------- Reverse direction -----------*/
Motor_type.User.s8NewDir = -1;
}
else{
/*-------- Forward direction ---------*/
Motor_type.User.s8NewDir = 1;
}
if(Motor_type.User.s8NewDir != Motor_type.User.s8Direction)
{
/*-------- Switch rotation direction ---------*/
Motor_type.User.bDirSwitchEnable = true;
}
if(Motor_type.User.bSlowLoopFlag)
{
WWDTFeedDog();
/* Slow Loop Statemachine */
s_STATE_SLOW[eM1_MainState]();
Motor_type.User.bSlowLoopFlag = 0;
}
}
}
参数设置
#ifndef __PARAMETER_H_
#define __PARAMETER_H_
/*System setting*/
#define SYS_REFV 3.3f // unit:v MCU VCC must be 5.0V or 3.3V
#define SYSCLK_HSE_72MHz 72000000 // unit:Hz MCU 主频
#define PWMFREQ 16000 // unit:Hz 载波频率
#define PWM_PERIOD (SYSCLK_HSE_72MHz/PWMFREQ/2)
#define DEAD_TIME (1.0f * SYSCLK_HSE_72MHz/1000000) // unit:us 死区时间
#define SLOWLOOP_FREQ 1000 // unit:Hz 慢环频率
/*Board parameter setting*/
/*Current相电流采样设置*/
#define ADC_REFV SYS_REFV
#define R_SHUNT (0.02f) // unit:ohm 相电流采样电阻
#define CURRENT_OPA_GAIN (4.86f) // unit:ohm 运放放大倍数,使用2K/10K电阻组合,结合内部耦合电阻计算得出
/*偏置1.6V,I_MAX=1.6/Gain/Rs */
/* I/Ibase *Rs*OP_Gain = (V-Voffset)/32768 * 3.3 右侧为实际电压值
IGAIN = 3.3/OP_Gain/Rs/Ibase 偏置已经被去除
*/
#define I_MAX (16.26f) // unit:A 最大相电流,此作为电流基准
#define IGAIN_Q10 (2113)
/*Voltage母线电压采样设置*/
#define UDC_MAX (69.3f) // unit:V Max DC Voltage of Hardware
#define DCBUS_OVER Q15(48.0f/UDC_MAX) //pu unit:V
#define DCBUS_UNDER Q15(10.0f/UDC_MAX) //pu unit:V
/*Vsp旋钮电压采样设置*/
#define VSP_MIN_VOL 0.5f // unit:V 旋钮最低有效电压
#define VSP_MAX_VOL 2.5f // unit:V 旋钮最高有效电压
#define VSP_MIN_AD Q15(VSP_MIN_VOL/ADC_REFV)
#define VSP_MAX_AD Q15(VSP_MAX_VOL/ADC_REFV)
/*转速控制设置*/
#define MIN_RPM 50 // unit:RPM 最低转速
#define MAX_RPM 1000 // unit:RPM 最高转速
/*软件过流保护*/
#define OC_VALUE Q15(5.0f/I_MAX) //pu unit:A 相电流软件过流保护设置值
/*速度环最大输出限制设定*/
#define SPD_PI_LIMIT (4.6f) // unit:A 速度环PI最大输出电流
#define SPD_PI_MAX Q15(SPD_PI_LIMIT/I_MAX) //pu unit:A
/*偏置电压保护设置*/
#define BIAS_OVER Q15(1.70f / SYS_REFV)
#define BIAS_UNDER Q15(1.55f / SYS_REFV)
/*fault滤波过渡时间设置*/
#define OC_TIME 10 // unit:times pwm cycles
#define UV_TIME 10 // unit:times pwm cycles
#define OV_TIME 10 // unit:times pwm cycles
#define OS_TIME 10 // unit:times pwm cycles
#define PLLERR_TIME 10 // unit:times pwm cycles
/*状态机相关设定*/
#define SPEED_TO_THETA Q15(2*SPEED_CALIBRATION*POLEPAIRS/60.0f/PWMFREQ) //2*5000*2 /60/8000 Spd转速转换到Theta角度的换算系数
/*状态切换转速阈值*/
#define STOP_TO_RUN_SPEED Q15(200.0f/SPEED_CALIBRATION) //pu unit:RPM if speed command higher this, Switch from Stop to Run state
#define OBS_MINIMUM_SPEED_RPM 300.0f //unit:RPM 开环切闭环转速设定
#define STARTUP_TO_SPIN_SPEED Q15(OBS_MINIMUM_SPEED_RPM/SPEED_CALIBRATION) //pu unit:RPM if actual speed higher this, Switch from Startup to Spin state
#define FREEWHEEL_SPEED Q15(200.0f/SPEED_CALIBRATION) //pu unit:RPM if speed command lower this, Switch to Freewheel state
/*PreCharge stage预充电*/
#define PRECHARGE_TIME 16 // unit:times pwm cycles precharge time setup
/*Align state*/
#define CUR_ALIGN Q15(0.5f/I_MAX) //pu unit:A 定位电流大小
#define CUR_DEC Q15(0.5f/I_MAX) //pu A/s : 定位电流斜坡减速度
#define CUR_INC Q15(0.5f/I_MAX) //pu A/s : 定位电流斜坡加速度
/*Startup state*/
#define CUR_STARTUP Q15(0.5f/I_MAX) //pu unit:A 开环电流大小
/*Transition State*/
#define TRANSIT_CUR_DEC Q15(3.0f/I_MAX) //pu A/s : 过渡电流斜坡减速度
#define TRANSIT_CUR_INC Q15(3.0f/I_MAX) //pu A/s : 过渡电流斜坡加速度
/*Startup开环运行状态*/
#define STARTUP_SPD_INC 500.0f // unit:RPM/s 开环运行加速度
/*run state */
#define SPIN_SPD_INC 1000.0f // unit:RPM/s 闭环运行加速度
#define SPD_DEC 1000.0f // unit:RPM/s 运行减速度
/*freewheel state */
#define FREEWHEEL_TIME 1.0f // unit:s 自由停机等待时间
/*fault state*/
#define FAULTRELEASE_TIME 3.0f // unit:s 异常停机等待时间
/*motor releated paremeter setting*/
/* Motor parameter */
#define Rs 11.2f // unit:ohm 电阻
#define Ls 0.00087f // unit:H 电感
#define POLEPAIRS 7.0f // unit:p 极对数
#define SPEED_CALIBRATION (5000.0f) // unit:rpm 转速标定
#define MAX_SPEED (MAX_RPM) // unit:rpm 电机额定转速
#define OVER_SPEED_VALUE Q15(3500.0f/SPEED_CALIBRATION)//pu unit:rpm 超速保护设定阈值
/*限制条件设定*/
#define MAX_DUTY (0.95f) // 百分比 最大调制占空比
/*电流环PI参数设定*/
#define CUR_PI_Q (15) // 15 or 10, can't select others, 15:Q15 format KP&KI, 10:Q10 format KP&KI
#define M1_IQ_KP (4000) // Q15 format KP of Q-axis Current loop
#define M1_IQ_KI (400) // Q15 format KI of Q-axis Current loop
#define M1_ID_KP (4000) // Q15 format KP of D-axis Current loop
#define M1_ID_KI (400) // Q15 format KI of D-axis Current loop
/*速度环PI参数设定*/
#define SPD_PI_Q (15) // 15 or 10, can't select others, 15:Q15 format KP&KI, 10:Q10 format KP&KI
#define M1_SPEED_KP (16384) // Q15 format KP of speed loop
#define M1_SPEED_KI (163) // Q15 format KI of speed loop
/*PLL锁相环PI参数设定*/
#define PLL_PI_Q (10) // 15 or 10, can't select others, 15:Q15 format KP&KI, 10:Q10 format KP&KI
#define M1_PLL_KP (2560) // KP of PLL
#define M1_PLL_KI (5) // KI of PLL
/*SMO滑模参数设定*/
#define SMO_ERR_MAX Q15(0.75f) // Max value of SMO error
#define SLIDE_GIAN Q15(0.5f) // Kslide gain value
#define SMO_FIFO_DEPTH 64 // 队列深度,默认设定为64
#define SPEED_BAND_UPPER_LIMIT 17 /*!<目前默认基准为16,此处为上限值设定,设置为开环切闭环转速的上限值,17/16 */
#define SPEED_BAND_LOWER_LIMIT 15 /*!<目前默认基准为16,此处为下限值设定,设置为开环切闭环转速的下限值,15/16 */
#define OBS_MINIMUM_SPEED_UNIT Q15(OBS_MINIMUM_SPEED_RPM/SPEED_CALIBRATION) //pu unit:RPM 最低观测转速切换节点
#define NB_CONSECUTIVE_TESTS 2 //unit:times pwm cycles 连续符合切换点要求
#define VARIANCE_THRESHOLD 0.03f /*!<观测速度平稳的最大可接受方差(百分比) */
#define PERCENTAGE_FACTOR_Q7 (uint16_t)(VARIANCE_THRESHOLD*128u)
/*切换过渡方式选择*/
#define SOFT_SWITCH_SPIN 1 //1:使能软切过渡 0:使能直接过渡
/*转速给定设定方式选择*/
#define SPD_SOFT_OR_KNOB 1 //0:使用软件下发转速 1:使用旋钮控制转速
/*功率转换系数*/
#define PWR_CONVERSION_FACTOR ((uint32_t)(1.732f*I_MAX*UDC_MAX))
#define STALL_ENABLE 0
#define MOTOR_VOLTAGE_CONSTANT (0.496f) /*!< Volts/kRPM */
#define SPD_TO_VOLTAGE_BEMF_GAIN (MOTOR_VOLTAGE_CONSTANT * SPEED_CALIBRATION / UDC_MAX /1000.0f)
#define SPD_TO_VOLTAGE_BEMF_GAIN_Q15 Q15(SPD_TO_VOLTAGE_BEMF_GAIN)
/*堵转检测功能相关参数*/
#define STALL_ERROR_THRESHOLD 10 //unit:ms
#define STALL_CHECK_SPD_CYCLE 10 //unit:ms 主要与加减速有关,类似设定4000RPM/s * 10ms = 40RPM 一般确保至少有10RPM以上的限制阈值
#endif
需要注意 DCBUS_UNDER额定电压、Rs内阻、Ls电感、MAX_SPEED转速等关键参数,结合实际使用的无刷电机,输入相应的配置信息。
硬件连接
将无刷电机的 U、V、W 三相电压输入端口与开发板的相应接口连接,直流供电电源与开发板的 DC+ 和 DC- 相连。

上传工程至芯片并复位,调整转速即可。
5.效果
将示例程序烧录至芯片,即可实现电机旋转、调速、方向改变等操作。
电机旋转

转速控制
通过板载旋转变阻器调整电机转速(逆时针旋转可增大转速)

正反转
通过板载拨动开关 K2 切换电机旋转方向

转动过程存在一些抖动,需要根据电机的实际运行状况进行参数微调。
6.总结
本文介绍了极海 APM32M3514 电机通用评估板实现无刷电机驱动的测试流程,包括无刷电机介绍、驱动原理、软硬件介绍、关键代码分析等。该开发板可快速实现电机驱动和控制,可作为各种电机前期调控和研发的可靠、快捷的工具。