电机矢量控制程序实例(附代码)
EV技研
公众号EV技研作者1900 2019-8-13 电动汽车


 运行环境

 RX62T 低电压电机控制评估系统 

下面以瑞萨 RX62T 低电压电机控制评估系统 (RSSK)为例,介绍控制相关内容。RSSK 是以 24V 电机为对象,进行 120°/180° 通电,实施霍尔传感器 / 旋转编码器 / 无传感器控制的实验系统。程序中的变量在实际运行过程中的变 化可以通过 PC 显示,也可以通过低电压电机控制系 统的变量波形显示工具 ICS(In-Circuit Scope)显 示,有助于缩短开发时间(照片 1)。 


系统运行参数 

(1)电 机 ·电机转速:最低 600r/min,最高 2000r/min ·母线电压:24V ·电流:最大相电流为 1.8A (2)逆变器 ·载波频率:20kHz ·电流 / 电压控制:PI 控制(监测 U 相、V 相、 W 相电流,母线电压) ·编码器脉冲:输出轴每旋转 1 圈产生 300 个脉冲 (3)软 件 微处理器 RX62T 的资源分配参见表 1,软件结 构如图 2 所示。



 控制方法

 控制周期

 由于是矢量控制,根据 PWM 载波周期(20kHz) 的编码器输出信号,计算转子位置和转速,并调整 PWM 输出。速度控制(PI 运算)以 1ms 为周期, 读取编码器脉冲计数的累计值。运算处理的负荷很大,能否在规定时间内完成 运算处理十分重要。运算处理的时间概念如图 3 所 示。下面,我们来看看具体内容。


 每个载波周期的运算处理项目

 载波周期内的矢量控制运算,大致可以归纳为 以下几点。·获取 U、W 相电流(V 相电流通过计算得出), 逆变器母线电压 ·坐标变换(U,V,W → α, β → d, q) ·电流 PI 控制 ·非干涉控制 ·调制,坐标变换(d, q → α β → U,V,W) ·设定 PWM 输出占空比(U,V,W) 也就是说,将矢量控制插入载波周期中断。当然,所有的计算都不能超过周期,这是必须遵守的绝对条件。对于没有 FPU(浮点运算单元) 的微处理器,要在进行坐标变换时,设定固定的小 数点。另外, 微处理器的时钟频率要达到 50MHz 左右,才有足够的处理能力。使用 20MHz 左右的微 处理器进行控制时,要下调载波频率;或者放弃在 每个载波周期进行控制,每 3 个周期进行一次矢量 控制。 

 运算的输入参数

 (1)编码器输入 编码器检测速度、位置,输入 MTU3 的 MTCLKA、MTCLKB 进行计数(图 4)。


 编码器每转 动 1 圈输出 300 个脉冲,其脉冲沿计数不会超过:300×4 倍= 1200当计数达到 1200 时,计数器归零。这就是编码 器的设定方式。但是,根据编码器输入得到的是相对位置 (图5),应在电机启动时进行位置调整。其方法将 在后面的内容中介绍。 


(2)母线电压 母线电压变化时,电机驱动的正弦波的峰峰值 与有效值也会变化。因此,这需要反映到 PWM 输 出占空比控制。实际上,这就决定了正弦波输出有 效值的大小(图 6)。


(3)相电流 相电流的检测时间,是载波周期内 PWM 输出 切换后电流达到稳定时。PWM 载波周期为 20kHz(50μs)。这比 A-D 转 换时间 1μs 要大,而且,使用了编码器的控制,是 根据相电流来估算转子位置的。因此,A-D 转换开 始触发,即使在载波周期中断内启动软件也是完全 可以的(图6)。


 为了提高相电流的检测精度,可以放大信号, 使 A - D 转 换 器 工 作 于 极 致 状 态 ( 图 7 )。


 当 然 , 分流电阻损耗会增加。以 RSSK 为例,电阻值为 0.05Ω(50mΩ)。测量范围是 -10~+10A,信号经 5 倍放大后, 有效值为 1/2Vcc 时,电压为 -2.5~+2.5V。


