FOC——无刷电机的简单驱动

2023-05-16

文章目录

  • 一、什么是无刷电机?
    • 1、长什么样?
    • 2、怎么工作?
  • 二、试着让它转起来
    • 1、STM32CubeMX配置
    • 2、keil/Clion代码编写
    • 3、结果分析
  • 参考的资料

   写这个是为了记录学习过程,为了方便日后快速理解所以话比较通俗,当然也会有些许理解错误,欢迎各位大佬指正,小弟在此感激不尽

一、什么是无刷电机?

1、长什么样?

  无刷无刷,跟有刷电机的区别就是有无电刷(电刷的作用是导电换向),在有刷电机中电刷会随着使用时间的增加逐渐磨损,所以寿命受限。
  下图里面是一种无刷电机,无刷电机分两种:外转子、内转子。图中这种如果我没理解错,应该叫外转子无刷电机?应该是的(60%确定吧)。
无刷电机实物图

2、怎么工作?

  无刷电机与有刷电机不同,有刷电机是两根线(也就是一个直流电源)加合适的电压就可以转起来,而无刷电机是有三根线(A、B、C相)按照一定的规律才可以转起来
  下图可表示无刷电机的简易驱动动画(在同一时间内有两根线通的,我觉着理解为三个有刷电机的驱动,一次只用两根线,用完了再换线),如果你手速够快,手动调整通电顺序,电机也可以转起来,但是你应该做不到速度那么快,所以尝尝采用MOS管控制电路的切换
在这里插入图片描述
你需要知道怎么用右手螺旋定则判断磁场方向
  根据右手螺旋定则(手心握着那个定子,四指是电流方向,大拇指方向为产生的磁场方向),判断在不同通电时刻下通电相(A、B、C)产生的磁场方向。
右手螺旋定则
在这里插入图片描述


  无刷电机中,三相星形联结的二导通方式最为常用,这里用该模型做简单分析:
在这里插入图片描述
  当对A、B分别施加正负电压,根据上文提到的右手螺旋定则可推断出定子产生的磁极方向如下图的右边部分所示:
在这里插入图片描述
  想象一下,在上面这个图中右边产生的这个磁场中,在中心点处随便放一块磁体(有N、S极),这个磁体最终的姿态应该是什么样的? 对,就是跟右边这个一样。 因为要保证这个磁场内的磁感应线方向是统一的,所以要一样。 那么如果这个随便放的磁铁是无刷电机的转子,那么这个转子就会转到这个位置,电机也就转了起来(理论上转了一丢丢)


  接着,给A、C分别施加正负电压,分析产生的新磁场,看下图:
在这里插入图片描述
  同理可得,转子会转到上图右边那样的位置。


  继续,给B、C分别施加正负电压,分析产生的新磁场,看下图:
在这里插入图片描述
  同理可得,转子会转到上图右边那样的位置。

  依次推,可以得到6种通电状态下转子的位置角度,每个状态依次相差60度,6个过程完成了无刷电机的依次完整转动。
在这里插入图片描述

二、试着让它转起来

1、STM32CubeMX配置

  (1)新建工程:这一块老规矩,穷,所以用stm32F103C8T6这块板子了。
  (2)配置相关功能
SYS设置
在这里插入图片描述


RCC设置
在这里插入图片描述


时钟树设置
  关于时钟树这一块不清楚可看STM32基础知识(三)-- 系统时钟RCC详解这个文章。
在这里插入图片描述


定时器TIM1设置
  因为要生成PWM信号,所以用定时器方便一点。此处用的TIM1属于高级定时器,由APB2负责。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  占空比在程序中进行设置,此处不设置占空比


工程输出设置
在这里插入图片描述
在这里插入图片描述
之后点击右上角的 GENERATE CODE 生成工程文件。

2、keil/Clion代码编写

  在生成的工程文件下 MDK-ARM 文件夹中点击后缀名为“.uvprojx”的文件打开工程。打开工程后先编译(保证工程代码正确)。如果出现下图情况
