两个光电管,两个步进电机独立控制,互不干扰。
简单介绍下,步进电机常态是不动的,我需要控制步进电机在某个角度内转动,当光电管被遮挡时,步进电机就要向后退,但是最多退90度,当光电管没有遮挡时,步进电机就尝试复位到原来位置。
为了达到某个角度内转动,我设计了加法器,步进电机的位移被存储起来,往前移动一个步机单位就加1,往后移动一个单位就减1,始终检测加法器的值,确保值在确定角度之间,在此之间做判断和移动。
我用数码管显示步进电机的状态,用不同的字母和数字表示。
增加了蜂鸣器报警,如果超过转动角度,蜂鸣器就被触发,直到角度在正常范围内。
两个电机的控制是不干扰的,并行控制,因为切换的很快,好像是同时控制的,其实就像cpu时间切片控制一样,短时间内在两个任务之间不断往返。如果需要更快更高精度、连接控制单元更多的控制,考虑换更快、io端口更多的芯片。
//功能:光电管被遮住,步进电机转90度;无遮挡,步进电机逆转90度。
#include
#include
#define uchar unsigned char
#define uint unsigned int
***it motor = P1^0;//位定义步进电机1脉冲信号端口
***it block = P1^1; //位定义接收光电开关1遮挡信号的端口
***it dir = P1^2;//位定义步进电机1方向控制端口
***it motor2 = P3^0;//位定义步进电机2脉冲信号端口
***it block2 = P3^1; //位定义接收光电开关2遮挡信号的端口
***it dir2 = P3^2;//位定义步进电机2方向控制端口
***it WE = P2^7;
***it DU = P2^6;
***it beep = P2^3;
uchar i; //电机转动角度,i = 1 表示转动1.8度
uint maxSum = 1600; //步进电机1能转到的最大步数,一步为1.8度 1600
uint maxSum2 = 1600; //步进电机2能转到的最大步数,一步为1.8度 1600
int sumDegree; //记录步进电机1转过的角度数
int sumDegree2; //记录步进电机2转过的角度数
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度
}
}
///步进电机2正反转/
void motor2_degree(uchar i) // i取值0-255
{
dir2 = 0; //方向设置为正转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor2 = 0;
delay();
motor2 = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
void invert_motor2_degree(uchar i) // i取值0-255
{
dir2 = 1; //方向设置为反转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor2 = 0;
delay();
motor2 = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
前四个数码管显示机械臂1的状态/
void shumaguanShow1()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x06; //数码管显示1
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguanShow0()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x3f; //数码管显示0
DU = 0;
beep = 1;
delay();
}
void shumaguanShowError()
{
WE = 1; //打开位选锁存器
P0 = 0xf0; //选中数码管1111 0000
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x79; //数码管显示字母E
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguanShowStraight()
{
WE = 1;//打开位选
P0 = 0xf0;//选中数码管1111 0000
WE = 0; //关闭位选
DU = 1; //打开段选
P0 = 0x40; //显示-
DU = 0; //关闭段选
beep = 1;
delay();
}
//后四个数码管显示机械臂2状态///
void shumaguan2Show1()
{
WE = 1; //打开位选锁存器
P0 = 0x7f; //选中数码管1110 1111
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x06; //数码管显示1
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguan2Show0()
{
WE = 1; //打开位选锁存器
P0 = 0x7f; //选中数码管1110 1111
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x3f; //数码管显示0
DU = 0;
beep = 1;
delay();
}
void shumaguan2ShowError()
{
WE = 1; //打开位选锁存器
P0 = 0x0f; //选中数码管0000 1111
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x79; //数码管显示字母E
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguan2ShowStraight()
{
WE = 1;//打开位选
P0 = 0x0f;//选中数码管0000 1111
WE = 0; //关闭位选
DU = 1; //打开段选
P0 = 0x40; //显示-
DU = 0; //关闭段选
beep = 1;
delay();
}
void main()
{
while(1)
{
///步进电机1的控制算法/
if(sumDegree <= maxSum && sumDegree >= 0 ) //如果步数和大于0,小于等于最大步数,可以继续后退
{
if(block == 0) //光电开关被遮挡,反转1步
{
shumaguanShow1(); //数码管显示1
invert_motor_degree(1);// 反转1步
sumDegree--; //总步数减1
}
else //光电开关无遮挡
{
shumaguanShow0(); //数码管显示0
motor_degree(1);// 无遮挡,正转1步
sumDegree++; //总步数加1
}
} //如果步数和等于0,说明在最前方,任何情况都不前进,有遮挡后退
else if(sumDegree < 0) //如果步数和小于0,则不能后退了,有遮挡不动,无遮挡前进。
{
if(block == 0) //光电开关被遮挡,电机不动
{
shumaguanShowError(); //报警提示
}
else //光电开关无遮挡,电机正转
{
shumaguanShow0();
motor_degree(1); //正转1步
sumDegree++; //总步数加1
}
}
else //如果步数和大于50,则不能前进了,无遮挡不动,有遮挡反转。
{
if(block == 0) //光电开关有遮挡,电机反转
{
shumaguanShow1();
invert_motor_degree(1);
sumDegree--;
}
else //光电管无遮挡,电机不动,显示机械臂伸直状态----
{
shumaguanShowStraight();
}
}
步进电机2的控制算法/
if(sumDegree2 <= maxSum2 && sumDegree2 >= 0 ) //如果步数和大于0,小于 最大步数,可以继续后退
{
if(block2 == 0) //光电开关被遮挡,反转1步
{
shumaguan2Show1(); //数码管显示1
invert_motor2_degree(1);// 反转1步
sumDegree2--; //总步数减1
}
else //光电开关无遮挡
{
shumaguan2Show0(); //数码管显示0
motor2_degree(1);// 无遮挡,正转1步
sumDegree2++; //总步数加1
}
} //如果步数和等于0,说明在最前方,任何情况都不前进,有遮挡后退
else if(sumDegree2 < 0) //如果步数和小于0,则不能后退了,有遮挡不动,无遮挡前进。
{
if(block2 == 0) //光电开关被遮挡,电机不动
{
shumaguan2ShowError(); //报警提示
}
else //光电开关无遮挡,电机正转
{
shumaguan2Show0();
motor2_degree(1); //正转1步
sumDegree2++; //总步数加1
}
}
else //如果步数和大于50,则不能前进了,无遮挡不动,有遮挡反转。
{
if(block2 == 0) //光电开关有遮挡,电机反转
{
shumaguan2Show1();
invert_motor2_degree(1);
sumDegree2--;
}
else //光电管无遮挡,电机不动,显示机械臂伸直状态----
{
shumaguan2ShowStraight();
}
}
}
}
两个光电管,两个步进电机独立控制,互不干扰。
简单介绍下,步进电机常态是不动的,我需要控制步进电机在某个角度内转动,当光电管被遮挡时,步进电机就要向后退,但是最多退90度,当光电管没有遮挡时,步进电机就尝试复位到原来位置。
为了达到某个角度内转动,我设计了加法器,步进电机的位移被存储起来,往前移动一个步机单位就加1,往后移动一个单位就减1,始终检测加法器的值,确保值在确定角度之间,在此之间做判断和移动。
我用数码管显示步进电机的状态,用不同的字母和数字表示。
增加了蜂鸣器报警,如果超过转动角度,蜂鸣器就被触发,直到角度在正常范围内。
两个电机的控制是不干扰的,并行控制,因为切换的很快,好像是同时控制的,其实就像cpu时间切片控制一样,短时间内在两个任务之间不断往返。如果需要更快更高精度、连接控制单元更多的控制,考虑换更快、io端口更多的芯片。
//功能:光电管被遮住,步进电机转90度;无遮挡,步进电机逆转90度。
#include
#include
#define uchar unsigned char
#define uint unsigned int
***it motor = P1^0;//位定义步进电机1脉冲信号端口
***it block = P1^1; //位定义接收光电开关1遮挡信号的端口
***it dir = P1^2;//位定义步进电机1方向控制端口
***it motor2 = P3^0;//位定义步进电机2脉冲信号端口
***it block2 = P3^1; //位定义接收光电开关2遮挡信号的端口
***it dir2 = P3^2;//位定义步进电机2方向控制端口
***it WE = P2^7;
***it DU = P2^6;
***it beep = P2^3;
uchar i; //电机转动角度,i = 1 表示转动1.8度
uint maxSum = 1600; //步进电机1能转到的最大步数,一步为1.8度 1600
uint maxSum2 = 1600; //步进电机2能转到的最大步数,一步为1.8度 1600
int sumDegree; //记录步进电机1转过的角度数
int sumDegree2; //记录步进电机2转过的角度数
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度
}
}
///步进电机2正反转/
void motor2_degree(uchar i) // i取值0-255
{
dir2 = 0; //方向设置为正转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor2 = 0;
delay();
motor2 = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
void invert_motor2_degree(uchar i) // i取值0-255
{
dir2 = 1; //方向设置为反转
while(i--) //i个脉冲,步进电机转动i*1.8度
{
motor2 = 0;
delay();
motor2 = 1;
delay(); //1个脉冲,步进电机转动1.8度
}
}
前四个数码管显示机械臂1的状态/
void shumaguanShow1()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x06; //数码管显示1
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguanShow0()
{
WE = 1; //打开位选锁存器
P0 = 0xfe; //选中第一位数码管1111 1110
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x3f; //数码管显示0
DU = 0;
beep = 1;
delay();
}
void shumaguanShowError()
{
WE = 1; //打开位选锁存器
P0 = 0xf0; //选中数码管1111 0000
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x79; //数码管显示字母E
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguanShowStraight()
{
WE = 1;//打开位选
P0 = 0xf0;//选中数码管1111 0000
WE = 0; //关闭位选
DU = 1; //打开段选
P0 = 0x40; //显示-
DU = 0; //关闭段选
beep = 1;
delay();
}
//后四个数码管显示机械臂2状态///
void shumaguan2Show1()
{
WE = 1; //打开位选锁存器
P0 = 0x7f; //选中数码管1110 1111
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x06; //数码管显示1
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguan2Show0()
{
WE = 1; //打开位选锁存器
P0 = 0x7f; //选中数码管1110 1111
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x3f; //数码管显示0
DU = 0;
beep = 1;
delay();
}
void shumaguan2ShowError()
{
WE = 1; //打开位选锁存器
P0 = 0x0f; //选中数码管0000 1111
WE = 0; // 锁存位选数据
DU = 1;
P0 = 0x79; //数码管显示字母E
DU = 0;
beep = 0; //报警提示
delay();
}
void shumaguan2ShowStraight()
{
WE = 1;//打开位选
P0 = 0x0f;//选中数码管0000 1111
WE = 0; //关闭位选
DU = 1; //打开段选
P0 = 0x40; //显示-
DU = 0; //关闭段选
beep = 1;
delay();
}
void main()
{
while(1)
{
///步进电机1的控制算法/
if(sumDegree <= maxSum && sumDegree >= 0 ) //如果步数和大于0,小于等于最大步数,可以继续后退
{
if(block == 0) //光电开关被遮挡,反转1步
{
shumaguanShow1(); //数码管显示1
invert_motor_degree(1);// 反转1步
sumDegree--; //总步数减1
}
else //光电开关无遮挡
{
shumaguanShow0(); //数码管显示0
motor_degree(1);// 无遮挡,正转1步
sumDegree++; //总步数加1
}
} //如果步数和等于0,说明在最前方,任何情况都不前进,有遮挡后退
else if(sumDegree < 0) //如果步数和小于0,则不能后退了,有遮挡不动,无遮挡前进。
{
if(block == 0) //光电开关被遮挡,电机不动
{
shumaguanShowError(); //报警提示
}
else //光电开关无遮挡,电机正转
{
shumaguanShow0();
motor_degree(1); //正转1步
sumDegree++; //总步数加1
}
}
else //如果步数和大于50,则不能前进了,无遮挡不动,有遮挡反转。
{
if(block == 0) //光电开关有遮挡,电机反转
{
shumaguanShow1();
invert_motor_degree(1);
sumDegree--;
}
else //光电管无遮挡,电机不动,显示机械臂伸直状态----
{
shumaguanShowStraight();
}
}
步进电机2的控制算法/
if(sumDegree2 <= maxSum2 && sumDegree2 >= 0 ) //如果步数和大于0,小于 最大步数,可以继续后退
{
if(block2 == 0) //光电开关被遮挡,反转1步
{
shumaguan2Show1(); //数码管显示1
invert_motor2_degree(1);// 反转1步
sumDegree2--; //总步数减1
}
else //光电开关无遮挡
{
shumaguan2Show0(); //数码管显示0
motor2_degree(1);// 无遮挡,正转1步
sumDegree2++; //总步数加1
}
} //如果步数和等于0,说明在最前方,任何情况都不前进,有遮挡后退
else if(sumDegree2 < 0) //如果步数和小于0,则不能后退了,有遮挡不动,无遮挡前进。
{
if(block2 == 0) //光电开关被遮挡,电机不动
{
shumaguan2ShowError(); //报警提示
}
else //光电开关无遮挡,电机正转
{
shumaguan2Show0();
motor2_degree(1); //正转1步
sumDegree2++; //总步数加1
}
}
else //如果步数和大于50,则不能前进了,无遮挡不动,有遮挡反转。
{
if(block2 == 0) //光电开关有遮挡,电机反转
{
shumaguan2Show1();
invert_motor2_degree(1);
sumDegree2--;
}
else //光电管无遮挡,电机不动,显示机械臂伸直状态----
{
shumaguan2ShowStraight();
}
}
}
}
举报