![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
闭环步进电机
motor.cpp
- Committer:
- heroistired
- Date:
- 2018-04-05
- Revision:
- 1:cbd6a3232d5b
- Parent:
- 0:5b4f19f8cd85
File content as of revision 1:cbd6a3232d5b:
#include "motor.h" ////////////////////////////////////////////////////////////////////////////////// //功能:电机结构体初始化 //参数:Motor:电机控制结构体 //返回值:无 ////////////////////////////////////////////////////////////////////////////////// void StepMotorInit(MotorType *Motor, DigitalOut *MotorDirPin, DigitalOut *EncoderCsPin, SPI *SPI_EncoderObj) { /*RCC->APB1ENR|=1<<0; //TIM2时钟使能 RCC->APB2ENR|=1<<2; //GPIOA时钟使能 GPIOA->CRL&=0XFFFFFF0F; //PA1清除之前的设置 GPIOA->CRL|=0X000000B0; //复用功能输出 TIM2->ARR=899; //设定计数器自动重装值 定时器时钟频率 72K 固定的 TIM2->PSC=999; //预分频器设置 TIM2->CCMR1|=7<<12; //CH2 PWM2模式 TIM2->CCMR1|=1<<11; //CH2预装载使能 TIM2->CCER|=1<<4; //OC2 输出使能 TIM2->CR1=0x0080; //ARPE使能 TIM2->CR1|=0x01; //使能定时器2*/ RCC->APB2ENR|=1<<11; //TIM1时钟使能 RCC->APB2ENR|=1<<2; //GPIOA时钟使能 GPIOA->CRH&=0XFFFFFFF0; //PA8清除之前的设置 GPIOA->CRH|=0X0000000B; //复用功能输出 TIM1->ARR=899; //设定计数器自动重装值 TIM1->PSC=999; //预分频器设置 TIM1->CCMR1|=7<<4; //CH1 PWM2模式 TIM1->CCMR1|=1<<3; //CH1预装载使能 TIM1->CCER|=1<<0; //OC1 输出使能 TIM1->BDTR|=1<<15; //MOE 主输出使能 TIM1->CR1=0x0080; //ARPE使能 TIM1->CR1|=0x01; //使能定时器1 //初始胡电机控制结构体 Motor->Encoder = 0; Motor->Difference = 0; Motor->Goal = 0; Motor->Integral = 0; Motor->PIDControl = 0; Motor->Kp = (float)MotorKp; Motor->Ki = (float)MotorKi; Motor->INTCounter = 0; Motor->EncoderPre = 0; Motor->ID = ID_Motor1; Motor->Status = MotorStatus_Running; Motor->Dir = 0; //默认使编码器读数减小的方向 Motor->ChangeRatePIDControl = 0; Motor->PIDControl_pre = 0; Motor->Velocity = 0; Motor->V_PIDControl = 0; Motor->V_PIDControl_pre = 0; Motor->V_Difference = 0; Motor->V_Integral = 0; Motor->V_Kp = MotorVKp; Motor->V_Ki = MotorVKi; Motor->V_Goal = 0; Motor->GoalUpdated = 0; Motor->RevolveTimes = 0; Motor->ZeroPosition = 0; Motor->PresentPosition = 0; Motor->ZeroPosFound = 0; Motor->ZeroPosFoundAll = 0; Motor->Init_State = MotorInitState_Out; Motor->Init_ErrorTimes = 0; Motor->LagFiliterValue = 0; Motor->LagFiliterValuePre = 0; Motor->ChangeRateLagFiliterValue = 0; Motor->ChangeRateLagFiliterValueDigital = 0; Motor->ChangeRateLagFiliterValueDigitalPre = 0; Motor->InZeroZone = 0; Motor->ZeroZoneCounter = 0; Motor->BigStepCounter = 0; Motor->BigStepEncoderValue = 0; Motor->BigStepEncoderValuePre = 0; Motor->BigStepRevolveTimes = 0; Motor->HandUp1 = 0; Motor->HandUp2 = 0; Motor->EncoderTemp = 0; Motor->ChangeRatePIDControlPre = 0; Motor->MotorDir = MotorDirPin; Motor->EncoderCs = EncoderCsPin; Motor->SPI_Encoder = SPI_EncoderObj; } ////////////////////////////////////////////////////////////////////////////////// //功能:电机控制的PI调节器 //参数:Motor:要计算PID控制量的电机对应的电机控制结构体 //返回值:无 ////////////////////////////////////////////////////////////////////////////////// void MotorPIDController(MotorType *Motor) { char ChangeRateDifferenceLimit = 50; //位置偏差滤波 限制上升率 和 限制幅值 Motor->Difference_pre = Motor->Difference; Motor->Difference = -(Motor->Encoder- Motor->Goal); //计算偏差 Motor->ChangeRateDifference = Motor->Difference - Motor->Difference_pre; //切换参数 /*if(Math_abs(Motor->Difference) <= ApproachDistance) //很接近目标距离了 { Motor->Ki = MotorKi_End; Motor->Kp = MotorKp_End; Motor->V_Ki = MotorVKi_End; Motor->V_Kp = MotorVKp_End; } else if(Motor->Velocity <= 15) { Motor->Ki = MotorKi_Start; Motor->Kp = MotorKp_Start; Motor->V_Ki = MotorVKi_Start; Motor->V_Kp = MotorVKp_Start; } else { Motor->Ki = MotorKi; Motor->Kp = MotorKp; Motor->V_Ki = MotorVKi; Motor->V_Kp = MotorVKp; }*/ Motor->Integral += Motor->Difference; //计算积分量 if(Motor->Integral>15000) Motor->Integral=15000; //积分限幅 if(Motor->Integral<-15000) Motor->Integral=-15000; //速度目标值 Motor->V_Goal = (Motor->Kp * Motor->Difference + Motor->Ki * Motor->Integral)/10; //速度环目标值 Motor->GoalUpdated = 0; Motor->Velocity = Motor->Encoder - Motor->EncoderPre; Motor->V_Difference = -(Motor->Velocity - Motor->V_Goal); //速度偏差 Motor->V_Integral += Motor->V_Difference; if(Motor->V_Integral>6000) Motor->V_Integral=6000; //积分限幅 if(Motor->V_Integral<-6000) Motor->V_Integral=-6000; Motor->PIDControl = (Motor->V_Kp * Motor->V_Difference + Motor->V_Ki * Motor->V_Integral); //计算控制量以及相应的数据处理 if(Motor->PIDControl < 0) { Motor->PIDControl = -Motor->PIDControl; Motor->Dir = 0; Motor->MotorDir->write(0); } else { Motor->Dir = 1; Motor->MotorDir->write(1); } //判断是否进入误差容限 if(Math_abs(Motor->Difference) <= ErrorTolerance) { if(Motor->INTCounter <= INT_TimesMin) Motor->INTCounter++; else { Motor->PIDControl = 0; Motor->Status = MotorStatus_OK; } } else { Motor->INTCounter = 0; Motor->Status = MotorStatus_Running; } //限幅 if(Motor->PIDControl > PulseFreqLimit) Motor->PIDControl = PulseFreqLimit; } ////////////////////////////////////////////////////////////////////////////////// //功能:求绝对值 //参数:num 带求绝对值的函数 //返回值:num的绝对值 ////////////////////////////////////////////////////////////////////////////////// int Math_abs(int num) { if(num < 0) return -num; else return num; } //编码器初始化 void Encoder_Init(MotorType *Motor) { Motor->EncoderCs->write(1); Motor->SPI_Encoder->format(16,1); Motor->SPI_Encoder->frequency(100000); } //读取编码器值 unsigned int Encoder_ReadData(MotorType *Motor) { Motor->EncoderCs->write(0); int response = Motor->SPI_Encoder->write(0xFFFF); response &= 0x3fff; Motor->EncoderCs->write(1); return response; } ////////////////////////////////////////////////////////////////////////////////// //功能:一阶低通滤波 //参数:Value_now 本次样值 Value_pre 上次滤波输出值 //返回值:本次滤波输出值 ////////////////////////////////////////////////////////////////////////////////// int Fliter_1(int Value_now, int Value_pre) { return (int)(FlierCoefficient*(float)Value_now+(1-FlierCoefficient)*(float)Value_pre); } ////////////////////////////////////////////////////////////////////////////////// //功能:设置步进电机脉冲信号的PWM频率 // //返回值:无 ////////////////////////////////////////////////////////////////////////////////// void StepMotorSetFreq(MotorType *Motor) { unsigned int Motor_ARR; //为了使频率步长1Hz平滑可调需要分段设置定时器的时钟频率,即满足(Tclk/freq-Tclk/freq)>1 //并且考虑到余量与ARR寄存器只有16位,设置分段如下 //8k-5k 72M //5k-1k 36M //1k-500 2M //500-100 720k //100-1 72k //Motor->PIDControl = 5000; /*if(Motor->PIDControl > PulseFreqLimit) Motor->PIDControl = PulseFreqLimit; else if((Motor->PIDControl <= PulseFreqLimit) && (Motor->PIDControl > 5000)) TIM2->PSC=0; //预分频器设置 else if((Motor->PIDControl <= 5000) && (Motor->PIDControl > 1000)) TIM2->PSC=1; //预分频器设置 else if((Motor->PIDControl <= 1000) && (Motor->PIDControl > 500)) TIM2->PSC=35; //预分频器设置 else if((Motor->PIDControl <= 5000) && (Motor->PIDControl > 100)) TIM2->PSC=99; //预分频器设置 else if((Motor->PIDControl <= 100) && (Motor->PIDControl > 0)) TIM2->PSC=999; //预分频器设置 else { Motor->PIDControl = 1; TIM2->PSC=999; //预分频器设置 } Motor_ARR = APB2Freq / (TIM2->PSC+1) / Motor->PIDControl; TIM2->ARR = Motor_ARR; TIM2->CCR2 = Motor_ARR/2;*/ if(Motor->PIDControl > PulseFreqLimit) Motor->PIDControl = PulseFreqLimit; else if((Motor->PIDControl <= PulseFreqLimit) && (Motor->PIDControl > 5000)) TIM1->PSC=0; //预分频器设置 else if((Motor->PIDControl <= 5000) && (Motor->PIDControl > 1000)) TIM1->PSC=1; //预分频器设置 else if((Motor->PIDControl <= 1000) && (Motor->PIDControl > 500)) TIM1->PSC=35; //预分频器设置 else if((Motor->PIDControl <= 5000) && (Motor->PIDControl > 100)) TIM1->PSC=99; //预分频器设置 else if((Motor->PIDControl <= 100) && (Motor->PIDControl > 0)) TIM1->PSC=999; //预分频器设置 else { Motor->PIDControl = 1; TIM1->PSC=999; //预分频器设置 } Motor_ARR = APB2Freq / (TIM1->PSC+1) / Motor->PIDControl; //printf("ll%dll \r\n", Motor_ARR); TIM1->ARR = Motor_ARR; TIM1->CCR1 = Motor_ARR/2; } //控制接口 void Communication(Serial *Uart, MotorType *Motor) { char UartTemp = 0; //串口缓存 if(Uart->readable()) { } }