在这里插入图片描述
  按照下图更改设置即可(好像是因为高级版本多了个啥,还是用老版本好一点感觉)。
在这里插入图片描述
  编译通过,0 Error,0 Warning。
在这里插入图片描述
在main.c函数中增添代码,main.c代码如下:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/***********************************************************************************************/
//按照CubeMX中设置:APB2为72MHz,Prescaler预分频系数为36-1,Counter Period(AutoReload Register)为100-1
//可计算PWM(定时器)周期为72MHz/((36-1)+1)/((100-1)+1)=20KHz,也就是PWM(定时器)周期为0.00005s=50us

//设置PWM占空比为duty%    
#define duty 10			//高电平在一个PWM中占空比为10%,换算为时间是0.000005s=5us的高电平时间

//设置(上桥臂)PWM占空比为0
#define A0 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0)
#define B0 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0)
#define C0 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0)
//设置(下桥臂)PWM占空比为10
#define A1 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,duty)
#define B1 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,duty)
#define C1 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,duty)
/***********************************************************************************************/

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
	
/***********************************************************************************************/
//开启PWM输出,输出6路PWM信号
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);
	
	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);
	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2);
	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3);
/***********************************************************************************************/

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
/***********************************************************************************************/
		A1;B0;C0;			//打开A上、B下、C下		关闭A下、B上、C上
		HAL_Delay(10);
		A0;B1;C0;			//打开A下、B上、C下		关闭A上、B下、C上
		HAL_Delay(10);
		A0;B0;C1;			//打开A下、B下、C上		关闭A上、B上、C下
		HAL_Delay(10);
/***********************************************************************************************/
		
    /* USER CODE END WHILE */

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

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

3、结果分析

  手上没有示波器,只有一个之前做的逻辑分析仪,接上stm32f103c8t6对应的6个引脚,对其进行逻辑分析,可以看出个大概。
  我这里用到的是PA8、PA9、PA10、PAB13、PB14、PB15:
在这里插入图片描述
在这里插入图片描述

  分析仪与stm32f103c8t6引脚对应关系如下:

D0——PA8
D1——PB13
D2——PA9
D3——PB14
D4——PA10
D5——PB15

按照

//按照CubeMX中设置:APB2为72MHz,Prescaler预分频系数为36-1,Counter Period(AutoReload Register)为100-1
//可计算PWM(定时器)周期为72MHz/((36-1)+1)/((100-1)+1)=20KHz,也就是PWM(定时器)周期为0.00005s=50us

//设置PWM占空比为duty%    
#define duty 10			//高电平在一个PWM中占空比为10%,换算为时间是0.000005s=5us的高电平时间

以及while中的

/***********************************************************************************************/
		A1;B0;C0;			//打开A上、B下、C下		关闭A下、B上、C上
		HAL_Delay(10);
		A0;B1;C0;			//打开A下、B上、C下		关闭A上、B下、C上
		HAL_Delay(10);
		A0;B0;C1;			//打开A下、B下、C上		关闭A上、B上、C下
		HAL_Delay(10);
/***********************************************************************************************/

中的设置,理论上一个PWM的周期为50us,PWM中高电平信号时间为50us*10%=5us。

  查看逻辑分析仪中的时间:
在这里插入图片描述
在这里插入图片描述
  对照着逻辑分析仪查看不同端口的输出电平状态:
初始时刻

/ABC
上桥臂1(PA8)0(PA9)0(PA10)
下桥臂0(PB13)1(PB14)1(PB15)

在这里插入图片描述

延迟10ms

/ABC
上桥臂0(PA8)1(PA9)0(PA10)
下桥臂1(PB13)0 (PB14)1(PB15)

在这里插入图片描述

延迟10ms

/ABC
上桥臂0(PA8)0(PA9)1(PA10)
下桥臂1(PB13)1(PB14)0(PB15)

