1. 背景
相较于无感FOC,有感FOC可以直接读取电机当前角度,而无需位置观测器。不仅实现容易,而且减少计算量。
评估版1.0的传感器接口只有霍尔编码器,而市面上很多编码器是I2C接口,或者SPI接口,无法通用。我手上有的电机编码器是AS5600型号,而开发板着实没有预留gpio口供使用,因此产生了将霍尔传感器接口改成普通的GPIO口的想法,使用模拟I2C驱动并读取电机旋转角度。
2.硬件电路改动
使用HA、HB分别作为SDA和SCL,将R7和R8两个电阻替换成0欧姆电阻即可。
3.AS5600编码器
◆AS5600与两极磁铁配对,可以输出12位分辨率的磁性旋转位置,支持IIC通信,还可以输出模拟电压和PWM信号。这里我是用I2C读取方式,分别对0x0C和0x0D两个寄存器进行读取。
在实物上,需要在电机旋转轴上吸附一个磁铁(旋转轴自带径向磁铁更好),as5600编码器放在磁铁正下方。
4.代码编写。这里创建两个源文件,分别对应了模拟I2C驱动和AS5600驱动
- #ifndef _BSP_I2C_GPIO_H
- #define _BSP_I2C_GPIO_H
-
- #include "apm32m35xx.h"
-
- typedef uint8_t u8;
- typedef uint16_t u16;
-
- #define DEVICE_I2C_WR 0 /* 写控制bit */
- #define DEVICE_I2C_RD 1 /* 读控制bit */
-
-
-
- #define DEVICE_I2C_GPIO_PORT GPIOA /* GPIO端口 */
- #define DEVICE_I2C_GPIO_CLK RCM_AHB_PERIPH_GPIOA /* GPIO端口时钟 */
- #define DEVICE_I2C_SCL_PIN GPIO_PIN_1 /* 连接到SCL时钟线到编码器HB */
- #define DEVICE_I2C_SDA_PIN GPIO_PIN_3 /* 连接到SDA数据线到编码器HA */
-
-
-
- #define DEVICE_I2C_SCL_1() GPIO_SetBit(DEVICE_I2C_GPIO_PORT, DEVICE_I2C_SCL_PIN) /* SCL = 1 */
- #define DEVICE_I2C_SCL_0() GPIO_ClearBit(DEVICE_I2C_GPIO_PORT, DEVICE_I2C_SCL_PIN) /* SCL = 0 */
-
- #define DEVICE_I2C_SDA_1() GPIO_SetBit(DEVICE_I2C_GPIO_PORT, DEVICE_I2C_SDA_PIN) /* SDA = 1 */
- #define DEVICE_I2C_SDA_0() GPIO_ClearBit(DEVICE_I2C_GPIO_PORT, DEVICE_I2C_SDA_PIN) /* SDA = 0 */
-
- #define DEVICE_I2C_SDA_READ() GPIO_ReadInputBit(DEVICE_I2C_GPIO_PORT, DEVICE_I2C_SDA_PIN) /* 读SDA口线状态 */
-
-
- void i2c_Start(void);
- void i2c_Stop(void);
- void i2c_SendByte(uint8_t _ucByte);
- uint8_t i2c_WaitAck(void);
- uint8_t i2c_ReadByte(unsigned char);
- void i2c_Ack(void);
- void i2c_NAck(void);
- void i2c_CfgGpio(void);
- uint8_t i2c_CheckDevice(uint8_t _Address);
-
- uint32_t I2C_ByteWrite(u8* pBuffer, u8 WriteAddr);
- uint32_t I2C_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead);
-
-
- #endif
-
-
- #ifndef __AS5600_H
- #define __AS5600_H
-
- #include "stm32f4xx.h"
- #include "user_config.h"
- #include "./i2c/software_i2c/bsp_i2c_gpio.h"
-
-
- #include <stdlib.h>
-
- #define AS5600_CPR 4096 // as5600的满量程
-
- #define AS5600_ADDRESS 0x36
-
- typedef struct
- {
- float angle;
- float angle_rad;
- float electronic_angle;
- float angle_rad_offset;
- } AS5600_ENCODER_Def;
-
- extern AS5600_ENCODER_Def as5600_encoder;
-
- float getAngle(void);
- float getFullAngle(void);
-
- float getVelocity(void);
- void MagneticSensor_Init(void);
- void Get_Encoder_Angles(void);
- #define _2PI 6.28318530718f
- #define PI 3.14159265f
-
- #endif
-
5. 代码讲解
初始化定义。这里使用了编码器的HA和HB两个引脚,注意HA在硬件电路上是PA3引脚。我一开始配置时直接copy例程里的PA0引脚,调试很久才发现问题。
GPIO口初始化配置。配置成无上拉的开漏输出。
读一字节函数。 输入参数为寄存器地址,返回参数为对应的值。
读AS5600的编码器结果函数。分别传入高和低寄存器地址,对内容进行读取,并返回。返回结果是0-4096对应0-360°
6.主函数编写,当读取的角度大于180°时,led灯点亮。反之熄灭
-
- IO_Init();
-
- MagneticSensor_Init();
- while(1){
- // 将弧度转换为度
- ang = getAngle()* (180.0 / 3.14158f);
- if(ang > 180)
- LED_Fault_ON();
- else
- LED_Fault_OFF();
-
- for(i=0;i<1000;i++);
-
- }
7. 效果展示
鎾斁鍣ㄥ姞杞藉け璐�: 鏈娴嬪埌Flash Player锛岃鍒�
瀹夎
5f79114885356724acad327fd9064c55