2F贴上步进电机控制的部分代码供参考!
#include "MotorController.h"
#include "MotorDriver.h"
extern TIM_HandleTypeDef htim2,htim1,htim5,htim8;
extern MotorInterFace MtDrvA; // 1
extern MotorInterFace MtDrvB; // 2
extern MotorInterFace MtDrvC; // 3
extern MotorInterFace MtDrvD; // 4
extern MotorInterFace MtDrvE; // 5
extern MotorInterFace MtDrvF; // 6
extern MotorInterFace MtDrvG; // 7
extern MotorInterFace MtDrvH; // 8
extern MotorInterFace MtDrvI; // 9
extern MotorInterFace MtDrvJ; // 10
extern MotorInterFace MtDrvK; // 11
extern MotorInterFace MtDrvL; // 12
extern MotorInterFace MtDrvM; // 13
extern MotorInterFace MtDrvN; // 14
extern MotorInterFace MtDrvO; // 15
extern MotorInterFace* MtDriver[15];
extern StepMotor* Motor[15];
//extern MotorDriver DrvA;
//extern MotorDriver DrvB;
//extern MotorDriver DrvC;
//extern MotorDriver DrvD;
//extern MotorDriver DrvE;
float KSin[257]= //20190116
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
float StepMotor::PidAdjust(float ErrIn)
{
float temi;
if(CntTime<1024) CntTime++;
if((ErrIn<0.00001)&&(ErrIn>-0.00001)) { temi=0; CntTime=0; }
else temi=-FdK*(ErrIn+PreK*(ErrIn-ErrInL));
ErrInLL=ErrInL;
ErrInL=ErrIn;
CalResult=temi;
return(temi);
}
float StepMotor::PidSinAdjust(float ErrIn)
{
float temi;
if(CntTime<1024) CntTime++;
if((ErrIn<0.00001)&&(ErrIn>-0.00001)) CntTime=0;
else temi=-FdK*KSin[CntTime/4]*(ErrIn+PreK*(ErrIn-ErrInL));
ErrInLL=ErrInL;
ErrInL=ErrIn;
CalResult=temi;
return(temi);
}
float StepMotor::PidSinFAdjust(float ErrIn)
{
float temi;
if(CntTime<512) CntTime++;
if((ErrIn<0.00001)&&(ErrIn>-0.00001)) CntTime=0;
else temi=-FdK*KSin[CntTime/2]*(ErrIn+PreK*(ErrIn-ErrInL));
ErrInLL=ErrInL;
ErrInL=ErrIn;
CalResult=temi;
return(temi);
}
void StepMotor::SetPar(float pFdK,float pPreK,float pPreKv)
{
FdK=pFdK;
PreK=pPreK;
PreKv=pPreKv;
ErrInL=0;
ErrInLL=0;
}
/*
void EnClk(GPIO_TypeDef* GPIOA2H)
{
if(GPIOA2H==GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE();
else if(GPIOA2H==GPIOB) __HAL_RCC_GPIOB_CLK_ENABLE();
else if(GPIOA2H==GPIOC) __HAL_RCC_GPIOC_CLK_ENABLE();
else if(GPIOA2H==GPIOD) __HAL_RCC_GPIOD_CLK_ENABLE();
else if(GPIOA2H==GPIOE) __HAL_RCC_GPIOE_CLK_ENABLE();
else if(GPIOA2H==GPIOF) __HAL_RCC_GPIOF_CLK_ENABLE();
else if(GPIOA2H==GPIOG) __HAL_RCC_GPIOG_CLK_ENABLE();
else if(GPIOA2H==GPIOH) __HAL_RCC_GPIOH_CLK_ENABLE();
}
uint16_t StepMotor::SetPortOut(GPIO_TypeDef* GPIOA2H,uchar PosPin)
{
uint16_t GPIOxPin;
GPIOxPin=(1<<PosPin);
GPIO_InitStruct.Pin = GPIOxPin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;; //输出
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA2H, &GPIO_InitStruct);
return(GPIOxPin);
}
*/
StepMotor::StepMotor(uchar MtNo)
{
uint16_t i;
Iam=MtNo;
RevDir=1;
Runing=0;
dir=0;
Pos_Pul=0;
Pos_Des=0;
Half_Pos=0;
Half_Step=0;
ZeroOutCnt=0;
ZeroTriged=0;
//X电机MPos=9022; Y电机MPos=3463; Z电机MPos=2165;
//X电机VRadio=2*8=16; Y 电机VRadio=8; Z电机VRadio=10;
if(Iam==1) { MaxPos=MaxAPos; RadioV=16; MaxSpeed=(10/RadioV); } //最大速度约50转每秒
if(Iam==2) { MaxPos=MaxBPos; RadioV=1; MaxSpeed=10/RadioV; } //最大速度约50转每秒
if(Iam==3) { MaxPos=MaxCPos; RadioV=4; MaxSpeed=(10/RadioV)*(MotorMaxV_rps/10); } //最大速度约10转每秒
if(Iam==4) { MaxPos=MaxDPos; RadioV=4; MaxSpeed=(10/RadioV)*(MotorMaxV_rps/10); } //最大速度约10转每秒
if(Iam==5) { MaxPos=MaxEPos; RadioV=4; MaxSpeed=(10/RadioV)*(MotorMaxV_rps/10); } //最大速度约10转每秒
if(Iam>5) { MaxPos=MaxAPos; RadioV=1; MaxSpeed=10/RadioV; } //最大速度约50转每秒
if(Iam==1) { SetPar(0.01,3,0); }
if(Iam==2) { SetPar(0.01,3,0); }
if(Iam==3) { SetPar(0.01,3,0); }
if(Iam==4) { SetPar(0.01,3,0); }
if(Iam==5) { SetPar(0.01,3,0); }
if(Iam>5) { SetPar(0.01,3,0); }
for(i=0;i<257;i++)
{
KSin[i]=(1-cos(3.1415926*i/256))/2; //20190116
if(KSin[i]<0.03) KSin[i]=0.03; //20201018
}
MovePhase=0xff;
PhaseZero=0xff;
Go0Finished=0;
}
void StepMotor::SetTimCCR(void)
{
uint32_t uhCapture,count;
// count=LL_TIM_GetCounter(TIM1);
// /*设置比较数值*/
// LL_TIM_OC_SetCompareCH1(TIM1, count + 1000);
switch(Iam)
{
case 1: count=LL_TIM_GetCounter(TIM2);
if((count + CurSpeed)>TIM2->ARR) LL_TIM_OC_SetCompareCH1(TIM2, count + CurSpeed-TIM2->ARR);
else LL_TIM_OC_SetCompareCH1(TIM2, count + CurSpeed); break;
case 2: count=LL_TIM_GetCounter(TIM2);
if((count + CurSpeed)>TIM2->ARR) LL_TIM_OC_SetCompareCH2(TIM2, count + CurSpeed-TIM2->ARR);
else LL_TIM_OC_SetCompareCH2(TIM2, count + CurSpeed); break;
case 3: count=LL_TIM_GetCounter(TIM2);
if((count + CurSpeed)>TIM2->ARR) LL_TIM_OC_SetCompareCH3(TIM2, count + CurSpeed-TIM2->ARR);
else LL_TIM_OC_SetCompareCH3(TIM2, count + CurSpeed); break;
case 4: count=LL_TIM_GetCounter(TIM1);
if((count + CurSpeed)>TIM2->ARR) LL_TIM_OC_SetCompareCH4(TIM2, count + CurSpeed-TIM2->ARR);
else LL_TIM_OC_SetCompareCH4(TIM2, count + CurSpeed); break;
case 5: count=LL_TIM_GetCounter(TIM1);
if((count + CurSpeed)>TIM1->ARR) LL_TIM_OC_SetCompareCH1(TIM1, count + CurSpeed-TIM1->ARR);
else LL_TIM_OC_SetCompareCH1(TIM1, count + CurSpeed); break;
case 6: count=LL_TIM_GetCounter(TIM1);
if((count + CurSpeed)>TIM1->ARR) LL_TIM_OC_SetCompareCH2(TIM1, count + CurSpeed-TIM1->ARR);
else LL_TIM_OC_SetCompareCH2(TIM1, count + CurSpeed); break;
case 7: count=LL_TIM_GetCounter(TIM1);
if((count + CurSpeed)>TIM1->ARR) LL_TIM_OC_SetCompareCH3(TIM1, count + CurSpeed-TIM1->ARR);
else LL_TIM_OC_SetCompareCH3(TIM1, count + CurSpeed); break;
case 8: count=LL_TIM_GetCounter(TIM1);
if((count + CurSpeed)>TIM1->ARR) LL_TIM_OC_SetCompareCH4(TIM1, count + CurSpeed-TIM1->ARR);
else LL_TIM_OC_SetCompareCH4(TIM1, count + CurSpeed); break;
case 9: count=LL_TIM_GetCounter(TIM5);
if((count + CurSpeed)>TIM5->ARR) LL_TIM_OC_SetCompareCH1(TIM5, count + CurSpeed-TIM5->ARR);
else LL_TIM_OC_SetCompareCH1(TIM5, count + CurSpeed); break;
case 10: count=LL_TIM_GetCounter(TIM5);
if((count + CurSpeed)>TIM5->ARR) LL_TIM_OC_SetCompareCH2(TIM5, count + CurSpeed-TIM5->ARR);
else LL_TIM_OC_SetCompareCH2(TIM5, count + CurSpeed); break;
case 11: count=LL_TIM_GetCounter(TIM8);
if((count + CurSpeed)>TIM8->ARR) LL_TIM_OC_SetCompareCH1(TIM8, count + CurSpeed-TIM8->ARR);
else LL_TIM_OC_SetCompareCH1(TIM8, count + CurSpeed); break;
case 12: count=LL_TIM_GetCounter(TIM8);
if((count + CurSpeed)>TIM8->ARR) LL_TIM_OC_SetCompareCH2(TIM8, count + CurSpeed-TIM8->ARR);
else LL_TIM_OC_SetCompareCH2(TIM8, count + CurSpeed); break;
case 13: count=LL_TIM_GetCounter(TIM8);
if((count + CurSpeed)>TIM8->ARR) LL_TIM_OC_SetCompareCH3(TIM8, count + CurSpeed-TIM8->ARR);
else LL_TIM_OC_SetCompareCH3(TIM8, count + CurSpeed); break;
case 14: count=LL_TIM_GetCounter(TIM8);
if((count + CurSpeed)>TIM8->ARR) LL_TIM_OC_SetCompareCH4(TIM8, count + CurSpeed-TIM8->ARR);
else LL_TIM_OC_SetCompareCH4(TIM8, count + CurSpeed); break;
case 15: count=LL_TIM_GetCounter(TIM5);
if((count + CurSpeed)>TIM5->ARR) LL_TIM_OC_SetCompareCH3(TIM5, count + CurSpeed-TIM5->ARR);
else LL_TIM_OC_SetCompareCH3(TIM5, count + CurSpeed); break;
}
}
void StepMotor::DisTimCCR(void)
{
switch(Iam)
{
case 1: DisTim2CC1; break;
case 2: DisTim2CC2; break;
case 3: DisTim2CC3; break;
case 4: DisTim2CC4; break;
case 5: DisTim1CC1; break;
case 6: DisTim1CC2; break;
case 7: DisTim1CC3; break;
case 8: DisTim1CC4; break;
case 9: DisTim5CC1; break;
case 10: DisTim5CC2; break;
case 11: DisTim8CC1; break;
case 12: DisTim8CC2; break;
case 13: DisTim8CC3; break;
case 14: DisTim8CC4; break;
case 15: DisTim5CC3; break;
}
}
void StepMotor::EnTimCCR(void)
{
switch(Iam)
{
case 1: EnTim2CC1; break;
case 2: EnTim2CC2; break;
case 3: EnTim2CC3; break;
case 4: EnTim2CC4; break;
case 5: EnTim1CC1; break;
case 6: EnTim1CC2; break;
case 7: EnTim1CC3; break;
case 8: EnTim1CC4; break;
case 9: EnTim5CC1; break;
case 10: EnTim5CC2; break;
case 11: EnTim8CC1; break;
case 12: EnTim8CC2; break;
case 13: EnTim8CC3; break;
case 14: EnTim8CC4; break;
case 15: EnTim5CC3; break;
}
}
void StepMotor::MoveT0(int32_t DestPos,int16_t DestV) //位置为脉冲数,速度为多少圈每分钟
{
if(DestPos>MaxPos) { return; }
Pos_Des=DestPos;
if(Pos_Des>Pos_Pul)
{
Half_Pos=((Pos_Des-Pos_Pul)>>1)+Pos_Pul;
Half_Step=((Pos_Des-Pos_Pul)>>1);
dir=1;
//if(RevDir==0) HAL_GPIO_WritePin(MyGPIOAn_Dir,MyAn_DirPin,GPIO_PIN_SET); else HAL_GPIO_WritePin(MyGPIOAn_Dir,MyAn_DirPin,GPIO_PIN_RESET);
}
else if(Pos_Des<Pos_Pul)
{
Half_Pos=((Pos_Pul-Pos_Des)>>1)+Pos_Des;
Half_Step=((Pos_Pul-Pos_Des)>>1);
dir=0;
//if(RevDir==0) HAL_GPIO_WritePin(MyGPIOAn_Dir,MyAn_DirPin,GPIO_PIN_RESET); else HAL_GPIO_WritePin(MyGPIOAn_Dir,MyAn_DirPin,GPIO_PIN_SET);
}
else
{
Half_Pos=Pos_Des;
Half_Step=0;
dir=0;
}
if(Motor[Iam-1]->dir==Motor[Iam-1]->RevDir) MtDriver[Iam-1]->MtCCW; else MtDriver[Iam-1]->MtCW;
if(RadioV==0) RadioV=1; //默认细分数为1,
//HignSpeed=MotorMaxV_rps*60*2*10/(DestV*RadioV);
HignSpeed=600000*60/((Presca_TIM+1)*DestV*RadioV);
LowSpeed=(HignSpeed<<10);
if(LowSpeed>0xffff) LowSpeed=0xffff;
CurSpeed=LowSpeed;
SetTimCCR();
if(dir==1) vCirpMinDes=DestV; else vCirpMinDes=-DestV;
Runing=1;
SmodePhase=0;
}
uchar StepMotor::IsZero(void) //返回是否零位处于触发状态,当前低电平为零位状态
{
if(ZeroTriged) return(1); else return(0);
}
//原先是先走脉冲再计数,控制方式兼容直接驱动后改为先计数,然后根据计数再发脉冲
uchar StepMotor::GoZeroInit(void) //以固定的速度(圈每分)归零,速度由执行周期决定
{
switch(PhaseZero)
{
case 0xff:
if(IsZero()==1) PhaseZero=0; else PhaseZero=5;
ZeroOutCnt=0;
break;
case 0: //在零位时向外运动
dir=1; PhaseZero=1;
break;
case 1:
Pos_Pul++; vTaskDelay(1); PhaseZero=2;
break;
case 2:
ZeroOutCnt++;
if(IsZero()==0) PhaseZero=3; else PhaseZero=1;
if(ZeroOutCnt>300) PhaseZero=3; //出零位以200个脉冲作为超时退出
break;
case 3: //出零位后再运行100脉冲
Pos_Pul++; PhaseZero=4;
break;
case 4:
ZeroOutCnt++;
if(ZeroOutCnt<300) PhaseZero=3; else PhaseZero=5;
break;
case 5: //不在零位时向内运动
dir=0; PhaseZero=6;
break;
case 6:
Pos_Pul++; PhaseZero=7;
break;
case 7:
if(IsZero()==1) PhaseZero=8; else PhaseZero=6;
break;
case 8: //到达零位后返回1
Pos_Pul=0; PhaseZero=0xff; return(1);
break;
}
return(0); //未到达零位后返回0
}
void StepMotor::ReFreshCnt(void) //根据调整过的马达速度更新计数器变量 HignSpeed=600000*60/((Presca_TIM+1)*DestV*RadioV);
{
if(vCirpMinDes>0) HignSpeed=600000*60/(uint32_t)((Presca_TIM+1)*vCirpMinDes*RadioV);// =(240000000/(Presca_TIM+1))/((vCirpMinDes/60)*200*2*RadioV) 定时器时钟/每秒脉冲数
else HignSpeed=600000*60/(uint32_t)((Presca_TIM+1)*(-vCirpMinDes)*RadioV); //1200=60*2*10 //HignSpeed=24000/((uint32_t)(-vCirpMinDes)*RadioV*200/60);
if(HignSpeed<MaxSpeed) HignSpeed=MaxSpeed;
// if((vCirpMinDes>60)||(vCirpMinDes<-60)) LowSpeed=(HignSpeed<<5); else LowSpeed=(HignSpeed<<2);
LowSpeed=(HignSpeed<<10);
if(LowSpeed>0xffff) LowSpeed=0xffff;
if(v_CirpMin>0)
{
if(v_CirpMin<1) v_CirpMin=1; //限制马达转速不低于1转每分,否则可能会导致数据溢出出错
CurSpeed=600000*60/(uint32_t)((Presca_TIM+1)*v_CirpMin*RadioV); //4000=10*200*2
}
else if(v_CirpMin<=0)
{
if(v_CirpMin>-1) v_CirpMin=-1;
CurSpeed=600000*60/(uint32_t)((Presca_TIM+1)*(-v_CirpMin)*RadioV); //4000=10*200*2
}
if(CurSpeed<HignSpeed) CurSpeed=HignSpeed;
if(CurSpeed>LowSpeed) CurSpeed=LowSpeed;
if(v_CirpMin>0)
{
v_CirpMin=(float)(600000*60)/(float)(RadioV*CurSpeed*(Presca_TIM+1)); //1200=60*2*10
if(v_CirpMin<1) v_CirpMin=1; //限制马达转速不低于1转每分,否则可能会导致数据溢出出错
}
else if(v_CirpMin<=0)
{
v_CirpMin=-float(600000*60)/(float)(RadioV*CurSpeed*(Presca_TIM+1)); //1200=60*2*10
if(v_CirpMin>-1) v_CirpMin=-1;
}
//取消16位到32位扩展,直接使用32位计数器 if(Iam==1) Tim3CC1SetShdARR(CurSpeed,0);
//取消16位到32位扩展,直接使用32位计数器 if(Iam==2) Tim3CC2SetShdARR(CurSpeed,0);
//取消16位到32位扩展,直接使用32位计数器 if(Iam==3) Tim3CC3SetShdARR(CurSpeed,0);
//取消16位到32位扩展,直接使用32位计数器 if(Iam==4) Tim3CC4SetShdARR(CurSpeed,0);
}
void StepMotor::Move(void) //,uint16_t MinV,uint16_t MaxV)
{
switch(MovePhase)
{
case 0xff:
if(Go0Finished==1) MovePhase=10; DisTimCCR(); //不需要等待回零的电机,Go0Finished初始化时直接置一
break;
//使用X电机脉冲控制电机走到指定的位置
case 10:
CurSpeed=LowSpeed;
SetTimCCR();
MtDriver[Iam-1]->On=1; //MtDrvA.On=1; //??????????是否必须。。。。。。。。。。。。。。
if(Pos_Des==Pos_Pul) { Runing=0; StopCode=22; } //20210316 Pos_Pul //20190227 避免已到指定位置后再次下指令Runing=1无法自动关闭
else { MovePhase=11; vTaskDelay(80); CalTimes=0; EnTimCCR(); v_CirpMin=0; } //等待方向切换完成 //20210319 加入速度初始值为0的条件
break;
case 11:
if((dir>0)&&(Runing>0))
{
if(Half_Pos>Pos_Pul)
{
v_CirpMin+=PidAdjust(v_CirpMin-vCirpMinDes);
if((v_CirpMin+0.0015*vCirpMinDes)<vCirpMinDes)
{
if(SmodePhase<1) SmodePhase=1;
}
else { v_CirpMin=vCirpMinDes; SmodePhase=2;} // ConvIndex++;
}
}
if((dir==0)&&(Runing>0))
{
if(Half_Pos<Pos_Pul)
{
v_CirpMin+=PidAdjust(v_CirpMin-vCirpMinDes);
if((v_CirpMin+0.0015*vCirpMinDes)>vCirpMinDes) //1 - 改为 +
{
if(SmodePhase<1) SmodePhase=1;
}
else { v_CirpMin=vCirpMinDes; SmodePhase=2; }
}
}
ReFreshCnt();
CalTimes++; //20211209 PID调整次数
if(Runing==0) { DisTimCCR(); MovePhase=12; MtDriver[Iam-1]->On=0; } //MtDrvA.On=0;
break;
case 12:
v_CirpMin=PidAdjust(0);
Half_Pos=Pos_Des;
SmodePhase=0;
MovePhase=0xff;
break;
}
}
|