//功能:控制步进电机活动范围在90度以内,在此区间内,通过光电管控制步进电机的正反转:光电管被遮挡反转,无遮挡正转。
#include 《reg52.h》
#include 《intrins.h》
#define uchar unsigned char
#define uint unsigned int
***it motor = P1^0;//位定义电机脉冲信号端口
***it block = P1^1; //位定义接收光电开关遮挡信号的端口
***it dir = P1^2;//位定义步进电机方向控制端口
***it WE = P2^7;
***it DU = P2^6;
***it stop = P1^3;
***it beep = P2^3;
uchar i; //电机转动角度,i = 1 表示转动1.8度
uint maxSum = 1600; //步进电机能转到的最大步数,一步为1.8度
int sumDegree; //记录电机转过的角度数
void delay(void) //误差 -0.217013888889us
{
uchar a,b;
for(b=20 ;b》0;b--) //初值80
for(a=10;a》0;a--);
}
//void delay_ms(uchar i) //误差 -0.000000000227us,延时0.1秒
//{
// uchar a,b,c;
// for(c=13*i;c》0;c--)
// for(b=247;b》0;b--)
// for(a=142;a》0;a--);
// _nop_; //if Keil,require use intrins.h
//}
void motor_degree(uchar i) // i取值0-255
{
dir = 0; //方向设置为正转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor = 0;
delay();
motor = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
void invert_motor_degree(uchar i) // i取值0-255
{
dir = 1; //方向设置为反转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor = 0;
delay();
motor = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
void InitShumaguan()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
}
void shumaguanShow1()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x06;
DU = 0;
// beep = 0; //报警提示
}
void shumaguanShow0()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x3f;
DU = 0;
// beep = 1;
}
void shumaguanShowError()
{
WE = 1; //打开位选锁存器
P0 = 0x00; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x79; //数码管显示字母E
DU = 0;
// beep = 0; //报警提示
}
void shumaguanShowStraight()
{
WE = 1;//打开位选
P0 = 0x00;//左边第一位数码管显示
WE = 0; //关闭位选
DU = 1; //打开段选
P0 = 0x40; //显示-
DU = 0; //关闭段选
}
void main()
{
InitShumaguan();//第一位数码管选定
while(1)
{
while(sumDegree 《= maxSum && sumDegree 》= 0 ) //如果步数和大于0,小于 最大步数,可以继续后退
{
if(block == 0) //光电开关被遮挡,反转1步
{
shumaguanShow1(); //数码管显示1
invert_motor_degree(1);// 反转1步
sumDegree--; //总步数减1
}
if(block == 1) //光电开关无遮挡
{
shumaguanShow0(); //数码管显示0
motor_degree(1);// 无遮挡,正转1步
sumDegree++; //总步数加1
}
} //如果步数和等于0,说明在最前方,任何情况都不前进,有遮挡后退
while(sumDegree 《 0) //如果步数和小于0,则不能后退了,有遮挡不动,无遮挡前进。
{
if(block == 0) //光电开关被遮挡,电机不动
{
shumaguanShowError(); //报警提示
}
if(block == 1) //光电开关无遮挡,电机正转
{
shumaguanShow0();
motor_degree(1); //正转1步
sumDegree++; //总步数加1
}
}
while(sumDegree 》 maxSum) //如果步数和大于50,则不能前进了,无遮挡不动,有遮挡反转。
{
if(block == 0) //光电开关有遮挡,电机反转
{
shumaguanShow1();
invert_motor_degree(1);
sumDegree--;
}
if(block == 1) //光电管无遮挡,电机不动,显示机械臂伸直状态----
{
shumaguanShowStraight();
}
}
}
}
想让步进电机限制在0-90度之间旋转,这里有两个状态,状态1:步进电机处于零度角,状态2:步进电机处于90度角。
这里我用了查询方式,设置一个计步器,正转步数加1,反转步数减1,步数加到最大步数,步进电机就不能正转了,光电管检测不到障碍物,就进入一个空函数中不断循环,这就解决了不超过90度的问题。步数减到0,步进电机就不能反转了,光电管检测到障碍物,就进入到另一个空函数不断循环,这就解决了不小于0度的问题。
注意,每次检测完障碍物,执行相应的函数后,一定要再返回来判断角度是不是在0-90以内。这就从根本上杜绝了电机瞎转。
//功能:控制步进电机活动范围在90度以内,在此区间内,通过光电管控制步进电机的正反转:光电管被遮挡反转,无遮挡正转。
#include 《reg52.h》
#include 《intrins.h》
#define uchar unsigned char
#define uint unsigned int
***it motor = P1^0;//位定义电机脉冲信号端口
***it block = P1^1; //位定义接收光电开关遮挡信号的端口
***it dir = P1^2;//位定义步进电机方向控制端口
***it WE = P2^7;
***it DU = P2^6;
***it stop = P1^3;
***it beep = P2^3;
uchar i; //电机转动角度,i = 1 表示转动1.8度
uint maxSum = 1600; //步进电机能转到的最大步数,一步为1.8度
int sumDegree; //记录电机转过的角度数
void delay(void) //误差 -0.217013888889us
{
uchar a,b;
for(b=20 ;b》0;b--) //初值80
for(a=10;a》0;a--);
}
//void delay_ms(uchar i) //误差 -0.000000000227us,延时0.1秒
//{
// uchar a,b,c;
// for(c=13*i;c》0;c--)
// for(b=247;b》0;b--)
// for(a=142;a》0;a--);
// _nop_; //if Keil,require use intrins.h
//}
void motor_degree(uchar i) // i取值0-255
{
dir = 0; //方向设置为正转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor = 0;
delay();
motor = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
void invert_motor_degree(uchar i) // i取值0-255
{
dir = 1; //方向设置为反转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor = 0;
delay();
motor = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
void InitShumaguan()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
}
void shumaguanShow1()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x06;
DU = 0;
// beep = 0; //报警提示
}
void shumaguanShow0()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x3f;
DU = 0;
// beep = 1;
}
void shumaguanShowError()
{
WE = 1; //打开位选锁存器
P0 = 0x00; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x79; //数码管显示字母E
DU = 0;
// beep = 0; //报警提示
}
void shumaguanShowStraight()
{
WE = 1;//打开位选
P0 = 0x00;//左边第一位数码管显示
WE = 0; //关闭位选
DU = 1; //打开段选
P0 = 0x40; //显示-
DU = 0; //关闭段选
}
void main()
{
InitShumaguan();//第一位数码管选定
while(1)
{
while(sumDegree 《= maxSum && sumDegree 》= 0 ) //如果步数和大于0,小于 最大步数,可以继续后退
{
if(block == 0) //光电开关被遮挡,反转1步
{
shumaguanShow1(); //数码管显示1
invert_motor_degree(1);// 反转1步
sumDegree--; //总步数减1
}
if(block == 1) //光电开关无遮挡
{
shumaguanShow0(); //数码管显示0
motor_degree(1);// 无遮挡,正转1步
sumDegree++; //总步数加1
}
} //如果步数和等于0,说明在最前方,任何情况都不前进,有遮挡后退
while(sumDegree 《 0) //如果步数和小于0,则不能后退了,有遮挡不动,无遮挡前进。
{
if(block == 0) //光电开关被遮挡,电机不动
{
shumaguanShowError(); //报警提示
}
if(block == 1) //光电开关无遮挡,电机正转
{
shumaguanShow0();
motor_degree(1); //正转1步
sumDegree++; //总步数加1
}
}
while(sumDegree 》 maxSum) //如果步数和大于50,则不能前进了,无遮挡不动,有遮挡反转。
{
if(block == 0) //光电开关有遮挡,电机反转
{
shumaguanShow1();
invert_motor_degree(1);
sumDegree--;
}
if(block == 1) //光电管无遮挡,电机不动,显示机械臂伸直状态----
{
shumaguanShowStraight();
}
}
}
}
想让步进电机限制在0-90度之间旋转,这里有两个状态,状态1:步进电机处于零度角,状态2:步进电机处于90度角。
这里我用了查询方式,设置一个计步器,正转步数加1,反转步数减1,步数加到最大步数,步进电机就不能正转了,光电管检测不到障碍物,就进入一个空函数中不断循环,这就解决了不超过90度的问题。步数减到0,步进电机就不能反转了,光电管检测到障碍物,就进入到另一个空函数不断循环,这就解决了不小于0度的问题。
注意,每次检测完障碍物,执行相应的函数后,一定要再返回来判断角度是不是在0-90以内。这就从根本上杜绝了电机瞎转。
举报