【教程】用STM32 MotorControl Workbench 5.4.3(FOC电机库)从零创建一个工程,正弦波驱动联控智能24V无刷电机

16 篇文章 7 订阅
4 篇文章 1 订阅

联控智能24V无刷电机FOC5.4.3工程下载地址:百度网盘 请输入提取码

本教程采用联控智能STM32F405RG低压单电机开发板,采用的无刷电机为联控智能24V无刷电机,如下图所示。

单片机晶振大小为8MHz,驱动电机使用了3个IR2101S预驱芯片和6个IRF540N N-MOS管。

单片机的运行频率为84MHz。虽然STM32F405RG的最高运行频率是168MHz,但是可能是因为板子上滤波电容的滤波效果不好,在168MHz频率下运行程序,电机转一会自动就停了,通过调试器可以发现进入了Hard Fault。单片机的运行频率越高,对滤波电容的质量要求也就越高,尤其是VCAP 2.2μF电容,不然即使程序是正确的,也会莫名其妙进入HardFault,而且经常是刚进入一个函数,第一句话都还没执行就HardFault了。把单片机主频降至84MHz,而保持APB1时钟42MHz,APB2时钟84MHz不变,就能解决电机转一会儿就自动停下,程序卡死的问题。

另外,调试电机时,最好采用可调电压的稳压电源,这样的电源可以配置电流保护模式,比如可以配置到0.6A,这样板子的最大电流就不会超过0.6A,可以在开发过程中有效地保护电机和开发板,防止MOS管因程序问题,电流过大而烧坏。

笔者使用的电机库是5.4.3非FULL版本。注意电机库是分为FULL版本和非FULL版本的。FULL版本是完全开源的版本,在ST官网是需要申请后才能下载的(笔者就没申请通过,下载不了)。非FULL版本的代码没有完全开源,可以在ST官网直接下载,不开源的代码在工程中是一个lib库。

首先,启动MotorControl Workbench 5.4.3软件:

新建一个空白工程:

下面这些全部保持默认设置,直接点击OK:

然后选择单片机。低压板的单片机用的是STM32F405RG,但是里面却没有405的选项,所以选一个最接近的407IG:

然后,我们将转子位置检测方式设为霍尔传感器方式,对话框中的其他配置不用动:

电源供电电压检测配置:电机的额定电压为24V,板子的工作电压为2~32V(软件检测到电压不对将无法启动电机,可起到保护作用)

根据板子原理图上的分压电阻配置Bus Voltage Sensing:

联控智能板子上默认没有焊热敏电阻,所以把Temperature Sensing的勾去掉:

相电流检测电阻和运放放大倍数的配置:

板子上相电流检测电阻的大小为0.05Ω,经过运放放大5倍,然后叠加上VREF(=3.3V÷2)后,送到单片机的ADC通道上。

也就是:放大后的电压=1.65+5×放大前的电阻电压

过流保护:因为运放叠加了1.65V的VREF上去,所以把电流阈值设置为2.5V。相电流过大时自动关闭电机。

——————————————————————————————————————————————————————

接下来就比较重要了,涉及到了电机的参数。

这款电机参数:

极对数(Pole Paires)为2极对,最大转速(电机上面写了的)是3000rpm,额定电流1.8Apk,额定电压24V,相电阻Rs为1.5Ω,相电感Ls为0.6mH,反电动势B-Emf constant为4.0Vrms/krpm(Vrms是电压有效值,krpm是每分钟几千转)。

霍尔传感器的安装角度为120°(决定了霍尔值的取值范围),放置的电角度为300°。

不采用编码器,所以去掉Quadrature encoder前面的勾。

Torque和Flux的PI值的配置也很重要,这个填错了,电机能转起来但是电流会特别大!其他的保持默认即可。

电机库支持按键启动或关闭电机,但是这是用外部中断实现的,没有消抖的功能!我们取消勾选这个功能,一会儿自己实现带消抖的按键起停功能:

配置电机引脚,霍尔引脚还有串口引脚:

根据开发板原理图,配置相电流和电源电压检测用的ADC引脚:

保存工程,然后点击代码生成按钮:

选择开发工具为Keil MDK 5,然后开始生成工程:

工程生成完了,还需要RUN STM32CubeMX一下,配置系统时钟,以及按键检测引脚。

先配置启动和关闭电机的按键(PC7),带上拉电阻输入,按下时按键为低电平:

配置时钟树,系统时钟设为84MHz,APB1时钟为42MHz,APB2时钟为84MHz,避免因为板子上滤波电容的问题,单片机在高频率下运行不稳定而进入HardFault,电机转一会儿就自动停转

配置完了之后,点击GENERATE CODE生成工程,用Keil打开,改下main.c代码,加上串口打印,还有按键起停的代码。

包含stdio.h头文件:

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

重定向printf函数到串口3:

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *fp)
{
  if (fp == stdout)
  {
    if (ch == '\n')
      HAL_UART_Transmit(&huart3, (uint8_t *)"\r\n", 2, HAL_MAX_DELAY);
    else
      HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
  }
  return EOF;
}
/* USER CODE END 0 */

main函数里面加上printf打印,以及按键起停(带按键消抖)的功能:

一定要保证刚才配置电机工程的时候取消了Start/Stop Button的勾选,以免生成的代码中含有EXTI中断处理的代码,按键按一下处理两遍,按下按键后电机启动又马上停止。

还有就是,启动电机前必须要执行MC_ProgramSpeedRampMotor1,不然会出错!这个在电机库的注释里面是说了的:

  * One of the following commands must be executed before calling MC_StartMotor1():
  *
  * - MC_ProgramSpeedRampMotor1()
  * - MC_ProgramTorqueRampMotor1()
  * - MC_SetCurrentReferenceMotor1()
  *
  * Failing to do so results in an unpredictable behaviour.

  /* USER CODE BEGIN 2 */
  printf("STM32F405RG Motor\n");
  printf("SystemCoreClock=%u\n", SystemCoreClock);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7) == GPIO_PIN_RESET)
    {
      HAL_Delay(15);
      if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7) == GPIO_PIN_RESET)
      {
        if (MC_GetSTMStateMotor1() == IDLE)
        {
          printf("Motor is started!\n");
          MC_ProgramSpeedRampMotor1(200, 100);
          MC_StartMotor1();
        }
        else
        {
          printf("Motor is stopped!\n");
          MC_StopMotor1();
        }
        
        while (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7) == GPIO_PIN_RESET)
          HAL_Delay(15);
      }
    }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

编译代码,下载到板子运行。板子的供电电压为24V。(联控智能的板子上没有复位键,需要关闭电源再打开,程序才真正开始运行)

按下按键,可以发现电机可以转起来,而且可以转很久不会自动停。再次按下按键,电机才停转。

---------------------------------------------------------------------------------------------------------------------------------------------------------------

HardFault错误定位代码:

void HardFault_Handler(void)
{
 /* USER CODE BEGIN HardFault_IRQn 0 */
  uint32_t addr = 0, *mem;
  
  mem = (uint32_t *)__current_sp();
  if (mem >= (uint32_t *)0x20000000 && mem < (uint32_t *)0x20020000 - 5)
    addr = mem[5];
 /* USER CODE END HardFault_IRQn 0 */
  TSK_HardwareFaultTask();
  printf("Hard Error! addr=0x%08x\n", addr);
  
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1);
}

这个代码可以打印出出错的代码的具体位置。可以在Keil中根据Flash地址定位到出错代码所在的文件和行数。(注意这里的addr实际上是出错代码的下一行代码的位置)

不过这在本工程里面没什么用,因为电机自动停转时遇到的HardFault是硬件引起的。

  • 5
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巨大八爪鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值