提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
无刷电机控制技术,按照是否按照编码器,可以分为“有感控制”和“无感控制”
有感控制,既电机需要安装编码器,通过编码器获取转子实时位置(如霍尔传感器、磁编码器、光电编码器)
相对应的为无感控制,无感电机控制不需要编码器,位置数据通过其他方法获取,如HFI高频注入、无感隆伯格观测器、高阶滑膜观测器、拓展卡尔曼滤波等
相对于无感控制,有感控制由于需要安装编码器,所以成本较高,但算法难度更低(无感控制依赖于数学体系,且需要扎实的自动控制理论),抗干扰性更强,更适合入行者接触
前一段时间,做了一个小的FOC云台,FOC控制的一个重要前提,是获取当前电机转子的电角度,这样才能生成对应的矢量,经过一番思索,决定选用MT6701磁编码器
(网上大多数FOC教程,使用的是AS5600,如simplefoc系列,其实也可以,但MT6701允许的极限转速要比AS5600高很多,且数据的输出方式更多样)
一、MT6701芯片简介
MT6701高速磁性角度编码器IC是麦歌恩微电子推出的新一代基于差分水平霍尔磁感应原理的角度位置传感器芯片,支持I2C, SSI, ABZ,UVW, 模拟电压、PWM以及Z轴按压检测等多种输出方式。
MT6701芯片特性:
1、3.3V~5.0V工作电压,内置EEPROM(烧写时需要保证VDD>4.5V);
2、独立输出接口: : I2C, SSI, ABZ,UVW, 模拟电压、PWM以及Z轴按压检测;
3、支持*高转速55,000 转/分钟;
4、基于霍尔技术,0~360°*对角度位置检测;
由于MT6701在各方面均领先于AS5600,所以这次选择使用他
二、MT6701安装
1.硬件连接
为了使用方便,我参照MT6701数据手册,自己画了一个传感器连接板,与电机孔距一致(拼夕夕也有相似的板子,但连接方式略有不同),后面我会单独做一期文章,分享这块电路板的原理图和PCB,大家下载后,打板焊接即可使用。
注意:
1.电机尾部需要安装径向磁铁,且安装完成后,磁铁与芯片间距不能大于2mm(紧紧贴合但不接触,芯片与磁铁必须在同一条轴线上)
安装完成后的样子:
2.与MCU连接
传感器底板的原理图如下:
通讯接口通过XH2.54-6P接口引出,我们将其与CH32开发板连接:
+5V、GND---------连接5V供电
MISO----------------PA6
SCK------------------PA5
CS--------------------PA15
三、驱动程序--读取数据
我们使用SPI方式读取MT6701(个人认为比IIC速度更快,更方便)
mt6701.c文件
/***************************************************************************/
#define SPI2_CS1_L GPIO_ResetBits(GPIOA, GPIO_Pin_15) //CS1_L
#define SPI2_CS1_H GPIO_SetBits(GPIOA, GPIO_Pin_15) //CS1_H
/***************************************************************************/
void SPI2_Init_(void) // 初始化SPI接口
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SPI3, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //CS--推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_15); //CS_H
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;//PA5--CLK,PA6--MISO,PA7--MOSI,
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//SPI1--双线全双工!!
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位数据
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //CPOL=0 CLK空闲为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //CPHA=1 建议在下降沿采集数据
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信号由硬件管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //4--9MHz,手册介绍最大速度15MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值计算的多项式
SPI_Init(SPI3, &SPI_InitStructure);
SPI_Cmd(SPI3, ENABLE);
}
/***************************************************************************/
unsigned char SPIx_ReadWrByte(unsigned char byte)
{
unsigned short retry = 0;
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET)
{
if(++retry>200)return 0;
}
SPI_I2S_SendData(SPI3, byte);
retry = 0;
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET)
{
if(++retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI3);
}
/***************************************************************************/
uint32_t ReadAngle(void)
{
uint8_t back1,back2,back3;
SPI2_CS1_L;
back1 = SPIx_ReadWrByte(0);
back2 = SPIx_ReadWrByte(0);
back3 = SPIx_ReadWrByte(0);
SPI2_CS1_H;
return (back1<<16)|(back2<<8)|back3;
}
/***************************************************************************/
ReadAngle(void)函数的原理,大家可以参考数据手册的解释:
我在这里去掉了磁场状态、校验码等信息,只保留了位置信息,将其作为返回值
需要注意的是MT6701的分辨率是14位!既输出的范围是0-16384,对应0°-360°
mt6701.h文件
#ifndef APP_MT6701_H_
#define APP_MT6701_H_
#include "ch32v30x.h"
void SPI2_Init_(void);
unsigned char SPIx_ReadWrByte(unsigned char byte);
uint32_t ReadAngle(void);
#endif /* APP_MT6701_H_ */
主函数调用:
unsigned int temp_Seat; // 存储位置数据
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
SPI2_Init_(void); // MT6701--SPI初始化
while(1)
{
temp_Seat = ReadAngle();// 获取角度值
Delay_Ms (200);
}
}
总结
MT6701经过我的测试,稳定性相较于AS5600强了太多,可拓展性极高(唯一的缺点就是有点小贵,大约12块一片,不过对于初学者,多花一分钱可以省很多力气!)。
这段程序经过测试,稳定精准,虽然是在CH32平台上测试,但代码与STM32完全兼容!大家可以移植到STM32平台使用。
至于这个MT6701的底板,我会专门做一起文章,讲解他的原理图和PCB,并分享给大家打样。
这是电机控制系列的第一篇文章,也是我在CSDN上的第一篇正式文章,希望能够帮助到大家
有问题、交流的朋友,或者对我的观点有疑惑,欢迎私信