步进电机【24BYJ-48】

步进电机

一种将电脉冲信号转换成相应角位移线位移的电动机。每输入一个脉冲信号转子就转动一个角度或前进一步,其输出的角位移线位移与输入的脉冲数成正比,转速脉冲频率成正比。

驱动方式:使用八拍方式(按照下方拍子顺序输出即可)

在24BYJ-48说明介绍中知道步距角和减速比

步距角:5.625

减速比:1/64


步距角与脉冲控制有关,

一个脉冲一个步距角,360/5.625=64  则需要64脉冲 转子转一圈


脉冲:变化的拍数,如现使用5线4相8拍方法,

8拍则8个脉冲,一次输出的高低电平就是一个拍子


转子圈数不等于输出轴圈数,输出轴圈数才是真正的转动一圈

由  减速比1:64  可得 64圈转子等于1圈输出轴

!!!!
1拍子-》一脉冲  

64脉冲-》1圈转子  

64圈转子-》1圈输出轴(电机转动一圈)

得计算:64*64*   角度/360 =脉冲数  !!!!!

=》8*8*64/360*角度=》8*64/45*角度   (计算出角度对应的脉冲数)

修改Motors数组数值,数值是由角度计算出的脉冲数,带复位示例:

const unsigned char Motors[4] ={0,85,57,29};  

//使用数组先计算出对应的脉冲数 

(数组数值对应公式,但还没有乘8,需要再乘8)
//85=64*60度/45        57=64*40度/45       29=64*20度/45

大概:设置摇头中间值,需要根据需求调整中间值,以防越界,

当设置某个方向为正方向,进行脉冲时,摇头中间值则+1,反方向则摇头中间值-1,

需要保证摇头中间值 + 最大脉冲数不越界,

需要保证摇头中间值 - 最大脉冲数大于0,

在需要复位时候,可以简化成 摇头中间值经过脉冲数变化后是900 则是复位成功





volatile unsigned char round;//圈数
volatile unsigned int swingmotors;//方向数值
volatile unsigned int swingnegatuve;//负方向数值
volatile unsigned int swingforward;//正方向数值
volatile unsigned int swingcenter;//摇头中心值 900 为中间  
const unsigned char Motors[4] ={0,85,57,29};   //还没有乘8
//85=64*60度/45   57=64*40度/45  29=64*20度/45

//1024 =8*64*90/45   90度    1024是脉冲数
//8192=8*64*720/45  720度    8192是脉冲数
//4096=8*64*360/45  360度    4096是脉冲数

/*
40度  456   /8 =58         20度   29       29*8=232
80度  912   /8 =114        40度   57       57*8=456
120度 1366  /8  =170       60度   85       85*8=680

*/

//黑  黄 棕 蓝
//触发一次脉冲    摇头1档间隔脉冲时间1.216ms  =38*32us
void motor_uln2003(void)
{
 
			if(swingstall==0)//档位为0  需要复位
			{
				if(swingcenter>900)//当摇头中间值大于900则有偏角度,
				{
				   swingcenter--;
				   motor--;
				   if(motor<1)//逆转  motor值控制对应拍子
				   {
						motor=8;
				   }
				}
				else if(swingcenter<900)//当摇头中间值小于900则有偏角度,
				{
				   swingcenter++;
				   motor++;
				   if(motor>8) //正转
				   {
						motor=1;
				   }
				}
				else
				{
					swingreset=0;               
                    //标志位是当摇头中间值为900,复位成功才能不用进入本函数
                    //否则会一直进入
				}
			}
			else
			{
				swingmotors=Motors[swingstall]*8;//swingstall是对应的档位的偏角度!!!!
                //由上述所知我公式是少了一次乘8的,在这补上才是正正需要偏移的脉冲数
				swingforward=swingmotors+900;//正方向数值
				swingnegatuve=900-swingmotors;//负方向数值

                //如:我想要是摇头中间值 左右20度,则共40度
                //计算得出  swingmotors=8*29=232  29由 64*20度/45来  请上上述公式
                //那么   正方向数值=900+232=1132   负方向数值=900-232=668
   //可知只要我脉冲数与摇头值对应, 1132~668之间  进行对应的拍子脉冲就能实现角度控制左20度右20度
				
				if(dir)//正向
				{
				   swingcenter++;
				   if(swingcenter>=swingforward)
				   {
					dir=0;//摇头中间值超过范围值最大值则进行反向
				   }
				   
				   motor++;
				   if(motor>8)
				   {
						motor=1;
				   }
                   //!!!!!需要注意拍子数方向,就是旋转方向与  motor从1到8还是8到1有关
				}
				else//反向
				{
				   swingcenter--;
				   if(swingcenter<=swingnegatuve)//摇头中间值超过范围值最小值则进行反向
				   {
					dir=1;
				   }
				   
				   motor--;
				   if(motor<1)
				   {
						motor=8;
				   }
				   
				}
			}

			
			
			
			
			
			
		OEP4|=0x0F;//各个io口需要配置成输出模式!!!!
      //在关闭后,是配置成输入模式,原因是不用步进电机还是发热,高阻态(输出模式)则不会
       //所以在不使用时候我配置成输入模式,需要用到再打开
		  
		switch(motor)//对应上述八拍方法进行驱动(标志着 “-” 的io口输出低电平,否则就高电平)
		{
			  case 1:
			  P43D=0;P42D=1;P41D=1;P40D=0;//   0110
			  break;
			  case 2:
			  P43D=0;P42D=1;P41D=1;P40D=1;//   0111
			  break;
			  case 3:
			  P43D=0;P42D=0;P41D=1;P40D=1;//   0011
			  break;
			  case 4:
			  P43D=1;P42D=0;P41D=1;P40D=1;//   1011
			  break;
			  case 5:
			  P43D=1;P42D=0;P41D=0;P40D=1;//   1001
			  break;
			  case 6:
			  P43D=1;P42D=1;P41D=0;P40D=1;//   1101
			  break;
			  case 7:
			  P43D=1;P42D=1;P41D=0;P40D=0;//   1100
			  break;
			  case 8:
			  P43D=1;P42D=1;P41D=1;P40D=0;//   1110
			  break;
			  
			  default:
			  break;

		}
		  
 
 
 
}




