stm32霍尔编码器电机测速原理six

在SimpleFOC代码中,ABZ信号和霍尔电机信号处理方式很像,都是信号边沿触发中断,在中断中获取状态计算角度。
本次移植驱动板103和官方代码保持一致。

驱动板405采用的是定时器计数脉冲,处理方式不同。

一、ABZ编码器介绍
ABZ或者ABI,叫法不同但指的都是同一种编码器,也叫增量式编码器。
ABZ编码器最大的优点就是接口统一,兼容性好。
不像SPI接口的磁编码器,不同厂家的芯片甚至同一厂家的不同型号,通信协议各不相同,换个编码器就要重新写代码。

1.1、ABZ信号
A、B两相相差90度,可通过比较A相在前还是B相在前,以判断编码器的正转与反转,通过零位脉冲,可获得编码器的零位参考位。


一般采用四倍频技术,比如500线的编码器,转一圈可以获得2000个脉冲信号,


1.2、光电式编码器
最初的ABZ编码器是光电式的,最有名的品牌是安华高( Avago),分辨率叫“线”,比如500线就是500ppr(2000cpr)。

拆开后是这样的:下图

500线属于正常分辨率,1000线算是比较高的,2000线的电机肯定很贵了。不像现在的磁编码器,起步就是1024ppr。

1.3、磁编码器
磁编码器体积小,性能强,价格便宜,发展的很快,会越来越多的代替光电编码器。

磁编码器购买链接: 某宝购买

需要说明的是,有些磁编码器上电后可以输出当前绝对位置对应的脉冲数(需要配置相应的寄存器)。下图:

ABZ编码器每次上电都需要校准,所以使用时会有不方便的时候,但这个功能完美的解决了校准问题。这也是光电编码器望尘莫及的功能,充分体现了磁编码器的灵活。

1.4、差分信号
在传输距离比较长的情况下(比如大于1m),信号容易发生变形和干扰,需要将编码器输出的TTL信号转为差分信号,待到控制器端再转为TTL信号。
工业应用中,ABZ差分信号是应用非常普遍的编码器接口。
在驱动板103或者驱动板405上,可以只用A+,B+,Z+做为ABZ信号,A-,B-,Z-悬空即可。虽然不够严谨,但是做为开发学习还是可以的。



二、电机驱动板103


ABZ编码器电机的代码是独立的,没有与其它编码器混在一起,不需要在 myproject.h 中设置编码器类型,代码看起来更简洁。

2.1、读ABZ信号的cpr
如果你已经知道编码器的cpr,可以跳过当前小节。

2.1.1、接线
A—SCL1(PB6/TIM4_1)、B—SDA1(PB7/TIM4_2)、Z—PA12


电机驱动板103 购买链接:某宝购买
2804电机购买链接:某宝购买

2.1.2、编译,下载代码


2.1.3、转动电机,观察串口打印
第一次输出的cpr肯定不准确,因为电机上电为任意位置,
可以发送指令“2”读取任意时刻的cpr。

2.2、驱动ABZ电机M1
2.2.1、接线

————————————————
版权声明:本文为CSDN博主「loop222」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/loop222/article/details/129819585

#include "bsp_motor.h"
#include "bsp_uart.h"
unsigned int n = 0;
unsigned int enval = 0;

void DC_Brush_Motor_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    //PA1úPWM
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    TIM_TimeBaseStructure.TIM_Period = 99;  //10KHz  peroid -->200ms
    TIM_TimeBaseStructure.TIM_Prescaler = 71;  //71+1= 72ؖƵ
    //TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OC2Init(TIM2, & TIM_OCInitStructure);
    
    TIM_Cmd(TIM2, ENABLE);
    
    //PA2:AIN1  PA3:AIN2  P4;STBY
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    AIN1_HIGH;
    AIN2_LOW;
}    


//PB6ìPB7طΪ֨ʱǷҠëǷޓࠚìԃԚӉܯABРҠëǷ״!
void Encoder_Init_TIM4(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;  
    TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  
    //TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    
    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
//    TIM4->CCMR1 |= 1<<0;
//    TIM4->CCMR1 |= 1<<8;
//    TIM4->CCER &= ~(1<<1);
//    TIM4->CCER &= ~(1<<5);
//    TIM4->SMCR |= 3<<0;
//    TIM4->CR1 |= 1<<0;
    
    TIM_SetCounter(TIM4, 0);
    
    TIM_Cmd(TIM4, ENABLE);
}

void TIM3_Base_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_TimeBaseStructure.TIM_Period = 49999;  //50000us
    TIM_TimeBaseStructure.TIM_Prescaler = 71;  //71+1= 72ؖƵ
    //TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM3, ENABLE);
}

void TIM3_IRQHandler(void)
{
    static unsigned int encode_value = 0;
    
    if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
    {
        n++;
        if(n == 20)
        {
            encode_value = TIM_GetCounter(TIM4);
//            printf("Speed = %drpm\r\n", (3 * encode_value) / 78);
//                    printf("data = %d\r\n", rxData);
            enval = (3 * encode_value) / 78;
            n = 0;
            TIM_SetCounter(TIM4, 0);
        }
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    }
}

极对数按照实际写入,

voltage_sensor_align是电机零点校准时的电压值,需要根据电机功率设置,100W以内的电机基本属于小功率,可以设置的大一点,200W以上的属于大功率,设置的小一点。

如果不清楚电机功率,可以多试几个值,电源有电流显示的话观察下零点校准时的电流,只要在0.2A — 0.8A这个范围内就行,电流太小电机无力,校准可能不准确,电流太大电机会发热,容易损坏电机。

初次调试请选择 Type_voltage 模式,因为可以跳过电流环,电流环的PI参数非常难设置。

云台电机请选择 Type_voltage 模式,电机转速低且电流小,检测电流反而增加误差。

速度环的PI请自行设置,不清楚可以先把速度I参数设置为0,只用速度P参数,先让电机转起来再说。不同电机的PI参数不相同,具体请百度。

以下参数针对2804电机,编译后下载,

2.2.3、串口发送指令,观察电机运行


2.3、驱动ABZ电机M2
A—SCL2(PB10)、B—SDA2(PB11)、Z—SWD(PA13),
其实最初的设计是打算接PA11引脚的,但是调试代码的时候发现PB11和PA11是同一个中断源EXTI_Line11,并且在中断代码中无法区分,所以用SWD(PA13)来代替。
SWD(PA13)并没有设计外部上拉电阻,反复测试后确定只要代码中打开了内部上拉也可以的。
只是占用SWD后不能再用ST-link下载代码了,请大家使用串口下载。
串口下载的方法在 SimpleFOC移植STM32(二)—— 开环控制 的第3.2小节有说明,不清楚的可以去查看。
————————————————
版权声明:本文为CSDN博主「loop222」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/loop222/article/details/129819585

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值