学习笔记【STM32】|【K60】自动往返小车 步进电机

学习笔记【STM32】|【K60】自动往返小车 步进电机

使用STM32F103制作

直接开始

步进电机部分

普通42步进电机,A4988驱动

  1. ENABLE高电平抱死,MS1,MS2,MS3控制细分数;
  2. 与电机接线 红-1A 粉 - 2A 黄-1B 蓝 - 2B;
  3. sleep只要和reset接在一起就行;

单片机部分

这边博主细布使用拨码开关硬件控制,单片机就接了DIR和pwm

pwm频率控制步进电机转速,但是不能直接改变频率到你的需要的频率,需要逐步增加,这里博主采用的是S型曲线加速方法,还有很多其他的方法梯形、SPA,DMA,slavetimer等等。S 曲线算法由于其加速度和速度曲线的连续性,能够保证步进电机在运动过程中速度和加速度没有突变,减小冲击,提高步进电机运动的平稳性。

s型加减速

网上很多讲这个的,讲的都很细致,这里就不过多介绍了,
https://blog.csdn.net/fengyu19930920/article/details/81043776
https://blog.csdn.net/tianjilieren/article/details/88419120
可以参考这两个博主的帖子,两个都讲的很好
博主的S型加速的c语言方程为在这里插入图片描述
y=1./(1+exp(-x))
学习笔记【STM32】|【K60】自动往返小车 步进电机_第1张图片
把x带入曲线中获得y。

起始点为起始频率Fstart,末尾为我们需要加到的频率Fstop。
'伪’s型加速:
可以把x自加一获得下一个点的频率,然后在32的TIM溢出中断中改变arr实现转速改变,通过一级一级的变化,可以使速度变快。
真s型加速
因为是为了防止加速度突变如果你x设置成等距离的在s的中间最抖的时候不就是突变了吗,所以应该在抖的地方x集中一些,则需要把这个s型曲线“拉伸”一下,在加速度小的x自然放宽,在加速度多的地方x收敛。 固定一个采样点的总数,将s分成两半。
(x - (num/2))
越靠近值越小。

先写这么多。。。。。。

/----------------2018/8/5-------------------------/
今天弄完舵机来更新一下这个
对s型曲线求导
在这里插入图片描述
学习笔记【STM32】|【K60】自动往返小车 步进电机_第2张图片
即可以用x-num/2来表示s变化中的x点
这里发一个网上其他找到的
源码地址:https://github.com/MGDG/SLineControl

//len:S曲线的长度,即采样点个数
//FStart:曲线的起始值
//FStop: 曲线的结束值
//flexible:曲线的拉伸变换,越大代表压缩的最厉害,中间(x坐标0点周围)加速度越大;越小越接近匀加速。理想的S曲线 flexible的取值为4-6。
//index:   曲线索引点,区间[0,len]
//Fcurrent:索引点对应的曲线幅值
//
//当FStart len)index = len;
	num = len/2;
	melo = flexible * (index-num) / num;
	deno = 1.0 / (1 + expf(-melo));
	Fcurrent = FStart - (FStart-FStop) * deno;
	return Fcurrent;
}

S型弄完了步进电机控制部分基本搞定了,然后我想想

往返

学习笔记【STM32】|【K60】自动往返小车 步进电机_第3张图片
前后各一个红外光电管,不同标志位计数

   uint8_t Front_arrive;
   uint8_t Back_arrive;

我最开始是第二那样写的,可以用但是函数一旦多起来车子就不减速了

主要是这个标志位你如何处理
void read_init(u8 x)
{ 	
	switch(x)
    {
        case 0 : Front_arrive = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) ;
                	  Back_arrive  = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3) ;
        case 1 : Front_arrive = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3) ;
                 	  Back_arrive  = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) ;
    }
}

void read_init(u8 x)
{
switch(x)
    {
        case 0 : 
        {
         			if(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)) 	Front_arrive =1;
                	if(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)) 	Back_arrive  = 1;
        
}
		case 1 : 		 
         			if(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)) 	Back_arrive =1;
                	if(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3))    Front_arrive =1;
    }
}

然后判断在主函数的位置

int main(void)
.....
while(1)
{
read_init();
if(!flag&&Front_arrive) 
                 
                 flag = 1; 
                 Front_arrive = 0;
         if(flag&&Back_arrive )
         {     
                flag = 0;
                Back_arrive = 0;
                counts++; 
         }
	 switch(counts)
            {
                case BC_line: status = 0;
                    break;
                case CD_line: status = 0;
                   break;
                case DE_line: status = 2;
                    break;
                case EF_line: status = 0;
                    break;
                case FG_line: status =1;
                    break;
                case GH_line: status = 3;
                    break;
                default:          // status = 0;
                    break;                    
            }
}

然后就是下一个关键点,pwm频率改变

PWM频率

不知道上面S型讲通顺没有,PWM加减速过程中在发生一个脉冲之后就该改变,所以我们在中断里面进行判断加减速度状态,然后进行加减速。

void TIM1_UP_IRQHandler(void)  
{    
    timecount++;
    TIM_ClearFlag(TIM1, TIM_FLAG_Update);
    switch(status)
    {   
        
        case 0 :  
            freq =  (int16_t) motorPower_PowerSLine(400,719,100,4,sindex)/2;
                    sindex++;
                    last_freq = freq;
            break;            //addspeed        
        case 1 :  
            freq =  last_freq;count = 0;
                    sindex++;
            
 
            break;             //avrspeed
        case 2 : 
            freq = (int16_t) motorPower_PowerSLine(400,100, 7190,4,sindex)/2;
                    sindex++;
                    last_freq = freq;
            break;              //miuspeed
        case 3 : 
//                   TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE);
                   TIM_CtrlPWMOutputs(TIM1, DISABLE);
//                   TIM_Cmd(TIM1, DISABLE); 
                   finish_flag = 1;
            break;
        default: break;
    } 
    //temp_arr=72000000/Frequency/(psc+1)-1
    if(freq<200)freq =200;
    if(freq>250)freq =250;
    TIM1->ARR = freq;
    TIM1->CCR4= freq>>1;
    
}

实现的PWM仿真图像
实现的效果图

你可能感兴趣的:(随便写写,步进电机,STM32)