void main(void)
{
	CLR_RAM();
   	
	GIE = 0;
   	Timer0_init();
   	Timer1_init();
   	GIE = 1;
   
   //0输入1输出
	OEP0=0xF7;
	OEP4=0x1F;
	OEP5=0x13;
   
    swingreset=1;//控制启动,找个地方启动置1就好
	swingtime=38;//设置时间延时, 38*32=1216us   
    //每个脉冲之间1.216ms 可实现转动,可调节时间控制转速,
    swingstall=1;//数组控制需要偏转的角度
    

   	while(1)
   	{  	   	
   	  
        //放在32us的定时器中断中,不使用软延时来延时
        //也可以放在其他定时器中断触发,我使用1.2ms脉冲是可以驱动的
		if(timer1us)
		{
			timer1us=0;
		    
			//摇头步进电机
			if(swingreset)//启动,只有复位成功,摇头中间值是900,swingreset才为0
			{
				timer1ms_1++;
				if(timer1ms_1>=swingtime)     //!!!!!!38*32=1.216ms
				{
				   timer1ms_1=0;
				    motor_uln2003(); //每次触发都是一次脉冲电平
				}
			}
			else//关闭则电平高
			{
				//端口设置输入模式  设置高阻态,否则持续有电流,电机发烫
				OEP4&=0x10;
			}
			
			
			
			
		}
       
	   
	   
	   
   	}
   	   	
}



void int_isr(void) __interrupt
{
   	__asm 
   	push
   	__endasm;
   	
   	
   	//当T0CNT递减到0时,此时产生T0溢出中断请求标志T0IF/T1IF置1 
   	if(T0IF)   //104us触发一次
   	{      	
   	   	T0IF=0; 
		T0CNT=0x9A;
   	}      
   	
   	
   	if(T1IF)   //32uS
   	{      	
   	   	T1IF=0; 
   	   	timer1us=1;
		
		
   	}
   	

   	__asm 
   	pop
   	__endasm;
}











修改Motors数组数值,数值是转圈数,带复位示例:

const unsigned char Motors[4] ={0,1,2,3}; 

由上述公式可知  脉冲数=8*64*角度/45

所以一圈是360度 则一圈脉冲数=8*64*360/45=4096    

设置摇头中间值需要大于旋转1圈的脉冲数  所以摇头中间值设值5000

大概:前述设置角度不同,设置摇头中间圈数值,则每进行4096次脉冲,根据摇头中间值得变化,,如顺时针进行4096次脉冲则摇头中间圈数值进行+1,逆时针进行4096次脉冲则摇头中间圈数值进行-1

在需要复位时候,可以简化成 摇头中间值经过脉冲数变化后是5000 同时也需要保证摇头中间圈数值是50,才能复位成功。(本次设置摇头中间圈数值为50)

volatile unsigned char round;//圈数
volatile unsigned char swingmotors;//方向数值
volatile unsigned char swingnegatuve;//负方向数值
volatile unsigned char swingforward;//正方向数值
volatile unsigned int swingcenter;//一圈脉冲数

volatile unsigned char swinground;//一圈数标志位

const unsigned char Motors[4] ={0,1,2,3}; 
//8192=8*64*720/45  720度    8192是脉冲数
//4096=8*64*360/45  360度    4096是脉冲数