在这里插入图片描述

参考的资料

1.有刷电机与无刷电机的区别,就是这么简单明了
2.一文看懂有刷电机与无刷电机的工作原理及区别
3.【自制FOC驱动器】深入浅出讲解FOC算法与SVPWM技术

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FOC——无刷电机的简单驱动 的相关文章

  • get请求和post请求的区别

    HTTP协议 什么是协议 xff1f 协议实际上是某些人 xff0c 或者某些组织提前制定好的一套规范 xff0c 大家都按照这个规范来 xff0c 这样可以做到沟通无障碍 协议就是一套规范 xff0c 就是一套标准 由其他人或其他组织来负
  • 常见网络协议

    网络协议为计算机网络中进行数据交换而建立的规则 标准或约定的集合 例如 xff0c 网络中一个微机用户和一个大型主机的操作员进行通信 xff0c 由于这两个数据终端所用字符集不同 xff0c 因此操作员所输入的命令彼此不认识 为了能进行通信
  • C++ 栈(stack)使用简述

    目录 1 有关函数的作用 2 测试用例 至于栈的结构与原理 xff08 先入后出 xff09 这里就不细说了 xff0c 这里主要记录下 C 43 43 的头文件 lt stack gt 有关栈的操作是如何使用的 1 有关函数的作用 sta
  • 解决一个镜像ID同时拥有多个tag的问题

    docker rmi span class token operator lt span REPOSITORY TAG span class token operator gt span

