STM32自学笔记15-步进电机驱动项目-磁编码器MT6816驱动

这个闭环驱动系统中,充当闭环反馈的是磁编码器MT6816,它的作用是告诉主控现在电机的转动位置。

一般来说磁编码器和光编码器相比,精度、分辨率和响应时间都要差一些,但优势是对环境要求较低,粉尘、油污、液体等等对磁编码器没有什么影响,不像光码需要清洁和透明,而且近来磁编码器的精度和分辨率都有显著提高,加入了无电池多圈技术,从而解决了多圈无法反馈的老问题,使得磁编码器成为闭环电机系统很好的选择。

MT6816是一款国产磁编码器,和项目相关的主要参数如下:

- 14bit绝对角度数据
- 提供4线SPI接口通信14bit的绝对值数据,也提供增量ABZ输出来替代光电编码器
- 支持最高电机转速为25K rpm

下面这张图将磁铁安装和芯片的相对位置描述得很易懂,MT6816的几何中心必须和电机转动轴中心一致,而且磁铁离芯片的距离尽量小(1-3mm为宜)。这就决定了这个驱动器必须安装在步进电机的尾端,且PCB布板的时候也要注意芯片的放置位置。
STM32自学笔记15-步进电机驱动项目-磁编码器MT6816驱动_第1张图片
我们按照datasheet的4线SPI参考电路来接线,如下图所示STM32自学笔记15-步进电机驱动项目-磁编码器MT6816驱动_第2张图片
研究下4线SPI是怎么读取磁编码器的角度数据的
STM32自学笔记15-步进电机驱动项目-磁编码器MT6816驱动_第3张图片

STM32自学笔记15-步进电机驱动项目-磁编码器MT6816驱动_第4张图片
STM32自学笔记15-步进电机驱动项目-磁编码器MT6816驱动_第5张图片
这里其实不用管0x05的数据了,一般步进电机的应用中超速的概率不大

从图17和图19可以得到读取0x03和0x04数据的指令为10000011和10000100,即0x83和0x84,由于DI7到DI0为0(没有要写入到芯片的数据),所以在库函数HAL_SPI_TransimitReceive()来读取寄存器的数据时,发送指令为0x8300和0x8400,从而接收到14bit的角度数据Angle[13:0]

uint16_t ReadAngledata(uint16_t _dataTx)
{
    uint16_t dataRx;

    GPIOA->BRR = GPIO_PIN_15; // 拉低CSN,准备通信
    HAL_SPI_TransmitReceive(&hspi1, (uint8_t*) &_dataTx, (uint8_t*) &dataRx, 1, HAL_MAX_DELAY);
    GPIOA->BSRR = GPIO_PIN_15; //拉高CSN,结束通信

    return dataRx;
}

完整的读取数据的代码如下(有很详细的注释,应该都能看懂)

void MT6816_SPI_Get_AngleData(void)
{
    uint16_t data_t[2];  //SPI发送数据
    uint16_t data_r[2];  //SPI接收数据,即角度数据
    uint8_t h_count;  //奇偶校验计数用

    data_t[0] = 0x8300;  //根据MT6816 Datasheet, 0x8300读取0x03寄存器数据
    data_t[1] = 0x8400;  //同上

    for(uint8_t i=0; i<3; i++)
    {
        MT6816_SPI_CS_L();
        HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&data_t[0], (uint8_t *)&data_r[0], 1, HAL_MAX_DELAY);
        MT6816_SPI_CS_H();
        MT6816_SPI_CS_L();
        HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&data_t[1], (uint8_t *)&data_r[1], 1, HAL_MAX_DELAY);
        MT6816_SPI_CS_H();

        mt6816_spi.sample_data = ((data_r[0] & 0xFF) << 8 | (data_r[1]) & 0xFF);  //16bits SPI接收数据

        //以下为奇偶校验
        h_count = 0;
        for(uint8_t j=0; j<16; j++)
        {
            if(mt6816_spi.sample_data & (0x0001 << j))
                h_count++;
        }
        if(h_count & 0x01)
        {
            mt6816_spi.pc_flag = false;
        }
        else{
            mt6816_spi.pc_flag = true;
            break;  //奇偶校验结束
        }

    }
    if(mt6816_spi.pc_flag)
    {
        mt6816_spi.angle = mt6816_spi.sample_data >> 2;  //前14bits 角度数据
        mt6816_spi.no_mag_flag = (bool) (mt6816_spi.sample_data & 0x0010);  //弱磁标志位,根据datasheet
    }
}

有了电机的旋转角度数据,就可以进行下一步的闭环计算等工作了。

未完待续

你可能感兴趣的:(stm32,单片机,arm)