//黑  黄 棕 蓝
//触发一次脉冲    摇头1档间隔脉冲时间1.216ms  =38*32us
void motor_uln2003(void)
{
            
			if(dir)//顺时针
			{
				swingcenter++;
				if(swingcenter>=9096)//5000+4096=9096 即超过了一圈
				{
				   swingcenter=5000;
				   round++;		//圈数+1,换向由下方的圈数范围决定	   
				}
			
				
				motor++;
			    if(motor>8) //正转
			    {
					motor=1;
			    }
			}
			else //逆时针
			{
				
				swingcenter--;
				if(swingcenter<=904)//5000-4096=904
				{
				   swingcenter=5000;
				   round--;				   
				}
				
				motor--;
			    if(motor<1)//逆转
			    {
					motor=8;
			    }
			}
			
			
 
			if(swingstall==0)//档位为0  需要复位
			{
//!!!!!!!如果需要复位的话先对摇头中间圈数值进行判断要等于50,在对摇头中间值判断要等于5000
     //当还没到一圈就停止得也可以复位,圈数等于50后,也能判断不到一圈的摇头中间值5000
					if(round>50)
					{
						dir=0;//逆时针
					}
					else if(round<50)
					{
						dir=1;//顺时针
					}
					else
					{
						if(swingcenter>5000)
						{
							dir=0;//逆时针
						}
						else if(swingcenter<5000)
						{
							dir=1;//顺时针
						}
						else
						{
							swingreset=0;
                    //需要复位到摇头中间圈数值等于50,摇头中间值等于5000
						}
						
					}
			}
			else
			{
				swingmotors=Motors[swingstall];
				swingforward=swingmotors+50;//正方向圈数
				swingnegatuve=50-swingmotors;//负方向圈数
				
				   
					if(dir)//正向
					{
						if(round>=swingforward)
						{                        
							dir=0;//脉冲数超过  进行反向
						}
					}
					else//反向
					{
						
						if(round<=swingnegatuve)
						{
							dir=1;//脉冲数超过  进行反向
						}
						
						
					}
				
			}
	
			
			
		OEP4|=0x0F;
		  
		switch(motor)
		{
			  case 1:
			  P43D=0;P42D=1;P41D=1;P40D=0;//   0110
			  break;
			  case 2:
			  P43D=0;P42D=1;P41D=1;P40D=1;//   0111
			  break;
			  case 3:
			  P43D=0;P42D=0;P41D=1;P40D=1;//   0011
			  break;
			  case 4:
			  P43D=1;P42D=0;P41D=1;P40D=1;//   1011
			  break;
			  case 5:
			  P43D=1;P42D=0;P41D=0;P40D=1;//   1001
			  break;
			  case 6:
			  P43D=1;P42D=1;P41D=0;P40D=1;//   1101
			  break;
			  case 7:
			  P43D=1;P42D=1;P41D=0;P40D=0;//   1100
			  break;
			  case 8:
			  P43D=1;P42D=1;P41D=1;P40D=0;//   1110
			  break;
			  
			  default:
			  break;

		}
		  
 
 
 
}



void main(void)
{
	CLR_RAM();
   	
	GIE = 0;
   	Timer0_init();
   	Timer1_init();
   	GIE = 1;
   
   //0输入1输出
	OEP0=0xF7;
	OEP4=0x1F;
	OEP5=0x13;
   
    swingreset=1;//控制启动,找个地方启动置1就好
	swingtime=38;//设置时间延时, 38*32=1216us   
    //每个脉冲之间1.216ms 可实现转动,可调节时间控制转速,
    swingstall=1;//数组控制需要偏转的圈数


   	while(1)
   	{  	   	
   	  
		if(timer1us)//放在32us的定时器中断中,不使用软延时来延时
		{
			timer1us=0;
		    
			//摇头步进电机
			if(swingreset)//启动,只有复位成功,摇头中间值是900,swingreset才为0
			{
				timer1ms_1++;
				if(timer1ms_1>=swingtime)//38*32=1.216ms
				{
				   timer1ms_1=0;
				    motor_uln2003(); //每次触发都是一次脉冲电平
				}
			}
			else//关闭则电平高
			{
				//端口设置输入模式  设置高阻态,否则持续有电流,电机发烫
				OEP4&=0x10;
			}
			
			
			
			
		}
       
	   
	   
	   
   	}
   	   	
}



void int_isr(void) __interrupt
{
   	__asm 
   	push
   	__endasm;
   	
   	
   	//当T0CNT递减到0时,此时产生T0溢出中断请求标志T0IF/T1IF置1 
   	if(T0IF)   //104us触发一次
   	{      	
   	   	T0IF=0; 
		T0CNT=0x9A;
   	}      
   	
   	
   	if(T1IF)   //32uS
   	{      	
   	   	T1IF=0; 
   	   	timer1us=1;
		
		
   	}
   	

   	__asm 
   	pop
   	__endasm;
}

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值