随机推荐

  • 蜂鸣器介绍

    蜂鸣器介绍 蜂鸣器是一种将电信号转换为声音信号的器件 xff0c 常用来产生设备的按键音 报警音等提示信号 蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器 有源蜂鸣器 xff1a 内部自带振荡源 xff0c 将正负极接上直流电压即可持续发声
  • DS1302时钟芯片(SPI协议)

    DS1302时钟芯片 DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片 它可以对年 月 日 周 时 分 秒进行计时 xff0c 且具有闰年补偿等多种功能 可以把该芯片看成一个小型的单片机 xff0c 其内部
  • ESP8266与单片机通信共地问题

    ESP8266与单片机通信共地问题 1 共地 xff1a 在数字电路中 xff0c 要判断一个电平信号的高低 xff0c 就需要一个标准来判断 xff0c 这个判断标准就是0电平 也叫地 xff09 xff0c 要把所有IC芯片的地连在一起
  • RS-485接口协议详解

    RS 485详解 通信协议 通讯协议主要是实现两个设备之间的数据交换功能 xff0c 通讯协议分硬件层协议和软件层协议 硬件层协议决定数据如何传输问题 xff0c 比如要在设备1向设备2发送0x63 xff0c 0x63的二进制数为0110
  • 使用阿里云IoT Studio建立物模型可视化界面

    使用阿里云IoT Studio建立物模型可视化界面 上一篇文章介绍了如何使用ESP 01S上报数据到物模型 xff1a https blog csdn net weixin 46251230 article details 12899671
  • 51单片机 简易光电循迹小车

    前言 应学校暑期课程要求 xff0c 也作为和小组成员完成一次对51单片机的练手 xff0c 制作了简易的光电小车 xff0c 完成了循迹功能 xff0c 下面包括较为详细的小车搭建过程以及完整代码 硬件部分准备 电源 可充电的电池组是智能
  • 阶段学习的总结

    当程序中存在多个对象的时候 xff0c 如何确定这些对象的析构顺序 单个对象创建时构造函数的调用顺序 调用父类的构造过程 调用成员变量的构造函数 xff08 调用顺序与声明顺序相同 xff09 调用类自身的构造函数 多个对象析构时 析构顺序
  • stm32学习笔记-1 STM32简介

    1 STM32简介 文章目录 1 STM32简介1 1 套件简介1 2 STM32芯片内部的外设1 3 STM32芯片系统结构1 4 STM32芯片引脚定义1 5 STM32最小系统 注 xff1a 笔记主要参考B站 江科大自化协 教学视频
  • Jetson Xavier NX 配置opencv3.4.5

    主要参考Jetson Xavier NX安装opencv3 x以及踩过的坑 xff0c 纪录下自己的错误 下载opencv3 4 5 链接 xff1a https pan baidu com s 17mASm87RNbgfmM 31vlxb
  • C++ 队列(queue、priority_queue)使用简述

    目录 1 queue有关函数的作用 2 priority queue 有关函数作用 3 queue 测试用例 4 priority queue 测试用例 至于队列的结构与原理 xff08 FIFO xff0c 先入先出 xff09 这里就不
  • 前端 | 数据可视化之ECharts

    文章目录 一 数据可视化1 1 什么是数据可视化1 2 数据可视化的使用场景1 3 常见可视化库1 4 小结 二 ECharts简介2 1 什么是ECharts 三 ECharts的快速入门3 1 ECharts使用五部曲3 2 选择不同类
  • Oracle数据库修改账户密码

    Oracle数据库用户密码忘记了怎么办 xff1f 1 首先需要进入cmd命令格式 xff1b 2 输入sqlplus as sysdba 超级用户角色 xff1b 3 SQL命令下输入alter user 用户名 account unlo
  • 如何让进程后台运行?(TX)

    一 运行指令 43 amp xff08 如 a out amp xff09 这样是将命令放入到一个作业队列中了 表现 xff1a 1 结果会输出到终端 2 前台出现进程号 3 使用Ctrl 43 C发送SIGINT信号 xff0c 程序免疫
  • Ubuntu20.04.2+ROS noetic打开rviz报错:...symbol lookup error...librviz.so: undefined symbol:

    打开rviz闪退 xff0c shell显示如下 xff1a 一开始我的独立显卡是安装好了的 xff0c 界面显示的OpenGL也是独显的 xff0c 但是用的其他博客的方法 xff1a span class token function
  • 计算机网络谢希仁第七版第四章习题

    4 09 xff1a xff08 1 xff09 子网掩码为 255 255 255 0 代表什么意思 xff1f xff08 2 xff09 一个网络的现在掩码为 255 255 255 248 xff0c 问该网络能够连接多少个主机 x
  • Ubuntu Linux操作系统——图形界面与命令行

    文章目录 Linux和Ubuntu命令行界面使用仿真终端窗口Shell基础正则表达式通配符模式表达式 Shell中的特殊字符 Linux命令行的使用命令行语法格式命令行基本用法命令行输入与输出执行Shell脚本vi编辑器vi操作模式打开vi
  • SDN控制器Ryu、Floodlight、OpenDayLight的安装以及Mininet连接

    文章中文件名内的xxx需要替换成自己文件的具体版本 ubuntu下安装之前可以先用 sudo apt cache madison soft name查看一下apt安装的版本 xff0c 如果版本合适的话用apt更加方便 Ryu控制器 Ryu
  • 调试时出现:undefined Expecting 'EOF','}',',',']', got STRING以下错误的解决方法

    网上查了很多跟此问题相关的答案 xff0c 都没彻底解决 xff0c 今天亲自遇到这个问题和解决方法了 xff0c 特写下来 问题描述 xff1a 代码是这样的 xff1a VM523 1 undefined Expecting EOF g
  • tensorflow详细安装过程

    我电脑安装的python是3 7 4的 xff0c 所以python如果版本不一样的话 xff08 不是3 7的 xff09 xff0c 下边的内容不建议完全参考 xff0c 可以适当参考 主要是注意很多numpy和models与你安装的t
  • FOC——无刷电机的简单驱动

    文章目录 一 什么是无刷电机 xff1f 1 长什么样 xff1f 2 怎么工作 xff1f 二 试着让它转起来1 STM32CubeMX配置2 keil Clion代码编写3 结果分析 参考的资料 写这个是为了记录学习过程 xff0c 为