基于STM32F103驱动AS5600读取磁体旋转的模拟量/角度数据

电子说

1.4w人已加入

描述

一、AS5600简介

AS5600 是一款易于编程的磁性旋转位置传感器,具有高分辨率 12 位模拟或 PWM 输出。该非接触式系统可测量径向磁化同轴磁体的绝对角度。AS5600 专为非接触式电位器应用而设计,其坚固的设计可消除任何均匀外部杂散磁场的影响。 I²C 接口支持用户轻松编程非易失性参数,无需专用编程器。默认情况下,输出范围为 0 至 360 度。也可以通过编程零角度(起始位置)和最大角度(停止位置)来定义更小的输出范围。
AS5600 还配备了智能低功耗模式功能,可自动降低功耗。输入引脚 (DIR) 可根据旋转方向选择输出极性。如果 DIR 接地,则输出值会随着顺时针旋转而增大。如果 DIR 连接到 VDD,则输出值会随着逆时针旋转而增大。
特性
非接触式角度测量
可编程最大角度从 18° 到 360°
12位DAC输出分辨率
输出方式:I2C接口 / PWM / 模拟输出
7位I2C地址:0x36(地址不可配置)
位置传感器
位置传感器

二、引脚说明

位置传感器

VDD5V5V 模式下的正电压供电
VDD3V33.3V 模式下的正电压电源
OUT模拟/PWM输出
GND
PGO编程选项(内部上拉,连接到 GND = 编程选项 B)
SDAI2C 数据
SCLI2C 时钟
DIR方向极性(GND = 值顺时针增加,VDD = 值逆时针增加)

PGO引脚说明:
PGO=高电平(悬空/VDD):AS5600处于正常工作模式,仅读取角度数据。
PGO=低电平(GND):进入编程模式,允许配置零位、最大角度等参数。

DIR 引脚控制磁铁旋转方向。如果 DIR 连接到 GND (DIR = 0),则从顶部顺时针旋转将产生计算角度的增量。如果 DIR 引脚连接到 VDD (DIR = 1),则计算的角度将逆时针旋转。
位置传感器

三、功能框图和数据的读写

位置传感器

写数据
位置传感器

读数据
位置传感器

指定地址读数据
位置传感器

四、寄存器说明

位置传感器
常用寄存器有:
CONF(0x07 / 0x08):配置寄存器
位置传感器
RAW ANGLE(0x0C / 0x0D):未缩放/未处理的原始角度数据,12-bit。

ANGLE(0x0E / 0x0F):已缩放/处理后的角度寄存器,12-bit。

RAW和ANGLE寄存器的区别:RAW 是芯片内部直接计算得到的无缩放角度;ANGLE 是按 ZPOS/MPOS/MANG(如有编程)以及滤波/死区后的输出值。

STATUS(0x0B):状态寄存器,包含磁铁检测位(Magnet Detected,MD)、Magnet Low/High(ML/MH)等位,判断是否检测到合适的磁场(MD=1 表示检测到磁铁)。

AGC(0x1A):自动增益控制,表示放大倍数,5V 下范围 0..255,3.3V 下 0..128。可用来补偿因温度变化、IC 与磁体之间的气隙以及磁体性能下降而导致的磁场强度变化。为了获得最稳健的性能,增益值应位于其范围的中间。
典型的径向磁铁感应气隙在 0.5 mm 到 3 mm 之间,这取决于所选的磁体。更大、更强的磁铁允许更大的气隙。以 AGC 值为指导,通过调整磁体和 AS5600 之间的距离,使 AGC 值位于其范围的中心,可以找到最佳气隙。当使用直径为 0.25mm 的磁体时,参考磁体的旋转轴从封装中心的最大允许位移为 6 mm。
位置传感器

MAGNITUDE(0x1B / 0x1C):用于判断磁场强弱与是否饱和/过弱。

BURN(0xFF):写 0x40 到 0xFF 可做永久写入/OTP,慎重,写入次数有限。
Burn_Angle 命令 (ZPOS, MPOS):主机微控制器可以使用 BURN_ANGLE 命令对 ZPOS 和 MPOS 进行永久编程。要执行 BURN_ANGLE 命令,请将值 0x80 写入寄存器 0x​​FF。BURN_ANGLE 命令最多可执行 3 次。ZMCO 显示 ZPOS 和 MPOS 已永久写入的次数。此命令仅在检测到磁铁存在 (MD = 1) 时执行。
Burn_Setting 命令 (MANG, CONFIG):主微控制器可以使用 BURN_SETTING 命令永久写入 MANG 和 CONFIG。要执行 BURN_SETTING 命令,请将值 0x40 写入寄存器 0x​​FF。只有在 ZPOS 和 MPOS 从未被永久写入 (ZMCO = 00) 的情况下,才能写入 MANG。BURN_SETTING 命令只能执行一次。