程序实例1矢量控制——初始化部分

void R_MTR_InitHardware(void)

{

/*==========================*/

/* 初始化时钟 */

/*==========================*/

SYSTEM.SCKCR.BIT.ICK = 0x00; // ICLK : EXTAL×8 (96MHz) / EXTAL=12MHz

SYSTEM.SCKCR.BIT.PCK = 0x01; // PCLK : EXTAL×4 (48MHz) / EXTAL=12MHz

/*===========================*/

/* 初始化外设功能 */

/*===========================*/

MSTP_CMT0 = 0; // 模块停止状态被取消

MSTP_MTU = 0;

MSTP_S12AD0 = 0;

MSTP_S12AD1 = 0;

/*========================*/

/* 初始化 CMT0 */

/*========================*/

CMT.CMSTR0.BIT.STR0 = 0; // 停止 CMT0

CMT0.CMCR.BIT.CKS = 0; // 时钟 : PCLK/8 */

CMT0.CMCOR = 5999; // 设定间隔时间

CMT0.CMCR.BIT.CMIE = 1; // 比较匹配中段(CMI0) 使能

ICU.IPR[0x04].BIT.IPR = 13;

ICU.IR[28].BIT.IR = 0;

ICU.IER[0x03].BIT.IEN4 = 1;

/*===================================*/

/* 初始化 MTU3_3,MTU3_4 */

/*===================================*/

MTU.TSTRA.BYTE = 0x00; // 停止 MTU3

MTU3.TCR.BIT.TPSC = 0; // MTU3_3 时钟 : ICLK

MTU3.TCR.BIT.CKEG = 0;

MTU4.TCR.BIT.TPSC = 0; // MTU3_4 时钟 : ICLK

MTU4.TCR.BIT.CKEG = 0;

MTU.TGCRA.BIT.BDC = 0;

MTU3.TCNT = MTR_DEADTIME_SET; // 设定社区时间

MTU4.TCNT = 0;

MTU3.TGRB = MTR_HALF_CARRIER_SET; // 设定占空比

MTU4.TGRA = MTR_HALF_CARRIER_SET;

MTU4.TGRB = MTR_HALF_CARRIER_SET;

MTU3.TGRD = MTR_HALF_CARRIER_SET; // 设定占空比

MTU4.TGRC = MTR_HALF_CARRIER_SET;

MTU4.TGRD = MTR_HALF_CARRIER_SET;

MTU.TDDRA = MTR_DEADTIME_SET;

MTU.TCDRA = (uint16)(MTR_CARRIER_SET - MTR_DEADTIME_SET);

MTU.TCBRA = (uint16)(MTR_CARRIER_SET - MTR_DEADTIME_SET);

MTU3.TGRA = MTR_CARRIER_SET; // 设定载波周期

MTU3.TGRC = MTR_CARRIER_SET;

MTU.TOCR1A.BIT.PSYE = 0;

MTU.TOCR1A.BIT.OLSP = 1; // 正相:初始输出"L", 有效电平"H"

MTU.TOCR1A.BIT.OLSN = 1; // 反相:初始输出"H", 有效电平"H"

MTU3.TMDR1.BIT.MD = 14; // 互补PWM 模式

MTU3.TMDR1.BIT.BFA = 1; // TGRA 和TGRC 一起用于缓冲器换作

MTU3.TMDR1.BIT.BFB = 1; // TGRB 和TGRD 一起用于缓冲器换作

MTU4.TMDR1.BYTE = 0x00;

MTU.TOERA.BYTE = 0xC0; // PWM 输出禁止

MTU4.TSR.BIT.TCFV = 0; // 下溢中断(TGIA) 使能

MTU4.TIER.BIT.TCIEV = 1;

ICU.IPR[0x5A].BIT.IPR = 14;

ICU.IR[138].BIT.IR = 0;

ICU.IER[0x11].BIT.IEN2 = 1;

MTU.TITMRA.BIT.TITM = 0; // 设定中断跳过功能

MTU.TITCR1A.BIT.T4VCOR = 1;

MTU.TITCR1A.BIT.T4VEN = 1;

MTU.TSTRA.BYTE = 0xC0; // 启动 MTU3_3 和MTU3_4

/*********** for encoder ***********/

PORT3.ICR.BIT.B2 = 1; // B 相输入模式

PORT3.DDR.BIT.B2 = 0;

PORT3.ICR.BIT.B3 = 1; // A 相输入模式

PORT3.DDR.BIT.B3 = 0;

MTU1.TMDR1.BIT.MD = 4;

MTU1.TCR.BIT.CCLR = 1;

MTU1.TGRA = (uint16)(MTR_LOAD_ENCD_CNT - MTR_ENCD_CPR_MECH) + 1;

MTU.TSTRA.BIT.CST1 = 1;

/*=======================================*/

/* 初始化 POE3 */

/*=======================================*/

IOPORT.PFMPOE.BIT.POE0E = 1; // POE3 过电流设定

POE.ICSR1.BIT.POE0M = 0x00;

POE.ICSR1.BIT.PIE1 = 1;

ICU.IER[0x15].BIT.IEN2 = 1;

ICU.IPR[0x67].BIT.IPR = 15;

POE.OCSR1.BIT.OCE1 = 1;

POE.OCSR1.BIT.OIE1 = 1;

POE.POECR2.BIT.MTU3BDZE = 1;

POE.POECR2.BIT.MTU4ACZE = 1;

POE.POECR2.BIT.MTU4BDZE = 1;

/*=============================*/

/* 初始化 I/O 端品 */

/*=============================*/

/*************** inverter ***************/

PORT7.DDR.BIT.B1 = 1; // Up 输出模式

PORT7.DDR.BIT.B2 = 1; // Vp 输出模式

PORT7.DDR.BIT.B3 = 1; // Wp 输出模式

PORT7.DDR.BIT.B4 = 1; // Un 输出模式

PORT7.DDR.BIT.B5 = 1; // Vn 输出模式

PORT7.DDR.BIT.B6 = 1; // Wn 输出模式

PORT7.DR.BIT.B1 = 0; // Up = "L"

PORT7.DR.BIT.B2 = 0; // Vp = "L"

PORT7.DR.BIT.B3 = 0; // Wp = "L"

PORT7.DR.BIT.B4 = 0; // Un = "L"

PORT7.DR.BIT.B5 = 0; // Vn = "L"

PORT7.DR.BIT.B6 = 0; // Wn = "L"

/*************** A/D 转换器 ***************/

PORT4.ICR.BIT.B0 = 1; ADC

PORT4.ICR.BIT.B1 = 1;

PORT4.ICR.BIT.B2 = 1;

PORT4.ICR.BIT.B6 = 1;

/*==================================*/

/* 初始化 A/D 转换器 */

/*==================================*/

/*************** Unit0 (Iu,Iw,Vdc) ***************/

S12AD0.ADCSR.BIT.TRGE = 0; // 使用具有采样保持功能的单周期扫描模式

S12AD0.ADCSR.BIT.CKS = 3;

S12AD0.ADCSR.BIT.ADIE = 0;

S12AD0.ADCSR.BIT.ADCS = 1;

S12AD0.ADANS.BIT.CH = 2;

S12AD0.ADCER.BIT.SHBYP = 0;

S12AD0.ADCER.BIT.ADRFMT = 0;

/*************** Unit1 (VR1) ***************/

S12AD1.ADCSR.BIT.TRGE = 0; // 使用单一模式

S12AD1.ADCSR.BIT.CKS = 3;

S12AD1.ADCSR.BIT.ADIE = 0;

S12AD1.ADCSR.BIT.ADCS = 0;

S12AD1.ADANS.BIT.CH = 2;

S12AD1.ADCER.BIT.ADRFMT = 0;

/*========================*/

/* 初始化 WDT */

/*========================*/

WDT.WRITE.WINA = 0x5A00; // 使用看门狗定时器模式

WDT.WRITE.WINB = 0xA500;

WDT.WRITE.WINB = 0x5A5F;

WDT.WRITE.WINA = 0xA5FF;

}


