这个闭环驱动系统中,充当闭环反馈的是磁编码器
MT6816,它的作用是告诉主控现在电机的转动位置。
一般来说磁编码器和光编码器
相比,精度、分辨率和响应时间都要差一些,但优势是对环境要求较低,粉尘、油污、液体等等对磁编码器没有什么影响,不像光码需要清洁和透明,而且近来磁编码器的精度和分辨率都有显著提高,加入了无电池多圈技术,从而解决了多圈无法反馈的老问题,使得磁编码器成为闭环电机系统很好的选择。
MT6816是一款国产磁编码器,和项目相关的主要参数如下:
- 14bit绝对角度数据
- 提供4线SPI接口通信14bit的绝对值数据,也提供增量ABZ输出来替代光电编码器
- 支持最高电机转速为25K rpm
下面这张图将磁铁安装和芯片的相对位置描述得很易懂,MT6816的几何中心必须和电机转动轴中心一致,而且磁铁离芯片的距离尽量小(1-3mm为宜)。这就决定了这个驱动器必须安装在步进电机的尾端,且PCB布板的时候也要注意芯片的放置位置。
我们按照datasheet的4线SPI参考电路来接线,如下图所示
研究下4线SPI是怎么读取磁编码器的角度数据的
这里其实不用管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
}
}
有了电机的旋转角度数据,就可以进行下一步的闭环计算等工作了。
未完待续