五、数据的换算公式

角度(deg) = raw / 4096.0 * 360.0。raw 为 0..4095(12-bit),即每 LSB ≈ 360/4096 = 0.087890625°。

MCU ADC(12-bit)电压换算:V = ADC_raw / 4095.0 * Vref。其中, ADC_raw为OUT引脚输出的模拟量,Vref为接的供电电压。

六、STM32F103驱动AS5600获取数据

准备工作

STM32F103C8T6开发板,OLED显示屏,AS5600磁编码器模块,磁铁等。

接线说明

STM32F103C8T6AS5600
3.3VVCC
GNDGND
PB10SCL
PB11SDA
PA0OUT
PB8OLED-SCL
PB9OLED-SDA

位置传感器

代码示例

AS5600.c

#include "as5600.h"
#include "oled.h"

void AS5600_Init(void)
{
	MyI2C_Init();
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);
	
	ADC_Cmd(ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
}

void AS5600_WriteData(uint8_t Wordaddress, uint8_t Data)
{
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDR);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(Wordaddress);
	MyI2C_ReceiveAck();
	
	MyI2C_SendByte(Data);
	MyI2C_ReceiveAck();
	MyI2C_Stop();
}

uint32_t AS5600_ReadData(uint8_t Wordaddress)
{
	uint8_t Data;
	
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDR);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(Wordaddress);
	MyI2C_ReceiveAck();
	
	MyI2C_Start();
	MyI2C_SendByte(AS5600_ADDR | 0x01);
	MyI2C_ReceiveAck();
	Data = MyI2C_ReceiveByte();
	MyI2C_SendAck(1);
	MyI2C_Stop();
	
	return Data;
}

uint16_t AS5600_ReadRawAngle(void)	//获取原始数值
{
    uint8_t hi = (uint8_t)AS5600_ReadData(AS5600_RAW_HI_REG);
    uint8_t lo = (uint8_t)AS5600_ReadData(AS5600_RAW_LO_REG);
    uint16_t val = ((uint16_t)hi < < 8) | (uint16_t)lo;
    val &= 0x0FFF;   
    return val;      
}

uint16_t AS5600_ADC_ReadRaw(void)  //获取ADC数值
{
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
	return ADC_GetConversionValue(ADC1);
}

float AS5600_ReadVolatge(uint16_t Vol)  //获取电压值
{
	float Volatge;
	Volatge = (float)Vol / 4095 * 3.3;
	return Volatge;
}

float AS5600_RawToDegree(uint16_t angle)  //获取角度
{
	return ((float)angle) * 360.0f / 4096.0f;
}

main.c

#include "stm32f10x.h"                  // Device header
#include "delay.h"  
#include "Delay.h"
#include "AS5600.h"
#include "OLED.h"

uint16_t rawAngle;
uint16_t adcRaw;
float  adcVolt, angleDeg;
char tmp[16];

int main(void)
{ 
    OLED_Init();
    AS5600_Init();
	OLED_ShowString(1,1,"RAW: ");
	OLED_ShowString(2,1,"ADC: ");
	OLED_ShowString(3,1,"Vol: 0.00V");
	OLED_ShowString(4,1,"ANG: 000.0");

	while(1)
	{
		rawAngle = AS5600_ReadRawAngle();  //角度原始数值
		adcRaw = AS5600_ADC_ReadRaw();	   //ADC模拟量
		adcVolt = AS5600_ReadVolatge(adcRaw);	//电压值
		angleDeg = AS5600_RawToDegree(rawAngle);  //角度:0-360°
		
		OLED_ShowNum(1,6,rawAngle,4);
		
		OLED_ShowNum(2,6,adcRaw,4);
		
		OLED_ShowNum(3, 6, adcVolt, 1);
		OLED_ShowNum(3, 8, (uint16_t)(adcVolt * 100) % 100, 2);

        OLED_ShowNum(4, 6, angleDeg, 3);
		OLED_ShowNum(4, 10, (uint16_t)(angleDeg * 1000) % 1000, 1);
		
		Delay_ms(50);
	}
}

效果展示

位置传感器
将磁铁固定在电机上,让电机转动。
位置传感器

注意事项

  1. AGC 与磁铁摆放:把磁铁放到合适的间隙(典型 0.5–3 mm),并用 AGC 值把距离调到居中(3.3V 下 AGC 0..128,目标约中间值)。如果 AGC 很小或很大,说明磁场太弱或太强。
  2. 程序写 OTP(Burn)非常谨慎:write 0x40 to 0xFF 会永久写入,次数有限。务必在确认无误后再做。
  3. 滤波设定:默认有 slow/fast filter,能在精度与响应间做折中;如果需要高速动态测量请降低慢滤波系数/调整 FTH。
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分