程序2 每个载波周期的矢量控制

static void mtr_mtu4_interrupt(void)

{

fl oat32 f4_temp0;

fl oat32 f4_temp1;

fl oat32 f4_temp2;

/*=============================================*/

/* A/D : 电流和电压检测 */

/*=============================================*/

clrpsw_i();

mtr_get_iuiwvdc(&g_f4_iu_ad, &g_f4_iw_ad, &g_f4_vdc_ad);

setpsw_i();

g_f4_iu_ad = g_f4_iu_ad - MTR_ADC_SCALING;

g_f4_iw_ad = g_f4_iw_ad - MTR_ADC_SCALING;

g_f4_iu_ad = g_f4_iu_ad * MTR_CURRENT_SCALING; // U 相电流

g_f4_iw_ad = g_f4_iw_ad * MTR_CURRENT_SCALING; // W 相电流

/*** 电流偏差调整 ***/

if (g_u2_cnt_adjust == 100)

{

g_f4_iu_ad = -g_f4_iu_ad + g_f4_offset_iu;

g_f4_iw_ad = -g_f4_iw_ad + g_f4_offset_iw;

g_f4_iu_ad = g_f4_pre_iu_ad + MTR_CURRENT_LPF_K * (g_f4_iu_ad - g_f4_pre_iu_ad);

g_f4_pre_iu_ad = g_f4_iu_ad;

g_f4_iw_ad = g_f4_pre_iw_ad + MTR_CURRENT_LPF_K * (g_f4_iw_ad - g_f4_pre_iw_ad);

g_f4_pre_iw_ad = g_f4_iw_ad;

}

else

{

/*** 调整偏差 ***/

g_f4_offset_iu += MTR_CURRENT_LPF_K * (g_f4_iu_ad - g_f4_offset_iu);

g_f4_iu_ad = -g_f4_iu_ad + g_f4_offset_iu;

g_f4_offset_iw += MTR_CURRENT_LPF_K * (g_f4_iw_ad - g_f4_offset_iw);

g_f4_iw_ad = -g_f4_iw_ad + g_f4_offset_iw;

g_u2_cnt_adjust++;

if (g_u2_cnt_adjust >= 100)

{

g_u2_cnt_adjust = 100;

}

}

g_f4_iv_ad = - (g_f4_iu_ad + g_f4_iw_ad); // V 相电流

g_f4_vdc_ad = g_f4_vdc_ad * MTR_VDC_SCALING; // Vdc

/*============================*/

/* 检查误差 */

/*============================*/

mtr_error_check();

/*====================================*/

/* 速度和角度计量 */

/*====================================*/

mtr_angle_speed();

/*=============================================================*/

/* 坐标变换(UVW -> αβ ->dq) */

/*=============================================================*/

f4_temp0 = cosf(g_f4_angle_rad) * g_f4_iu_ad;

f4_temp1 = cosf(g_f4_angle_rad - (MTR_TWOPI / 3)) * g_f4_iv_ad;

f4_temp2 = cosf(g_f4_angle_rad + (MTR_TWOPI / 3)) * g_f4_iw_ad;

g_f4_id_lpf = MTR_SQRT_2_3 * (f4_temp0 + f4_temp1 + f4_temp2);

f4_temp0 = sinf(g_f4_angle_rad) * g_f4_iu_ad;

f4_temp1 = sinf(g_f4_angle_rad - (MTR_TWOPI / 3)) * g_f4_iv_ad;

f4_temp2 = sinf(g_f4_angle_rad + (MTR_TWOPI / 3)) * g_f4_iw_ad;

g_f4_iq_lpf = MTR_SQRT_2_3 * (f4_temp0 + f4_temp1 + f4_temp2);

g_f4_iq_lpf = -g_f4_iq_lpf;

/*============================*/

/* 电流 PI 控制 */

/*============================*/

/* d-axis */

vd.f4_diff = g_f4_id_ref - g_f4_id_lpf;

vd.f4_kp = g_f4_kp_id;

vd.f4_ki = g_f4_ki_id;

vd.f4_limit = g_f4_lim_vd;

vd.f4_ilimit = g_f4_ilim_vd;

g_f4_vd_ref = mtr_pi_ctrl( &vd );

/* q-axis */

vq.f4_diff = g_f4_iq_ref - g_f4_iq_lpf;

vq.f4_kp = g_f4_kp_iq;

vq.f4_ki = g_f4_ki_iq;

vq.f4_limit = g_f4_lim_vq;

vq.f4_ilimit = g_f4_ilim_vq;

g_f4_vq_ref = mtr_pi_ctrl( &vq );

/*============================*/

/* 解耦控制 */

/*============================*/

f4_temp0 = MTR_LQ * g_f4_iq_lpf; // Lq*iq

f4_temp0 = g_f4_ref_speed_rad * f4_temp0; // w*Lq*iq

g_f4_vd_ref = g_f4_vd_ref - f4_temp0; // -w*Lq*iq

f4_temp0 = MTR_LD * g_f4_id_lpf; // Ld*id

f4_temp0 = f4_temp0 + MTR_M; // Ld*id+Ke

f4_temp0 = g_f4_ref_speed_rad * f4_temp0; // w*(Ld*id+Ke)

g_f4_vq_ref = g_f4_vq_ref + f4_temp0; // +w*(Ld*id+Ke)

/* 坐标变换(dq -> UVW) */

/*================================================*/

f4_temp0 = cosf(g_f4_angle_rad) * g_f4_vd_ref;

f4_temp1 = sinf(g_f4_angle_rad) * g_f4_vq_ref;

g_f4_refu = MTR_SQRT_2_3 * (f4_temp0 - f4_temp1);

f4_temp0 = cosf(g_f4_angle_rad - (MTR_TWOPI / 3)) * g_f4_vd_ref;

f4_temp1 = sinf(g_f4_angle_rad - (MTR_TWOPI / 3)) * g_f4_vq_ref;

g_f4_refv = MTR_SQRT_2_3 * (f4_temp0 - f4_temp1);

f4_temp0 = cosf(g_f4_angle_rad + (MTR_TWOPI / 3)) * g_f4_vd_ref;

f4_temp1 = sinf(g_f4_angle_rad + (MTR_TWOPI / 3)) * g_f4_vq_ref;

g_f4_refw = MTR_SQRT_2_3 * (f4_temp0 - f4_temp1);

if (g_f4_refu < -g_f4_inv_limit)

{

g_f4_refu = -g_f4_inv_limit;

}

else if (g_f4_refu > g_f4_inv_limit)

{

g_f4_refu = g_f4_inv_limit;

}

else

{ }

if (g_f4_refv < -g_f4_inv_limit)

{

g_f4_refv = -g_f4_inv_limit;

}

else if (g_f4_refv > g_f4_inv_limit)

{

g_f4_refv = g_f4_inv_limit;

}

else

{ }

if (g_f4_refw < -g_f4_inv_limit)

{

g_f4_refw = -g_f4_inv_limit;

}

else if (g_f4_refw > g_f4_inv_limit)

{

g_f4_refw = g_f4_inv_limit;

}

else

{ }

/*==============================*/

/* PWM 参考值设定 */

/*==============================*/

mtr_inv_set_uvw(g_f4_refu, g_f4_refv, g_f4_refw, g_f4_vdc_ad);

mtr_clear_mtu4_fl ag();

}

