AS5600步进电机编码器(原理图+pcb+stm32控制代码)

这篇具有很好参考价值的文章主要介绍了AS5600步进电机编码器(原理图+pcb+stm32控制代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、AS5600介绍

AS5600是一个易于编程的磁性旋转位置传感器,具有高分辨率的12位模拟或PWM输出。这种非接触式系统测量一个直径磁化的轴上磁铁的绝对角度。
引脚如下图
as5600,硬件设计,stm32单片机,stm32,单片机,arm
as5600,硬件设计,stm32单片机,stm32,单片机,arm
他有两种供电模式:5V和3.3V
as5600,硬件设计,stm32单片机,stm32,单片机,arm
我们为了和stm32F103C8T6单片机的电压一致,也使用3.3V供电,然后开始画PCB。

二、pcb设计

使用嘉立创EDA画图
as5600,硬件设计,stm32单片机,stm32,单片机,arm
as5600,硬件设计,stm32单片机,stm32,单片机,arm
as5600,硬件设计,stm32单片机,stm32,单片机,arm
as5600,硬件设计,stm32单片机,stm32,单片机,arm

三、实物照片

as5600,硬件设计,stm32单片机,stm32,单片机,arm
已经把as5600贴到了电机后面,暂时没有稍微长一点的螺丝,不然用四个螺丝固定更好。

四、程序代码

代码实现的功能:
1、可以实时显示当前绝对位置的角度(0~360)
2、可以实时显示增量角度,比如正转了2转,显示为720度,又在此基础上反转了3转,显示为-360度。
3、一上电当前位置即可自动设置为初始零位。
3、也可以测实时的速度(暂时没有写这部分功能,实现也简单,两次位置差除以时间即可)

难点:as5600接在了电机尾部,步进电机的轴转5.18圈,减速器输出的轴转1圈,as5600直接读的是步进电机轴的位置(我这个步进电机带了减速器,减速比为5.18)所以还需要一些转换。

程序大概思路:
设置3个变量temp0(记录一上电之后电机轴的初始位置,在程序中只需运行一次即可),temp1(用于记录本次电机轴的位置),temp2(用于记录下一次电机轴的位置)。temp1和temp2主要用于过360度判断,即如果temp-temp2>180度(在很短的时间内),那么肯定是过了360度了,即下一转开始了,因为电机不可能在很短的时间转过这么多度。而且从程序初始化以后就要一直拿比较temp1和temp2,每次都不能少,比较完了就把temp2赋值给temp1,然后下次再获取最新的temp2以后,继续和temp1比较。就是要一直和上一次的数据比较,中间不能又一次断开,这样可以保证不漏过那个变化的点,每次过360度的时候,进行一个计数(程序中用过零点标记sign_angle计数),然后只要知道初始角度(temp0)、过零点的次数(sign_angle),以及当前点的角度(temp2),就可以算出角度增量。
程序代码如下:

下面是as5600.h文件

#ifndef __AS5600__
#define __AS5600__
#include "sys.h"
#include "stm32f10x.h"

#define Slave_Addr                0x36 //设备从地址
#define Write_Bit                 0	   //写标记	
#define Read_Bit                  1    //读标记
#define Angle_Hight_Register_Addr 0x0C //寄存器高位地址
#define Angle_Low_Register_Addr   0x0D //寄存器低位地址
#define Jian_Su_Bi                5.18 //步进电机减速比

void AS5600_Init ( void );  //初始化
u16 AS5600_Read_Len ( u8 addr, u8 reg, u8 len, u8 *buf );//从AS5600读取一次数据
void Get_Ini_Val(void); //得到上电后角度初始值
void Get_Temp_Add(void); //等到角度增量(原始值表示的)
void Change_angle(void); //将原始增量数据转化为角度
void Get_Num_sign(void); //用于过零点计数

下面是as5600.c文件

#include "as5600.h"
#include "i2c.h"
#include "delay.h"


u32 angle_ini = 0; 		   //初始角度值
u32 temp0 = 0;			   //初始角度原始输出值
u32 temp1 = 0;		       //上次角度原始输出值
u32 temp2 = 0;		       //这次角度原始输出值
u32 temp_add = 0;	       //从初始角度开始的累计角度原始值
u8  buf[2] = {0};	       //用于oled显示存放变量,和本程序关系不大
int sign_angle = 0;	       //过零点标记(即从0度转到360度之后继续转又回零的那个点,正向经过一次加一,反向经过一次减一)
double True_Angle = 0.0;   //真实角度(累计角度)
int dir = 0; //0正向 1反向  //方向 
double Current_Angle = 0;   //当前角度(就是绝对位置角度,小于360度)
	
void AS5600_Init ( void ) {
    IIC_Init();
}

u16 AS5600_Read_Len ( u8 addr, u8 reg, u8 len, u8 *buf ) {
    IIC_Start();
    IIC_Send_Byte ( ( addr << 1 ) | Write_Bit );

    if ( IIC_Wait_Ack() ) {
        IIC_Stop();
        return 1;
    }

    IIC_Send_Byte ( reg );
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte ( ( addr << 1 ) | Read_Bit ); // 发送器件地址 + 读命令
    IIC_Wait_Ack(); // 等待应答

    while ( len ) {
        if ( len == 1 ) {
            *buf = IIC_Read_Byte ( 0 ); // 读数据,发送nACK
        } else {
            *buf = IIC_Read_Byte ( 1 ) & 0x000f; // 读数据,发送ACK 原始1f,改为0f
        }

        len--;
        buf++;
    }

    IIC_Stop();
    return 0;
}

void Get_Ini_Val(void)//获得初始角度
{
	u8 i = 0;
	u32 transfer = 0;
	for ( i = 0; i < 20; i++ ) { // 刚开始数据可能不稳定,直接丢掉
		AS5600_Read_Len ( Slave_Addr, Angle_Hight_Register_Addr, 2, buf );
		delay_ms ( 5 );
    }
	for ( i = 0; i < 20; i++ ) { // 软件滤波
		AS5600_Read_Len ( Slave_Addr, Angle_Hight_Register_Addr, 2, buf );
		transfer += ( ( buf[0] << 8 ) | buf[1] );
		delay_ms ( 5 );
    }
	temp0 = transfer / 20;
	temp2 = temp0;//给temp2初始化为初始值
	temp1 = temp0;//给temp1初始化为初始值
}


void Get_Temp_Add(void)//计算角度增量
{
	
	if(sign_angle == 0)  //当从没经过零点时
	{
		if(temp2 >= temp0) //正转
		{	temp_add = temp2 - temp0;	
			dir = 0;}
		else    			//反转
		{	temp_add = temp0 - temp2;
			dir = 1;}
	}
	else if(sign_angle > 0)//经过一次及以上零点位置后,分两种情况,正向经过与反向经过,需分开讨论
	{

		temp_add = 4096 + temp2 - temp0 + ( sign_angle - 1)*4096;  //正向经过
		dir = 0;
	}
	else 
	{
		temp_add =4096 + temp0 - 4096*(sign_angle+1) - temp2;   //反向经过
		dir = 1;
	}
}

void Change_angle(void)//考虑减速比,计算增量实际角度
{
	True_Angle = (temp_add/(Jian_Su_Bi*4096))*360;  //4096代表as5600原始数据最大值(0~4096)
}

void Get_Current_angle(void)//获取360度角度,即计算绝对位置,小于等于360度
{
	u32 x0 = 0;
	x0 = (temp_add*100)%((u32)(Jian_Su_Bi*100)*4096);
	Current_Angle = (x0/(Jian_Su_Bi*4096))*360/100;
}

void Get_Num_sign(void) //计算过零点次数,这个函数也可以用定时器中断来调用,效果更好
{
	u32 x;
	AS5600_Read_Len ( Slave_Addr, Angle_Hight_Register_Addr, 2, buf );
	temp2 = ( ( buf[0] << 8 ) | buf[1] );
	if(temp1 >= temp2)
	{
		x = temp1 - temp2;
		if(x>2048)//正转通过零点
		{
			sign_angle++;
		}
	}
	else
	{
		x = temp2 -temp1;
		if(x>2048)//反转通过零点
		{
			sign_angle--;
		}
	}
	temp1 = temp2;//每次都把temp2赋给temp1
}



下面是main函数

#include "stm32f10x.h"
#include "oled.h"
#include "delay.h"
#include "timer.h"
#include "key.h"
#include "exti.h"
#include "as5600.h"
#include "stdio.h"
#include "sys.h"
#include "key.h"
#include "mtor.h"
#include "exti.h"
#include "oledfont.h"

extern u8  TIM2_Pulse_TIM3_Counter_OK;

uint16_t pwm = 7199;
u32 pulsecnt = 200;
extern double Current_Angle;
extern double True_Angle;
extern int dir;
extern u32 temp_add;
extern u32 temp2;
extern u32 temp0;
uint8_t sign = 0;
extern int sign_angle;
 int main(void)
 {		 
	 char strff[21];
	 char strff2[21];
     static uint8_t x = 1;

     delay_init();
     OLED_Init();
     led_Init();
     KEY_Init();
  
  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    TIM3_PWM_Init(pwm,19);//控制频率 72000000/(7199+1)/(19+1)=500HZ
	TIM_SetCompare2(TIM3,10);//控制占空比,原始49,改为2999
    motor_init();
    TIM2_Init(pulsecnt);
    EXTIX_Init();
    AS5600_Init();
    memset(strff,0,sizeof(strff));
	memset(strff2,0,sizeof(strff2));
	Get_Ini_Val();//获得初始角度
	
  while(1)
  {
	Get_Temp_Add();
	Change_angle();
	Get_Current_angle();
	Get_Num_sign();
	sprintf(strff,"%.2f",True_Angle);//%0.2f  angle
	//sprintf(strff2,"%.2f",Current_Angle);//%0.2f  angle
	sprintf(strff2,"%.2f",Current_Angle); 
	  if(dir == 0)
	  {
		OLED_ShowChar(0,0,'+');
		OLED_ShowChar(0,4,'+');
	  }
	  else
	  {
		OLED_ShowChar(0,0,'-');
		OLED_ShowChar(0,4,'-');
	  }
	  
	OLED_ShowNum(6,0,True_Angle,5,12);
	OLED_ShowString(0,2,strff);
	OLED_ShowNum(6,4,Current_Angle,5,12);
	OLED_ShowString(0,6,strff2);  
	//OLED_ShowNum(54,6,3600000/pwm,5,12);
	  
	Get_Num_sign();
	
		switch(sign)
		{
			case 1:
				if(x==1)
				{/*TIM_Cmd(TIM3,ENABLE);
					led_On_Off();
					x++;*/
					setDir();
					x++;	
				}
				else if(x==2)
				{
					/*setDir();
					x++;*/	
					TIM_Cmd(TIM3,ENABLE);
					led_On_Off();
					x++;					
				}
				else if(x==3)
				{	TIM_Cmd(TIM3,DISABLE);
					led_On_Off();
					x=1;}
				sign = 0;
				break;
			case 2:
				if(pwm>0)
				{
					pwm-=100;
				}else
				{
					pwm=7199;
				}
				sign = 0;
				TIM_SetAutoreload(TIM3,pwm);
				break;
				
			case 3:
			
			if(pwm<15000)
				{
					pwm+=100;
				}else
				{
					pwm=7199;
				}
				sign = 0;
				TIM_SetAutoreload(TIM3,pwm);
				break;
			case 4:
				//正转1/4,反转1/4,正转半圈,反转半圈
			Pulse_output(1036);
			
			/*setDir();
			
			Pulse_output(1036);
			while(TIM2_Pulse_TIM3_Counter_OK!=1);
			TIM2_Pulse_TIM3_Counter_OK=0;*/
			
			//setDir();
			
			/*Pulse_output(100);
			while(TIM2_Pulse_TIM3_Counter_OK!=1);
			TIM2_Pulse_TIM3_Counter_OK=0;
			
			setDir();
			
			Pulse_output(100);
			while(TIM2_Pulse_TIM3_Counter_OK!=1);
			TIM2_Pulse_TIM3_Counter_OK=0;
			
			*/
			
			sign = 0;
			break;	
			
			default:
				break;
		}	
		if(TIM2_Pulse_TIM3_Counter_OK==1)
		{
				TIM2_Pulse_TIM3_Counter_OK=0;
		}
		
	}
	
 }

注意switch后面的语句是用来按钮控制步进电机运动的,和as5600本身无关。

五、实物演示

as5600,硬件设计,stm32单片机,stm32,单片机,arm
图中一个是基于STM32F103C8T6的控制器,一个是TB6600步进电机驱动板。
实测,代码正常运行,功能都可以实现,连续正转10圈误差在3.6度以内,再反转10圈回零点误差在0.15度以内,数据也基本稳定。
测试数据记录
as5600,硬件设计,stm32单片机,stm32,单片机,arm
测试的时候每次给半圈的脉冲,所以一转是两个数据,0->180.21->0.103->180.63->0.239…依次测量得到。

最后,附上程序代码以及AS5600的berger制板文件的下载地址
链接:https://pan.baidu.com/s/1zxl2O3oEvmDIDNtbDGoTPg
提取码:m5k5
演示效果观看地址:
https://www.bilibili.com/video/BV1hP411N7PJ/?vd_source=81fb9332eb85b94d92d4e3884ff48c6a文章来源地址https://www.toymoban.com/news/detail-780472.html

到了这里,关于AS5600步进电机编码器(原理图+pcb+stm32控制代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程

    📍相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》 ✨stm32使用硬件I2C去读取角度数据,通过STM32CubeMX工具配置工程,读取角度数据,只需要调用一个函数,即可完成数据的读取。了解函数的用法以及从设备地址命令,上手十分快速和简单。 📌AS5600资料: https://p

    2024年04月26日
    浏览(56)
  • MT6701磁编码器使用指南,14Bit单圈绝对值,I2C stm32 HAL库读角度,兼容AS5600

      MT6701是麦歌恩(MagnTek)公司的磁性角度传感器芯片,提供14Bit 0~360°单圈绝对角度检测,拥有 ABZ/PWM/模拟量/I2C/SSI 等多种信息输出方式,还可根据磁场强度的瞬时变化提供非接触式按压检测功能。能够以较低的成本来替代传统光电编码器,可应用于绝对值角度输出、闭环

    2024年02月02日
    浏览(40)
  • stm32霍尔编码器电机测速原理

            本次选用的编码器电机为13线的霍尔编码器电机,电机减速比为30:1,转动一圈输出13*30=390个脉冲。轮胎直径为75mm,轮胎周长为pi*d=3*75=225mm.定时器采用四倍频计数,则一圈输出390*4=1560个脉冲。具体编码器知识这里就不多说了。          根据测速原理:假设编

    2024年02月15日
    浏览(43)
  • 【程序】【必须】编码器电机测速,原理+代码+滤波

    参考资料: https://blog.csdn.net/lzzzzzzm/article/details/119416134 野火STM32电机开发教程 常见的编码器有两种,分别为霍尔编码器和GMR编码器。 1.1 霍尔编码器 ​ 霍尔编码器圆盘上分布有磁极,当圆盘随电机主轴转动时,会输出两路相位差90°的方波,用这两路方波可测出电机的转速和

    2023年04月23日
    浏览(47)
  • 步进电机工作原理

    什么是步进电机 ​ 步进电机是将电脉冲信号,转变为角位移或线位移的开环控制电机,又称为脉冲电机。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响。当步进驱动器接收到一个脉冲信号时,它就可以驱动步进电机

    2024年02月06日
    浏览(36)
  • 步进电机结构及原理

    步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。通过控制施加在电机线圈上的电脉冲顺序、 频率和数量, 可以实现对步进电机的转向、 速度和旋转角度的控制。在不借助带位置感应的闭环反馈控制系统的情况下、 使用步进电机与其配套的驱动器共同组成的

    2023年04月21日
    浏览(34)
  • 【基础知识】【模块介绍】电机编码器

    目录 概述  测速原理 波形分析 解码 单相计数 A相 B相 双相计数 转速计算 电机编码器常见的是AB相电机编码器,和旋转编码器类似,传送门 常见的有光电和霍尔等,属于非接触测转速的方法 不管是光电还是霍尔的编码器本质上都是在电机的旋转轴上放上一个码盘, 不同的是

    2023年04月08日
    浏览(44)
  • 霍尔编码器电机与TB6612电机驱动相关学习

    简单粗暴的说下,电机-电机驱动-单片机该怎么连线。 先简单认识一下霍尔编码器电机 以上选用的平衡小车之家的,市面上基本都跟这个差不了多少。 电机线-+这两个引脚 与电机驱动相连接 来控制电机的正反转(自己的浅显理解)  编码器的AB相 连接单片机(定时器)  编

    2023年04月09日
    浏览(29)
  • 步进电机原理及参数详解

    步进电机常见型号:20,28,35,39,42,57,86等,功能大同小异,差异主要点在尺寸和输出力的大小不一样。下面我们以57为例详细说明其原理。 步进电机常见和用到最多的是2相步进电机,也有3,5相等,用量较少,驱动器价格昂贵,一般一些特殊场景才会使用。 1. 为什么叫20,28,35,39

    2024年02月04日
    浏览(37)
  • ESP32(MicroPython) 编码器电机闭环控制

    本人最近查找资料时,发现ESP32上的使用MicroPython的编码器电机相关程序较少,闭环控制程序都是Pyboard上的,与ESP32不完全兼容。本人通过micropython编程 esp32+drv8833+霍尔编码器_micropython 编码器_青右的博客-CSDN博客 上的程序读取编码器计数,然后另写了控制程序,有两个版本。

    2024年02月16日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包