typedef struct {
//! What part of the speed ramp we are in.
u8 run_state ;
//! Direction stepper motor should move.
u8 dir ;
//! Peroid of next timer delay. At start this value set the accelration rate.
s32 step_delay;
//! What step_pos to start decelaration
u32 decel_start;
//! Sets deceleration rate.
s32 decel_val;
//! Minimum time delay (max speed)
s32 min_delay;
//! Counter used when accelerateing/decelerateing to calculate step_delay.
s32 accel_count;
} speedRampData;
GPIO_InitTypeDef GPIO_InitStructure;
#define T1_FREQ 1000000
#define SPR 1600
// Maths constants. To simplify maths when calculating in AxisMoveRel().
#define ALPHA (2*3.14159/SPR) // 2*pi/spr
#define A_T_x100 ((long)(ALPHA*T1_FREQ*100)) // (ALPHA / T1_FREQ)*100
#define T1_FREQ_148 ((int)((T1_FREQ*0.676)/100)) // divided by 100 and scaled by 0.676
#define A_SQ (long)(ALPHA*2*100000*100000) //
#define A_x20000 (int)(ALPHA*20000) // ALPHA*20000
// Speed ramp states
#define STOP 0
#define ACCEL 1
#define DECEL 2
#define RUN 3
//設置向量表的位置和偏移
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //向量表位于RAM
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //向量表位于FLASH
#endif
}
break;
case FASTSEEKSTOP:
break;
case FASTSEEKBACK:
if(!MotionStatus[axis])
{
switch(axis)
{
case 0:
EnableHomeCapture1;
break;
case 1:
EnableHomeCapture2;
break;
case 2:
EnableHomeCapture3;
break;
case 3:
EnableHomeCapture4;
break;
}
AxisMoveRel(axis+1, 0x7FFFFFFF*ZeroDir[axis], accel[axis], decel[axis], HomeSlowSpeed[axis]);
ZeroStep[axis]=SLOWSEEK;
}
break;
case SLOWSEEK:
if(!MotionStatus[axis])
{
if(bZeroCapture[axis])
{
ZeroStep[axis]=MOVETOZERO;
bZeroCapture[axis]=FALSE;
AxisMoveRel(axis+1, (position[axis]-HomePos[axis]+ZeroOffset[axis])*ZeroDir[axis]*-1, accel[axis], decel[axis], HomeFastSpeed[axis]);
}
else
{
ZeroStep[axis]=IDEL;
}
}
break;
case SLOWSEEKSTOP:
break;
case MOVETOZERO:
if(!MotionStatus[axis])
{
ZeroStep[axis]=IDEL;
position[axis]=0;
}
break;
}
}
void AxisMoveAbs(u32 axis, s32 step, u32 accel, u32 decel, u32 speed)//絕對運動,axis參數是軸號,step是目標位置,accel是加速度,decel是減速度,speed是速度
{
//! Number of steps before we hit max speed.
u32 max_s_lim;
//! Number of steps before we must start deceleration (if accel does not hit max speed).
u32 accel_lim;
float ftemp=0.0;
if(step == 1)
{
// Move one step...
srd[axis-1].accel_count = -1;
// ...in DECEL state.
srd[axis-1].run_state = DECEL;
// Just a short delay so main() can act on 'running'.
srd[axis-1].step_delay = 1000;
switch(axis)
{
case 1:
TIM2->CCR1=10;
TIM2->ARR=10;
break;
case 2:
TIM3->CCR1=10;
TIM3->ARR=10;
break;
case 3:
TIM4->CCR1=10;
TIM4->ARR=10;
break;
case 4:
TIM5->CCR1=10;
TIM5->ARR=10;
break;
}
MotionStatus[axis-1] = 1;
switch(axis)
{
case 1:
TIM_Cmd(TIM2, ENABLE);
break;
case 2:
TIM_Cmd(TIM3, ENABLE);
break;
case 3:
TIM_Cmd(TIM4, ENABLE);
break;
case 4:
TIM_Cmd(TIM5, ENABLE);
break;
}
}
// Only move if number of steps to move is not zero.
else if(step != 0)
{
// Refer to documentation for detailed information about these calculations.
// Set max speed limit, by calc min_delay to use in timer.
// min_delay = (alpha / tt)/ w
srd[axis-1].min_delay = T1_FREQ/speed/2;
// Set accelration by calc the first (c0) step delay .
// step_delay = 1/tt * sqrt(2*alpha/accel)
// step_delay = ( tfreq*0.676/100 )*100 * sqrt( (2*alpha*10000000000) / (accel*100) )/10000
srd[axis-1].step_delay = ((long)T1_FREQ*0.676* sqrt(2000000 / accel))/1000/2;
// Find out after how many steps does the speed hit the max speed limit.
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = speed*speed/(2*accel);
// If we hit max speed limit before 0,5 step it will round to 0.
// But in practice we need to move atleast 1 step to get any speed at all.
if(max_s_lim == 0){
max_s_lim = 1;
}
// Find out after how many steps we must start deceleration.
// n1 = (n1+n2)decel / (accel + decel)
if((accel+decel)>step)
{
// accel_lim = step*decel/(accel+decel);
ftemp=(float)decel/(float)(accel+decel);
accel_lim = (float)step*ftemp;
}
else
{
accel_lim = step/(accel+decel)*decel;
}
// We must accelrate at least 1 step before we can start deceleration.
if(accel_lim == 0){
accel_lim = 1;
}
// Use the limit we hit first to calc decel.
if(accel_lim <= max_s_lim){
srd[axis-1].decel_val = accel_lim - step;
}
else{
srd[axis-1].decel_val =-(s32)(max_s_lim*accel/decel);
}
// We must decelrate at least 1 step to stop.
if(srd[axis-1].decel_val == 0){
srd[axis-1].decel_val = -1;
}
// If the maximum speed is so low that we dont need to go via accelration state.
if(srd[axis-1].step_delay <= srd[axis-1].min_delay)
{
srd[axis-1].step_delay = srd[axis-1].min_delay;
srd[axis-1].run_state = RUN;
}
else{
srd[axis-1].run_state = ACCEL;
}
// Reset counter.
srd[axis-1].accel_count = 0;
MotionStatus[axis-1] = 1;
//OCR1A = 10;
switch(axis)
{
case 1:
TIM2->CCR1=10;
TIM2->ARR=10;
break;
case 2:
TIM3->CCR1=10;
TIM3->ARR=10;
break;
case 3:
TIM4->CCR1=10;
TIM4->ARR=10;
break;
case 4:
TIM5->CCR1=10;
TIM5->ARR=10;
break;
}
// Set Timer/Counter to divide clock by 8
//TCCR1B |= ((0<<CS12)|(1<<CS11)|(0<<CS10));
switch(axis)
{
case 1:
TIM_Cmd(TIM2, ENABLE);
break;
case 2:
TIM_Cmd(TIM3, ENABLE);
break;
case 3:
TIM_Cmd(TIM4, ENABLE);
break;
case 4:
TIM_Cmd(TIM5, ENABLE);
break;
}
}
}
void AxisMoveRel(u32 axis, s32 step, u32 accel, u32 decel, u32 speed)//相對運動
{
//! Number of steps before we hit max speed.
u32 max_s_lim;
//! Number of steps before we must start deceleration (if accel does not hit max speed).
u32 accel_lim;
float ftemp=0.0;
if(step == 1)
{
// Move one step...
srd[axis-1].accel_count = -1;
// ...in DECEL state.
srd[axis-1].run_state = DECEL;
// Just a short delay so main() can act on 'running'.
srd[axis-1].step_delay = 1000;
switch(axis)
{
case 1:
TIM2->CCR1=10;
TIM2->ARR=10;
break;
case 2:
TIM3->CCR1=10;
TIM3->ARR=10;
break;
case 3:
TIM4->CCR1=10;
TIM4->ARR=10;
break;
case 4:
TIM5->CCR1=10;
TIM5->ARR=10;
break;
}
MotionStatus[axis-1] = 1;
switch(axis)
{
case 1:
TIM_Cmd(TIM2, ENABLE);
break;
case 2:
TIM_Cmd(TIM3, ENABLE);
break;
case 3:
TIM_Cmd(TIM4, ENABLE);
break;
case 4:
TIM_Cmd(TIM5, ENABLE);
break;
}
}
// Only move if number of steps to move is not zero.
else if(step != 0)
{
// Refer to documentation for detailed information about these calculations.
// Set max speed limit, by calc min_delay to use in timer.
// min_delay = (alpha / tt)/ w
srd[axis-1].min_delay = T1_FREQ/speed/2;
// Set accelration by calc the first (c0) step delay .
// step_delay = 1/tt * sqrt(2*alpha/accel)
// step_delay = ( tfreq*0.676/100 )*100 * sqrt( (2*alpha*10000000000) / (accel*100) )/10000
srd[axis-1].step_delay = ((long)T1_FREQ*0.676* sqrt(2000000 / accel))/1000/2;
// Find out after how many steps does the speed hit the max speed limit.
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = speed*speed/(2*accel);
// If we hit max speed limit before 0,5 step it will round to 0.
// But in practice we need to move atleast 1 step to get any speed at all.
if(max_s_lim == 0){
max_s_lim = 1;
}
// Find out after how many steps we must start deceleration.
// n1 = (n1+n2)decel / (accel + decel)
if((accel+decel)>step)
{
// accel_lim = step*decel/(accel+decel);
ftemp=(float)decel/(float)(accel+decel);
accel_lim = (float)step*ftemp;
}
else
{
accel_lim = step/(accel+decel)*decel;
}
// We must accelrate at least 1 step before we can start deceleration.
if(accel_lim == 0){
accel_lim = 1;
}
// Use the limit we hit first to calc decel.
if(accel_lim <= max_s_lim){
srd[axis-1].decel_val = accel_lim - step;
}
else{
srd[axis-1].decel_val =-(s32)(max_s_lim*accel/decel);
}
// We must decelrate at least 1 step to stop.
if(srd[axis-1].decel_val == 0){
srd[axis-1].decel_val = -1;
}
// If the maximum speed is so low that we dont need to go via accelration state.
if(srd[axis-1].step_delay <= srd[axis-1].min_delay)
{
srd[axis-1].step_delay = srd[axis-1].min_delay;
srd[axis-1].run_state = RUN;
}
else{
srd[axis-1].run_state = ACCEL;
}
// Reset counter.
srd[axis-1].accel_count = 0;
MotionStatus[axis-1] = 1;
//OCR1A = 10;
switch(axis)
{
case 1:
TIM2->CCR1=10;
TIM2->ARR=10;
break;
case 2:
TIM3->CCR1=10;
TIM3->ARR=10;
break;
case 3:
TIM4->CCR1=10;
TIM4->ARR=10;
break;
case 4:
TIM5->CCR1=10;
TIM5->ARR=10;
break;
}
// Set Timer/Counter to divide clock by 8
//TCCR1B |= ((0<<CS12)|(1<<CS11)|(0<<CS10));
switch(axis)
{
case 1:
TIM_Cmd(TIM2, ENABLE);
break;
case 2:
TIM_Cmd(TIM3, ENABLE);
break;
case 3:
TIM_Cmd(TIM4, ENABLE);
break;
case 4:
TIM_Cmd(TIM5, ENABLE);
break;
}
}
}
void TIM2_IRQHandler(void)//1軸定時器中斷處理
{
// Holds next delay period.
u16 new_step_delay;
// Remember the last step delay used when accelrating.
static u16 last_accel_delay;
// Counting steps when moving.
static u32 step_count = 0;
// Keep track of remainder from new_step-delay calculation to incrase accurancy
static s32 rest = 0;
static u8 i=0;
xr = 0; // clear result
q2 = 0x40000000L; // higest possible result bit
do
{
if((xr + q2) <= x)
{
x -= xr + q2;
f = 1; // set flag
}
else{
f = 0; // clear flag
}
xr >>= 1;
if(f){
xr += q2; // test flag
}
} while(q2 >>= 2); // shift twice
if(xr < x){
return xr +1; // add for rounding
}
else{
return xr;
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/