void mtr_get_iuiwvdc(volatile fl oat32 *f4_iu_ad,

volatile fl oat32 *f4_iw_ad, volatile fl oat32 *f4_vdc_ad)

{

S12AD0.ADCSR.BIT.ADST = 1; // 开始转换

while (S12AD0.ADCSR.BIT.ADST == 1);

*f4_iu_ad = (fl oat32)S12AD0.ADDR0A;

*f4_iw_ad = (fl oat32)S12AD0.ADDR1;

*f4_vdc_ad = (fl oat32)S12AD0.ADDR2;

}

void mtr_inv_set_uvw(fl oat32 f4_u, fl oat32 f4_v, fl oat32 f4_w, fl oat32 f4_vdc)

{

fl oat32 f4_temp0, f4_temp1;

f4_temp0 = (fl oat32)(MTR_HALF_CARRIER_SET);

f4_temp1 = (f4_vdc / 2);

f4_u = -f4_u;

MTU3.TGRD = (uint16)(((f4_temp0 * f4_u) / f4_temp1) + f4_temp0);

// set U 相占空比设定

f4_v = -f4_v;

MTU4.TGRC = (uint16)(((f4_temp0 * f4_v) / f4_temp1) + f4_temp0);

// set V 相占空比设定

f4_w = -f4_w;

MTU4.TGRD = (uint16)(((f4_temp0 * f4_w) / f4_temp1) + f4_temp0);

// set W 相占空比设定

}

