51单片机——步进电机

目录

步进电机原理

步进电机使用

步进电机的控制

小知识点


步进电机原理

原理是给线圈通电产生磁场然后转子旋转,通过控制不同方向的线圈使得中间的转子旋转,一般就是ABCDABCDABCD这样去控制旋转。线圈与转子的具体控制有点玄幻,基本不会出现空转的情况。

步进电机使用

一定要根据手册使用步进电机,例如以下重点参数

  • 步进角(每节拍转子转动的角度)
  • 减速比(靠外部齿轮)— 意思大概是转子转动1600°,然而外界显示出来只转了1°
  • 供电电压(一般不是5V,更高的电压)
  • 启动频率(驱动电机输入的频率有上线,因为机械结构有延迟)
  • 可以A(AB)B(BC)C(CD)D这样驱动步进电机——四相八拍

步进电机的控制

  • 旋转方向—顺逆时针——简单的一个bit变量判定方向即可
  • 旋转一定角度——通过bea输入的数值和使用手册控制
  • 来回摆动式旋转——如下
  • 配合按键完成花样旋转——如下

本次控制使用的是四相电机,仅仅只需要运用到4位,为减少位节的使用,防止影响其他外设的工作,这里有一步特殊的取值

P1=(P1&0xf0)|(motor_code[index]&0x0f);//屏蔽高4位的影响,只对P1低4位进行赋值,高4位和原来一样

这段代码实现的功能是

  1. 顺逆时针旋转
  2. 双击来回旋转(一定角度)

核心的步进电机代码

void motor_run()
{
	//步进电机转动函数
 if(beat || swing_flag)
	 {
		 if(dir==0 && curbeat>0)
		 {
			 P1=(P1&0xf0)|(motor_code[index]&0x0f);//屏蔽高4位的影响,只对P1低4位进行赋值,高4位和原来一样
			index--;
			if(index==-1) index=7;
		  curbeat--;
			 
		 }
		 else if(dir==1 && curbeat<64)
		 {
		  P1=(P1&0xf0)|(motor_code[index]&0x0f);
			index++;
			if(index==8) index=0; 
			 curbeat++;
			
		 }
		  if(curbeat==0 && swing_flag){dir=~dir;}
		  if(curbeat==64 && swing_flag) {dir=~dir;}
		  if(beat>0)beat--;
	 }
}

void timer_2ms() interrupt 1 
{
	static unsigned char count=0;
	TH0=63536>>8;
	TL0=63536;
	cur_sta_update();
	count++;
	if(count==5)
	{
		count=0;
		motor_run();
	}

}

全部代码

#include<reg51.h>
sbit k1=P2^0;
sbit k2=P2^1;
sbit k3=P2^3;
char beat=0;
char curbeat=0;
char index=0;
bit swing_flag=0;
bit dir=1;
unsigned char cur_sta[3]={1,1,1};
unsigned char pre_sta[3]={1,1,1};
unsigned char code motor_code[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};
void key_action(unsigned char key_value)
{
 if(key_value==1) //第一个按键
 {
	 if(swing_flag==0)
	 {
  dir=1;
	 beat=8;
	 }
 }
 else if(key_value==2) //第二个按键
 {
	 if(swing_flag==0)
	 {
   dir=0;
	 beat=8;
	 }
 }
 else if(key_value==3) ///两个按键同时按下
 {
  swing_flag=~swing_flag; //摇头功能控制flag
 }
}
unsigned char key_scan()
{
	char i;
  char key_value=0;
	
	//判断两个按键是否同时按下
	for(i=0;i<2;i++)
	{
	 if(pre_sta[i]!=cur_sta[i])
	 {
	  if(pre_sta[i])
		{
			 if(i==1 && cur_sta[0]==0) //当第二个按键按下时,第一个按键也正好处于按下状态
		   key_value=3;
		else
		 { 
			 key_value=i+1;
		 }
		}
		pre_sta[i]=cur_sta[i];// 状态更新
	 }
	}
	return(key_value);
}
void cur_sta_update()
{
	char i;
  static unsigned char keybuff[3]={0xff,0xff,0xff};
  
	//八次更新状态,要是按键对应的八位都为1则是按下
	keybuff[0]=(keybuff[0]<<1)|k1;
  keybuff[1]=(keybuff[1]<<1)|k2;
  keybuff[2]=(keybuff[2]<<1)|k3;
	
	//遍历三个按键
  for(i=0;i<3;i++)
 {
  if(keybuff[i]==0xff)
		cur_sta[i]=1;
	else if(keybuff[i]==0x00)
		cur_sta[i]=0;
 }
}
void motor_run()
{
	//步进电机转动函数
 if(beat || swing_flag)
	 {
		 if(dir==0 && curbeat>0)
		 {
			 P1=(P1&0xf0)|(motor_code[index]&0x0f);//屏蔽高4位的影响,只对P1低4位进行赋值,高4位和原来一样
			index--;
			if(index==-1) index=7;
		  curbeat--;
			 
		 }
		 else if(dir==1 && curbeat<64)
		 {
		  P1=(P1&0xf0)|(motor_code[index]&0x0f);
			index++;
			if(index==8) index=0; 
			 curbeat++;
			
		 }
		  if(curbeat==0 && swing_flag){dir=~dir;}
		  if(curbeat==64 && swing_flag) {dir=~dir;}
		  if(beat>0)beat--;
	 }
}
void timer_config()
{
	//定时器配置函数
  EA=1;
	ET0=1;
	TR0=1;
	TMOD=0x01;
	TH0=63536>>8;
	TL0=63536;
}
void main()
{
	char key_value=0;
	 timer_config();
 while(1)
 {
	key_value=key_scan();//返回按键值
	 key_action(key_value);
 }
}
void timer_2ms() interrupt 1 
{
	static unsigned char count=0;
	TH0=63536>>8;
	TL0=63536;
	cur_sta_update();
	count++;
	if(count==5)
	{
		count=0;
		motor_run();
	}

}

小知识点

  • (对于51而言)由于减速比的存在,并且步进电机驱动的前几个节拍很可能是无效的,即前几个节拍可以直接忽视,不用调的很精确,对最后的精度影响也不是很大。步进电机的旋转的精度控制又是一个很复杂的东西,可能涉及惯性、通电时长、扭矩、驱动力等等等,需要一步步的调整参数,对于不同承重的旋转又有不同的要求。
  • 可以通过硬件进行消抖和限制运动,但大概率会增加机械结构,从而增加成本,用软件都可以直接实现,进而减少成本的损耗
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值