倒立摆制作全过程


最近在练习pid的控制算法,就选用了2013年的电子设计国赛题目:倒立摆 。

首先给你们看看我的成果

在这里插入图片描述

注意哦:倒立摆不是靠上面黄色的传感器保持平衡的,而是通过下面的电机左右扭动使得摆杆不掉下来,难度可不小了。

材料准备

1.机械部分

机械部分

如图所示选好电机和角位移传感器进行组装就好了,这个部分是我直接网上购买的,如果要自己装也是可以的,不过会比较麻烦,结构差不多的。

2.主控部分

控制部分

这个部分的话完全是我自己设计的,作用和网上买的一样,因为网上买的话太贵了,有需要的话可以联系我,有pcb文件也可以代焊。

3.代码编写以及调参
上面的话都是硬件部分,需要自己动手去制作的,接下来我教大家怎么给倒立摆调参。代码的话我已经把源码上传到我的资料那里了,里面都有详细解说的,大家可以直接去下载来看,可以理解的。

下面展示 main函数部分。

int main(void)
{ 
	Stm32_Clock_Init(9);          
	delay_init(72);                 
	JTAG_Set(JTAG_SWD_DISABLE);    
	JTAG_Set(SWD_ENABLE);         
	delay_ms(1000);                
	delay_ms(1000);             
	LED_Init();               
	EXTI_Init();                 
	OLED_Init();                   
	uart_init(72,128000);           
  MiniBalance_PWM_Init(7199,0); 
	Encoder_Init_TIM4();            
	Angle_Adc_Init();            
	//Baterry_Adc_Init();           
	Timer1_Init(49,7199);      
	while(1)
		{      
				//DataScope();	          
				delay_flag=1;	        
				oled_show();             
				while(delay_flag);       							
		} 
}

学过32的基本都懂,就是需要用到的模块都初始化,然后启动定时器函数进入pid控制的中断进行偏差控制。

pid控制代码

int TIM1_UP_IRQHandler(void)  
{    
	if(TIM1->SR&0X0001
	{   
		  TIM1->SR&=~(1<<0);                                       	                     
	     if(delay_flag==1)
			 {
				 if(++delay_50==10)	 delay_50=0,delay_flag=0;          
			 }		
    	Encoder=Read_Encoder(4);             	                   
      Angle_Balance=Get_Adc_Average(3,15);                     
     	Balance_Pwm =balance(Angle_Balance);                                          
	    if(++Position_Target>4)	Position_Pwm=Position(Encoder),Position_Target=0;     
      Moto=Balance_Pwm-Position_Pwm;        
		  if(Angle_Balance<1600 || Angle_Balance>2660) Moto = 0;
		  Xianfu_Pwm();                 
		 // if(Turn_Off(Voltage)==0)          
			Set_Pwm(Moto);                    
	  	Led_Flash(100);                      
	   // Voltage=Get_battery_volt();       	      
			Key();                  
	}       	
	 return 0;	  
} 


int balance(float Angle)
{  
   float Bias;                       
	 static float Last_Bias,D_Bias;   
	 int balance;                   
	 Bias=Angle-ZHONGZHI;          
	 D_Bias=Bias-Last_Bias;            
	 balance=-Balance_KP*Bias-D_Bias*Balance_KD;   
   Last_Bias=Bias;                  
	 return balance;
}


int Position(int Encoder)
{  
   static float Position_PWM,Last_Position,Position_Bias,Position_Differential;
	 static float Position_Least;
  	Position_Least =Encoder-Position_Zero;       
    Position_Bias *=0.8;		   
    Position_Bias += Position_Least*0.2;	        
	  Position_Differential=Position_Bias-Last_Position;
	  Last_Position=Position_Bias;
		Position_PWM=Position_Bias*Position_KP+Position_Differential*Position_KD;
	  return Position_PWM;
}

接下来就是重头戏了,调参部分

倒立摆要保持平衡,就需要有两个环,一个是角度环,保证摆杆能够不倒下来,再有一个是位置环,确保水平杆不会乱转。

角度环5ms采集一下 位置环25ms采集一次,电机控制是5ms控制一次。

这里位置环25ms是这样的出来的:首先尝试5ms,但是不论参数怎么调试都是反应剧烈,所以逐渐加大延长编码器采集时间,到了30ms的时候根据相同参数比较反应滞后,座椅

最后确定25ms。

角度环:p :加参数加到放手可以直立一会 但是一碰就抖动很厉害

加上d后:加参数加到可以直立不倒 向两边或一边加速,碰一下不抖

位置环:p:因为电机总得脉冲是7200,然后倒立摆转一圈编码器根据正交解码测得是1024个脉冲,在25ms中断中大部分时候达到的最大脉冲差值是100左右,所以我们P参数

确定的范围暂且是1~50.

因为有位置环p的存在,所以倒立摆在偏了一小段的时候会有恢复力,但这个恢复力超调太大了,导致倒立摆剧烈来回摆动,所以此时加微分参数D,来减小超调。

微分参数大小的判断是因为它乘的是这次位置差-上次位置差,这个差值在25ms中断中最大位十左右,所以我们暂定微分参数是0~300。

具体请参考文章:参数整定