📄 medium_event.c
字号:
/**********************************************************************
* 程序说明
*
* 该文件包含中等速率事件处理程序及其相关得函数,中等速率事件每10毫秒
* 执行一次电压和速度控制循环在这里完成。
**********************************************************************/
#include "general.h"
#include "hardware.h"
#include "defs.h"
#include "extern_globals.h"
void medium_event_handler(void);
void speed_loop(void);
void voltage_control(void);
void starting_code(void);
extern void debounce_switches(void);
//中等事件处理
void medium_event_handler(void)
{
long ltemp;
int itemp;
// MED_EVENT_RATE设为10mSec,参见defs.h
if (medium_speed_event_count > MED_EVENT_RATE)
{
medium_speed_event_count=0;
debounce_switches();
//判断从获取(acquistion)到无刷(sensorless)转换后是否处于锁定周期,
//如是(check_counter>0)则假定速度与最后的速度相同
if (check_counter)
rpm=user_parameters[7];
else
{
asm("disi #5");
ltemp=((unsigned long)user_parameters[25] \
*(unsigned long)period_measurement);
if (ltemp < (COUNTER_RATE*60/65535))
rpm=65535;
else
rpm = COUNTER_RATE*60/ltemp;
}
if (run_state!=RUNNING) stall_counter=0;
// 检测是否超速
if (!trip_state)
{
if ((rpm>user_parameters[14]) && (control_flags.SENSORLESS))
{
DISABLE_FIRING;
run_state=FAULT;
trip_state=OVER_SPEED;
}
if (stall_counter>user_parameters[13])
{
DISABLE_FIRING;
run_state=FAULT;
trip_state=STALLED;
}
else
stall_counter++;
}
// 计算相位超前
if (rpm < user_parameters[11])
{
phase_advance=TIME_CORRECTION;
}
else
{
ltemp=(long)(rpm-user_parameters[11])*user_parameters[12];
phase_advance=((ltemp*period_measurement)/180000)+TIME_CORRECTION;
}
if (control_flags.SENSORLESS==TRUE) speed_loop();
voltage_control();
if (run_state==STARTING) starting_code();
}
return;
}
// 速度控制子程序,当速度控制模式是开环是,不考虑PI.
// 如果是OPEN_VOLTS模式,PWM波的占空比直接由电位器控制
// 如果是OPEN_CURRENT模式,电流控制来自电位器
// 如果是CLOSED_VOLTS模式,PWM波的占空比直接由速度环输出控制
// 如果是CLOSED_CURRENT模式,速度环输出即是电流控制输入环
void speed_loop(void)
{
static long speed_integral;
int speed_error;
long proportional_term, pos_wloop_limit, neg_wloop_limit;
int control_output,scaled_demand;
long temp;
#ifdef DEBUG
asm("bset LATG,#2");
#endif
if ((run_state != RUNNING) || (check_counter))
{
speed_integral=0;
return;
}
switch (user_parameters[1])
{
case OPEN_VOLTS: speed_integral=0;
//禁止PWM刷新
PWMCON2bits.UDIS=1;
scaled_demand=filtered_pot/user_parameters[37];
//做补偿
if (scaled_demand > FULL_DUTY) PDC1=0;
else PDC1=FULL_DUTY-scaled_demand;
PDC2=PDC1;
PDC3=PDC1;
//使能PWM刷新
PWMCON2bits.UDIS=0;
return;
break;
case OPEN_CURRENT:speed_integral=0;
scaled_demand=filtered_pot/user_parameters[38];
if (scaled_demand >= (current_trip-ibus_offset))
current_demand=current_trip-ibus_offset;
else
current_demand=scaled_demand;
return;
break;
case CLOSED_VOLTS:
//电流循环用到占空比缩放比例为*512,这里要*16384,比例为32,故*32
pos_wloop_limit=pos_duty_limit*32;
neg_wloop_limit=neg_duty_limit*32;
break;
case CLOSED_CURRENT:
pos_wloop_limit=pos_current_limit;
neg_wloop_limit=neg_current_limit;
break;
}
speed_demand=filtered_pot*user_parameters[39];
control_flags.TORQUE_LIMIT=FALSE;
speed_error=speed_demand-rpm;
proportional_term=((long)speed_error*(long)wloop_p_gain);
if (proportional_term > pos_wloop_limit)
{
control_flags.TORQUE_LIMIT=TRUE;
control_output=pos_wloop_limit/16384;
if (user_parameters[1]==CLOSED_VOLTS)
control_output+=ZERO_DUTY;
speed_integral=0;
}
else
{
if (proportional_term < neg_wloop_limit)
{
control_flags.TORQUE_LIMIT=TRUE;
control_output=neg_wloop_limit/16384;
if (user_parameters[1]==CLOSED_VOLTS)
control_output+=ZERO_DUTY;
speed_integral=0;
}
}
//计算I项
if (control_flags.TORQUE_LIMIT==FALSE)
{
speed_integral+=((long)speed_error * (long)wloop_i_gain);
temp=speed_integral+proportional_term;
if (temp > pos_wloop_limit)
{
control_flags.TORQUE_LIMIT=TRUE;
control_output=pos_wloop_limit/16384;
if (user_parameters[1]==CLOSED_VOLTS)
control_output+=ZERO_DUTY;
//计算I项的限制
speed_integral = pos_wloop_limit - proportional_term;
}
else
{
if (temp < neg_wloop_limit)
{
control_flags.TORQUE_LIMIT=TRUE;
control_output=(neg_wloop_limit/16384);
if (user_parameters[1]==CLOSED_VOLTS)
control_output+=ZERO_DUTY;
speed_integral=neg_wloop_limit - proportional_term;
}
else
//基于P、I项计算输出
{
control_output=(temp/16384);
if (user_parameters[1]==CLOSED_VOLTS)
control_output+=ZERO_DUTY;
}
}
}
if (user_parameters[1]==CLOSED_VOLTS)
{
if (control_output < 0) control_output=0;
//禁止PWM占空比寄存器刷新
PWMCON2bits.UDIS=1;
//把值放入占空比寄存器刷新
control_output=FULL_DUTY-control_output;
PDC1=(unsigned int)control_output;
PDC2=(unsigned int)control_output;
PDC3=(unsigned int)control_output;
//允许PWM占空比寄存器刷新
PWMCON2bits.UDIS=0;
}
else
{
current_demand=control_output;
}
return;
}
// 电压控制子程序,TIMER3用于产生PWM
void voltage_control(void)
{
static long voltage_integral;
int voltage_error;
long proportional_term;
long temp;
if ((run_state != RUNNING) && (run_state != STARTING))
{
voltage_integral=0;
return;
}
if(IEC0bits.T3IE)
{
IEC0bits.T3IE=0;
// BRAKE_FIRE=0;
}
//计算电压误差和比例
voltage_error=filtered_vdc-voltage_demand;
proportional_term=((long)voltage_error*(long)vloop_p_gain);
if (proportional_term > POS_V_LIMIT)
{
voltage_integral=0;
return;
}
else
{
// 电压误差负饱和值为-10,即满度的1%
if (voltage_error < -10)
{
voltage_integral=0;
return;
}
}
// 更新I项
voltage_integral+=((long)voltage_error * (long)vloop_i_gain);
temp=voltage_integral+proportional_term;
//P+I大于正极限
if (temp > POS_V_LIMIT)
{
voltage_integral = POS_V_LIMIT - proportional_term;
return;
}
else
{
//P+I小于负极限
if (temp <= 0)
{
voltage_integral = 0 - proportional_term;
return;
}
else
//计算输出
{
PR3=(unsigned int)(temp/512);
TMR3=0;
//允许 Timer3运行,当TMR3=PR3时触发中断
IFS0bits.T3IF=0;
IEC0bits.T3IE=1;
}
}
return;
}
//起动代码子程序
void starting_code(void)
{
unsigned int temp;
unsigned long ltemp;
static unsigned int rotation_timer=0;
// 检查马达是否已经旋转
if (control_flags2.ROTATION_CHECK==TRUE)
{
DISABLE_INTERRUPTS;
control_flags.ACQUIRE2=TRUE;
control_flags.ADCCONFIG=TRUE;
control_flags2.ROTATION_CHECK=FALSE;
ENABLE_INTERRUPTS;
rotation_timer=user_parameters[36];
return;
}
if ((control_flags.ACQUIRE2==TRUE) && (rotation_timer))
{
rotation_timer--;
return;
}
else
{
control_flags.ACQUIRE2=FALSE;
}
// 检查自转
if (control_flags2.WINDMILLING==TRUE)
{
if (new_PR2 < BRAKING_PR2_LIMIT)
{
new_PR2+=windmilling_decel_rate;
return;
}
else
{
DISABLE_INTERRUPTS;
control_flags2.WINDMILLING=FALSE;
control_flags.DIR=user_parameters[0];
IEC0bits.T2IE=0;
control_flags.RAMP=FALSE;
control_flags.LOCK1=FALSE;
control_flags.LOCK2=FALSE;
ENABLE_INTERRUPTS;
}
}
// 进入加速区
if (control_flags.RAMP==TRUE)
{
// 下面的语句用汇编写,主要是为了mul.us和div.sd指令,由于与ANSI C兼容问题编译器没有提供
// 要做的计算是:
// new_speed= ramp_start_speed + (ramp_speed_delta*(starting_timer/ramp_time)^2)
// temp = ramp_start_demand + (ramp_demand_delta*starting_timer/ramp_time)
// 首先把w0-w5压栈,以便编译器用来保存立即数,在后面的C程序中调用。
#define V120 1
#ifdef ORIG
asm(" push.d w0");
asm(" push.d w2");
asm(" push.d w4");
asm(" mov.w _starting_timer,w1");
asm(" mov.w _starting_timer,w0");
asm(" mul.uu w0,w1,w4");
asm(" mov.w _ramp_time,w2");
asm(" repeat #17");
asm(" div.ud w4,w2");
asm(" mov.w _ramp_speed_delta,w1");
asm(" mul.uu w0,w1,w4");
asm(" repeat #17");
asm(" div.ud w4,w2");
asm(" mov.w _ramp_start_speed,w1");
asm(" add w0,w1,w0");
asm(" mov.w w0,_new_speed");
asm(" mov.w _ramp_demand_delta,w1");
asm(" mov.w _starting_timer,w0");
asm(" mul.us w0,w1,w4");
asm(" mov.w _ramp_time,w2");
asm(" repeat #17");
asm(" div.sd w4,w2");
asm(" mov.w w0,_stemp");
asm(" pop.d w4");
asm(" pop.d w2");
asm(" pop.d w0");
#elif V120
{ unsigned long mul_result;
register unsigned int div_result asm("w0");
/* asm("instruction(s)" : outputs : inputs :
clobbered registers ); */
asm volatile("mul.uu %1, %1, %0" : "=r"(mul_result) :
"r"(starting_timer));
asm volatile("repeat #17\n\t"
"div.ud %0, %1" : /* implied outputs */ : "r"(mul_result),
"r"(ramp_time) :
"w0", "w1" );
asm volatile("mul.uu %1, %2, %0":"=r"(mul_result) : "r"(div_result),
"r"(ramp_speed_delta));
asm volatile("repeat #17\n\t"
"div.ud %0, %1" : /* implied outputs */ : "r"(mul_result),
"r"(ramp_time) :
"w0", "w1" );
asm volatile("add %1, %2, %0" : "=r"(new_speed): "r"(ramp_start_speed),
"r"(div_result));
asm volatile("mul.us %1, %2, %0":"=r"(mul_result): "r"(starting_timer),
"r"(ramp_demand_delta));
asm volatile("repeat #17\n\t"
"div.ud %0, %1" : /* implied outputs */ : "r"(mul_result),
"r"(ramp_time) :
"w0", "w1" );
stemp = div_result;
}
#elif V130
{ unsigned long mul_result;
unsigned int div_result;
mul_result = __builtin_muluu(starting_timer, starting_timer);
div_result = __builtin_divud(mul_result, ramp_time);
mul_result = __builtin_muluu(div_result, ramp_speed_delta);
div_result = __builtin_divud(mul_result, ramp_time);
new_speed = div_result + ramp_start_speed;
mul_result =__builtin_mulus(starting_timer,ramp_demand_delta);
stemp = __builtin_divud(mul_result, ramp_time);
}
#else
#error Which version
#endif
temp=ramp_start_demand+stemp;
//使用电压控制,还是电流控制
if (user_parameters[40])
{
temp=FULL_DUTY-temp;
PWMCON2bits.UDIS=1;
PDC1=temp;
PDC2=temp;
PDC3=temp;
PWMCON2bits.UDIS=0;
}
else
current_demand=temp;
//计算新的PR2值
ltemp=(COUNTER_RATE*20) / \
((unsigned long)new_speed*(unsigned long)user_parameters[25]);
if (ltemp>65535)
new_PR2=65535;
else
new_PR2=ltemp;
// 检查用何种探测方法,如果用方法1,则new step rate < step rate
if ((user_parameters[43]==FALSE) && \
(new_PR2<=acquire1_enable_rate) && \
(control_flags.ACQUIRE1==FALSE))
{
control_flags2.ACQUIRE1_REQUEST=TRUE;
acquire_counter=0;
}
// 判断加速是否结束
if (new_PR2 <=ramp_end_rate)
{
DISABLE_INTERRUPTS;
control_flags.RAMP=FALSE;
DISABLE_FIRING;
IEC0bits.T2IE = 0;
// 检查用何种探测方法,如果用方法2,则关闭acquire_position函数
if (user_parameters[43]==TRUE)
{
control_flags.ACQUIRE2=TRUE;
control_flags.ADCCONFIG=TRUE;
control_flags2.RETRY_FLAG=FALSE;
run_state=RUNNING;
}
else //如是方法1,前面已经执行,结束加速,进入错误状态
{
run_state=FAULT;
trip_state=FAILED_TO_START;
}
ENABLE_INTERRUPTS;
return;
}
}
//进入锁存子程序
if ((control_flags.LOCK1==FALSE) && (control_flags.LOCK2==FALSE))
{
if (control_flags.RAMP==FALSE)
{
starting_timer=0;
control_flags.LOCK1=TRUE;
// 判断是用电流还是电压控制
if (user_parameters[40])
{
PWMCON2bits.UDIS=1;
PDC1=(FULL_DUTY-hold1_demand);
PDC2=PDC1;
PDC3=PDC1;
PWMCON2bits.UDIS=0;
}
else
current_demand=hold1_demand;
OVDCON=SECTOR0_OVERRIDE;
ENABLE_FIRING;
}
}
// LOCK1时间结束
if ((starting_timer >= user_parameters[2]) \
&& (control_flags.LOCK1==TRUE))
{
starting_timer=0;
control_flags.LOCK1=FALSE;
control_flags.LOCK2=TRUE;
//使用电压控制
if (user_parameters[40])
{
PWMCON2bits.UDIS=1;
PDC1=(FULL_DUTY-hold2_demand);
PDC2=PDC1;
PDC3=PDC1;
PWMCON2bits.UDIS=0;
}
else
current_demand=hold2_demand;
if (control_flags.DIR==FORWARDS)
OVDCON=SECTOR1_OVERRIDE;
else
OVDCON=SECTOR5_OVERRIDE;
}
// LOCK2时间结束
if ((starting_timer > user_parameters[3]) \
&& (control_flags.LOCK2==TRUE))
{
control_flags.LOCK2=FALSE;
control_flags.RAMP=TRUE;
starting_timer=0;
// 采用电压控制
if (user_parameters[40])
{
PWMCON2bits.UDIS=1;
PDC1=(FULL_DUTY-ramp_start_demand);
PDC2=PDC1;
PDC3=PDC1;
PWMCON2bits.UDIS=0;
}
else
current_demand=ramp_start_demand;
// 检查用何种探测方法,如果用方法1,则ramp speed > speed
if ((user_parameters[43]==FALSE) && \
(ramp_start_rate<=acquire1_enable_rate))
{
control_flags2.ACQUIRE1_REQUEST=TRUE;
acquire_counter=0;
}
//写sector值,保证正确换向
sector=3;
//给new_PR2赋新值,使能中断
new_PR2=ramp_start_rate;
IFS0bits.T2IF=TRUE;
IEC0bits.T2IE=TRUE;
}
starting_timer++;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -