目录
一、寄存器配置
首先寄存器配置官方推荐的我驱动不起来,最后用的这一套可以去驱动maxon的微型无刷电机。具体配置的注释在后面代码里有
address | value |
0X20 | 0XFC |
0X21 | 0X98 |
0X22 | 0XBF |
0X23 | 0X00 |
0X24 | 0X18 |
0X25 | 0XC0 |
0X26 | 0X9D |
0X27 | 0X7C |
0X28 | 0X11 |
0X29 | 0X37 |
0X2A | 0X0D |
0X2B | 0X2 |
二、上电驱动流程
三、踩的坑
1、如果你用iic写寄存器去驱动电机速度,就要把speed引脚给悬空,如果接地则转不了,因为speed可以通过输入信号去控制速度。
2、电机的uvw三相,地接上也不能转,这个可能因电机而异,我这个是这样。
四、电机寄存器读写
1、写电机寄存器
2、寄存器写入EEPROM固化
在加载寄存器之后,下一步是将它们写入EEPROM,这样设备就可以维护这些设置。图中描述了写入EEPROM的命令链。首先,输入程序键(0xB6)在设备控制寄存器(0x02),然后立即,在EEPROM控制寄存器(0x03)中设置eeWrite bit到1(0x50)。如果eeWrite位在程序键进入后没有直接设置,则程序键将被重置。
3、读取寄存器值
上电默认会将EEPRO里的值刷新到寄存器,写这个寄存器也能刷新
五、代码驱动部分
上述的寄存器读写和固化以及电机驱动代码都已经写好了。
#include <stdio.h>
#include "xparameters.h"
#include "netif/xadapter.h"
#include "xil_printf.h"
#include "sleep.h"
#include "xil_cache.h"
//#include "hdl_ps_iic.h"
#include "hdl_i2cps_polled.h"
#include "motor.h"
#include "data.h"
u8 M1,M2,M3,S1,S2,S3,S4,S5,S6,S7,S8,S9;
static XIicPs I2cInst0;
I2C_ADDR8 I2C_WINST_8ps;
I2C_ADDR8 I2C_RINST_8ps;
/**************************************************
* 功能:PS IIC初始化
* 返回值:无
* 说明: I2C初始化
***************************************************/
void IIC_init(void)
{
u8 n = i2cps_init(&I2cInst0, IIC_DEVICE_ID0, 50*1000);//initial ps i2c controller
}
u8 DRV10983_REG_single_READ(u8 address)//单次读一个寄存器值
{
//24c02 2kbits read all
I2C_RINST_8ps.reg_addr=address;
i2cps_rd8(&I2cInst0, 0x52, &I2C_RINST_8ps, 1);
return I2C_RINST_8ps.reg_buf;
//return 0;
}
void DRV10983_REG_single_WRITE(u8 address,u8 Value)//这是用指令进行单次写一个寄存器值,会刷新到eeprom
{
//使能sidata写位
I2C_WINST_8ps.reg_addr= EECtrl;
I2C_WINST_8ps.reg_buf = 0x40;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
usleep(1000);
//写寄存器值
I2C_WINST_8ps.reg_addr= address;
I2C_WINST_8ps.reg_buf = Value;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
usleep(1000);
//写入电机芯片的EEPROM缓存,此后得延时24ms,才能进行新的一次刷新
I2C_WINST_8ps.reg_addr= DevCtrl;
I2C_WINST_8ps.reg_buf = 0xB6;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
usleep(1000);
I2C_WINST_8ps.reg_addr= EECtrl;
I2C_WINST_8ps.reg_buf = 0x50;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
usleep(25000);
}
void IIC_WD(u8 address,u8 Value)//只是往寄存器写,不会刷新到eeprom
{
I2C_WINST_8ps.reg_addr= address;
I2C_WINST_8ps.reg_buf = Value;
// u8 Data;
// u8 *SendBufferPtr;
// SendBufferPtr = &I2C_WINST_8ps;
// Data = *SendBufferPtr;
// SendBufferPtr += 1;
// Data = *SendBufferPtr;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
}
void DRV10983_all_REG_READ(void)//串口打印所有配置寄存器的值
{
M1=DRV10983_REG_single_READ(MotorParam1);
M2=DRV10983_REG_single_READ(MotorParam2);
M3=DRV10983_REG_single_READ(MotorParam3);
S1=DRV10983_REG_single_READ(SysOpt1);
S2=DRV10983_REG_single_READ(SysOpt2);
S3=DRV10983_REG_single_READ(SysOpt3);
S4=DRV10983_REG_single_READ(SysOpt4);
S5=DRV10983_REG_single_READ(SysOpt5);
S6=DRV10983_REG_single_READ(SysOpt6);
S7=DRV10983_REG_single_READ(SysOpt7);
S8=DRV10983_REG_single_READ(SysOpt8);
S9=DRV10983_REG_single_READ(SysOpt9);
// xil_printf(" MotorParam1-%X\n",M1);
// xil_printf(" MotorParam2-%X\n",M2);
// xil_printf(" MotorParam3-%X\n",M3);
// xil_printf(" SysOpt1-%X\n",S1);
// xil_printf(" SysOpt2-%X\n",S2);
// xil_printf(" SysOpt3-%X\n",S3);
// xil_printf(" SysOpt4-%X\n",S4);
// xil_printf(" SysOpt5-%X\n",S5);
// xil_printf(" SysOpt6-%X\n",S6);
// xil_printf(" SysOpt7-%X\n",S7);
// xil_printf(" SysOpt8-%X\n",S8);
// xil_printf(" SysOpt9-%X\n",S9);
}
void motor_initj(void)//竞品配置
{
IIC_WD(EECtrl, 0x40);//写sidata位
IIC_WD(MotorParam1, 0XFC);//相间电阻14.8欧姆,驱动电机的输出的频率是50Hz
IIC_WD(MotorParam2, 0X98);//含有BEMF速度常数14.6mV/Hz,闭环调节模式设置为半周期调节
IIC_WD(MotorParam3, 0XBF);//换相提前角(供电电压相位提前与BEMF电压)设置为基于供电和电机速度动态匹配
IIC_WD(SysOpt1, 0X00);//不做初始速度检测ISD,直接跳到判断制动使能,不会做反向驱动
IIC_WD(SysOpt2, 0X18);//对齐开环电流:0.2A;开环电流上升速率:0.7 VCC/s;关闭制动(no break)
IIC_WD(SysOpt3, 0XC0);//闭环控制反馈系数:1;开环加速一阶二阶都为最快档位,即最快加速到闭环速度
IIC_WD(SysOpt4, 0X9D);//电机最大转速的1/3作为进入闭环的阈值速度;对齐时间设置为0.16s
//异常检测都打开;
//AVS打开,设置为BEMF电压到达VCC时开启限制降速,此功能作用是当速度急速下降时,电机自己产生的BEMF电压可能会高于VCC;
//IPD释放模式:循环模式
IIC_WD(SysOpt5, 0X7C);
IIC_WD(SysOpt6, 0X11);//加速电流限制阈值0.2A;电流阈值0A:超过则停止转动(没有使能)
IIC_WD(SysOpt7, 0X37);//闭环加速限制0.77VCC/s;死区时间24V电压建议为400ns,12V电压建议为360ns,我们是8v用的320ns
IIC_WD(SysOpt8, 0X0D);//关闭初始位置检测;稳压器电压选择3.3V;IPD释放模式为“循环模式”下电流衰减到0的时间:12Hz(没有开启IPD)
IIC_WD(SysOpt9, 0X2C);//在开环和闭环都输出FG;FG设置为2个周期对应一个脉冲(可以按需设置);异常Kt检测的阈值:2Kt~1/2Kt;速度输入模式为PWM输入;达到速度阈值进入闭环
//写电机速度
IIC_WD(0X01,0X80);
IIC_WD(0X00,0X6F);
//写入电机芯片的EEPROM缓存,此后得延时24ms,才能进行新的一次刷新
I2C_WINST_8ps.reg_addr= DevCtrl;
I2C_WINST_8ps.reg_buf = 0xB6;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
usleep(10000);
I2C_WINST_8ps.reg_addr= EECtrl;
I2C_WINST_8ps.reg_buf = 0x10;
i2cps_wr8(&I2cInst0, 0x52, &I2C_WINST_8ps, 1);
usleep(25000);
}
float get_xiafen_speed(void)
{
u32 speed_r=0;
float xiafen_speed = 0;
speed_r = Xil_In32(REG_SPEED);
if(speed_r == 0)
{
xiafen_speed = 0;
}
else
{
xiafen_speed = 100000000.0/speed_r; //REG_SPEED地址获取的是360度以10ns为单位的时钟数量,也就是一圈的时间
}
return xiafen_speed;
}
float get_motor_speed(void)
{
u16 M1,M2;
float motorspeed = 0;
M1=DRV10983_REG_single_READ(0X11);
M2=DRV10983_REG_single_READ(0X12);
motorspeed = ((M1<<8)|M2)/40.0;
return motorspeed;
}
void set_xiafen_speed(float xia_speed)
{
u16 motor_speed = 0;
if(xia_speed<0)//设定速率在2~20之间,做一个超值保护
{
xia_speed = 0;
}
else if(xia_speed>20)
{
xia_speed = 20;
}
Motor_stru.xiafen_set_speed = xia_speed;
Motor_stru.flag = 1;
motor_speed = ((int)(50+xia_speed*20))|0X8000;//计算电机速度,,轮转比为60比11,但是实际跑就是设置250输入给电机驱动芯片,对应就是20Hz
Motor_stru.reg_data = motor_speed;
IIC_WD(0X01,motor_speed>>8);
IIC_WD(0X00,motor_speed);
}