写这篇文章是为了对最近学习无刷电机FOC的一些学习心得进行记录,本文基于STM32F407标准库函数编写。

在无刷电机FOC中,需要获取电机实时运行的电角度来进行克拉克变换和帕克变换及其逆变换,而AS5600磁编码器常用于电机的角位移测量。

原理图

AS5600封装如下图所示
AS5600封装
其引脚定义如下
在这里插入图片描述
VDD5V、VDD3V3:电源输入
OUT:模拟电压/PWM输出口,如果输出模拟电压,其上限为VDD电源电压,下限为GND,以比例线性绝对值形式输出角度对应的电压值;如果输出PWM,其输出的角度值由PWM脉冲宽度表示。
GND:地
PGO:模式选择(模式A:用I2C读取角度(PGO悬空);模式B:用OUT引脚读取角度(PGO接GND))
SDA、SCL:I2C接口(需外部上拉)
DIR:旋转方向(连GND:顺时针数值增加,连VDD:顺时针数值减小)

原理框图

在这里插入图片描述
黑虚线框图中的部分为AS5600的核心部分,其将测得到的角度经过数字处理和滤波后可以通过I2C、PWM、DAC三种方式输出。

电源输入

其推荐电路图如下图所示
在这里插入图片描述
改芯片有两种电源模式:5.0V和3.3V
5V模式:当电源输入为5V时,其内部LDO输出的3.3V不能为其他I2C设备供电,且3.3V需要一个1uF电容。
3.3V模式:当电源输入为3.3V时,需要将VDD5V和VDD3V3连接到一起,如果需要OTP编程,VDD3.3V还需一个10uF电容。

使用I2C读取角度时的应用电路

在这里插入图片描述
当使用I2C接口获取编码器值时的应用电路,左边电源输入为5V,右边电源输入为3.3V,PGO悬空。
其C1、C2、 RPU的取值见下表。

元器件 符号 取值 单位 精度
VDD5V滤波电容 C1 100 nF 20%
LDO滤波电容 C2 1 μF 20%; < 100 mΩ(低等效电阻)
I2C上拉电阻 RPU 4.7

I2C应用

AS5600的7为地址为 0x36 (0110110)。若加上读写位为读(01101101)(0x6D)、写(01101100)(0x6C)。
AS5600的I2C时钟线SCL最大为1MHZ。

AS5600寄存器

在这里插入图片描述
配置寄存器:ZMCO、ZPOS、MPOS、MANG、CONF。
主要功能:可配置AS5600的起始位置(ZPOS),即让电机旋转到某一位置后可以配置这个寄存器让其输出0角度;可配置AS5600的停止位置(MPOS);可配置AS5600的最大角度(MANG)(默认为360度);可配置AS5600的OUT引脚输出(CONF),即可以控制OUT是输出模拟电压或PWM,
输出PWM的频率等等。
输出寄存器:RAW _ANGLE、ANGLE
主要功能:RAW _ANGLE存储未经过缩放和未经修改的角度。ANGLE存储经过缩放和过滤后的角度。本文使用I2C读取RAW _ANGLE寄存器获取角度值。
状态寄存器:STATUS、AGC、MANGNITUDE
主要功能:提供指示AS5600当前状态。可提供AS5600所配套的磁铁是否安装合适(STATUS);
可配置AGC增益(AGC);显示内部CORDIC的幅度值。

AS5600.c

#include "stm32f4xx.h"                  // Device header

#include "Delay.h"
#include "MyI2C.h"
#include <stdio.h>
#include <math.h>
//AS5600的7位从机地址位0x36(0110110),加上读位(01101101),写位(01101100)
#define AS5600_ADDRESS        0x6C //加上读写位(1位1/0)0x6C是写
#define AS5600_RAW_ANGLE_H    0x0C
#define AS5600_RAW_ANGLE_L    0x0D

#define _2PI       6.2832f
//AS5600写数据
void AS5600_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	MyI2C_Start();							//起始信号
	MyI2C_SendByte(AS5600_ADDRESS);			//发送从机地址,读写位为0,表示即将写入
	MyI2C_ReceiveAck();						//接收应答
	MyI2C_SendByte(RegAddress);				//发送寄存器地址
	MyI2C_ReceiveAck();						//接收应答
	MyI2C_SendByte(Data);					//发送要写入寄存器的数据
	MyI2C_ReceiveAck();						//接收应答
	MyI2C_Stop();							//I2C终止
}
//AS5600读数据
uint8_t AS5600_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDRESS);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	
	MyI2C_Start();								//I2C重复起始
	MyI2C_SendByte(AS5600_ADDRESS | 0x01);		//发送从机地址,读写位为1,表示即将读取
	MyI2C_ReceiveAck();							
	Data = MyI2C_ReceiveByte();					//接收指定寄存器的数据
	MyI2C_SendAck(1);							//发送应答,给从机非应答,终止从机的数据输出
	MyI2C_Stop();
	
	return Data;
}
//AS5600获取角度值
float AS5600_GetRawData(void)
{
	uint8_t Data_L;
	uint8_t Data_H;
	float Raw_Data = 0;
	
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDRESS);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(AS5600_RAW_ANGLE_H);
	MyI2C_ReceiveAck();
	//读高4位
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDRESS | 0x01);
	MyI2C_ReceiveAck();
	Data_H = MyI2C_ReceiveByte();
	MyI2C_ReceiveAck();
	//AS5600在读出数据后,寄存器指针自动加1,所以无需发送地位地址,直接读后8位即可
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDRESS | 0x01);
	MyI2C_ReceiveAck();
	Data_L = MyI2C_ReceiveByte();
	MyI2C_SendAck(1);
	MyI2C_Stop();
	
	Raw_Data = (Data_H << 8) | Data_L;
	
	return Raw_Data;
}
void AS5600_Init(void)
{
	MyI2C_Init();
}

float GetAngle_NoTrack(void)//将编码器的值转换为弧度
{
	float Angle = 0.0;
	
	Angle = (AS5600_GetRawData()/4096) * _2PI;//弧度
//	Angle = (Angle/4096) * 360;//角度

	return Angle;
}
float full_rotations = 0.0f;//圈数
float Last_Angle = 0.0f;
//磁编码器弧度制角度累计计算:(0-∞)
float GetAngle(void)
{
	float D_Angle = 0.0f;
	float Angle = GetAngle_NoTrack();//获取弧度
	
	D_Angle = Angle - Last_Angle;//e
	
	if( fabs(D_Angle) > (0.8f*2*PI) ) 
		//通过判断角度变化是否大于80%的一圈来判断是否发生了溢出,如果发生了
	{
		full_rotations = full_rotations + ((D_Angle > 0) ? -1 :1);
	}
	
	Last_Angle = Angle;
	
	return (full_rotations * 2 * PI + Last_Angle);
}

AS5600.h

#ifndef __AS5600_H
#define __AS5600_H


void AS5600_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t  AS5600_ReadReg(uint8_t RegAddress);
void AS5600_Init(void);
float AS5600_GetRawData(void);
float GetAngle(void);
float GetAngle_NoTrack(void);
float GetVelocity(void);
#endif

OTP

前面有提到OTP编程但并没有解释是什么,这里简单说一下。
非易失性存储器(OTP)
非易失性存储器用于永久性编程配置。前面说配置寄存器可以配置编码器输出值的最大值等等,但每次上电编码器都会恢复默认值,(即改变编码器输出值的最大值后,重新上电编码器输出值的最大值会恢复默认的360度),使用OTP可以永久改变配置寄存器的值,无需上电后重新配置寄存器。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