void mtr_angle_speed(void)

{

fl oat32 f4_temp_d_encd_tcnt;

fl oat32 f4_temp_speed_rad;

fl oat32 f4_temp;

g_f4_encd_tcnt = mtr_get_encd_tcnt();

if (g_f4_encd_tcnt == 0)

{

g_f4_encd_tcnt = MTR_LOAD_ENCD_CNT; // 编码器 : 0 -> 0x10000 */

}

if (MTR_ENCD_FOC_MODE == g_u2_run_mode)

{

f4_temp_d_encd_tcnt = g_f4_pre_encd_tcnt - g_f4_encd_tcnt;

if (f4_temp_d_encd_tcnt < 0)

{

f4_temp_d_encd_tcnt += MTR_ENCD_CPR_MECH;

}

g_f4_d_angle_rad = ((MTR_TWOPI * f4_temp_d_encd_tcnt) / MTR_ENCD_CPR_ELE);

/* 速度 */

f4_temp_speed_rad = (g_f4_d_angle_rad / MTR_CHECK_ENCD_PERIOD);

g_f4_speed_rad += MTR_SPEED_LPF_K * (f4_temp_speed_rad - g_f4_speed_rad);

/* LPF */

/* 角度 */

f4_temp = MTR_LOAD_ENCD_CNT - g_f4_encd_tcnt;

g_f4_angle_rad = ((MTR_TWOPI * f4_temp) / MTR_ENCD_CPR_ELE); /* angle: 0 to 7*2pi [rad] */

}

else

{

/* 速度 */

g_f4_speed_rad = 0;

if (0 == g_u1_fl ag_id_open)

{

/* 角度 */

g_f4_angle_rad = 0;

}

else if (1 == g_u1_fl ag_id_open)

{

/* 角度 */

g_f4_angle_rad = MTR_HALFPI;

}

}

g_f4_pre_encd_tcnt = g_f4_encd_tcnt;

}



1

END

1



往期精彩








来自 电动汽车

想参与大家的讨论?现在就 登录 或者 注册

插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
ID:{{user.uid}}
{{user.username}}
{{user.info.certsName}}
{{user.description}}
{{format("YYYY/MM/DD", user.toc)}}注册,{{fromNow(user.tlv)}}活动
{{submitted?"":"投诉"}}
请选择违规类型:
{{reason.description}}
支持的图片格式:jpg, jpeg, png