较Version 1.0, 增加了对针臂步进电机、针臂停留底部时间的控制模块, 可通过给定参数以定量方式控制针臂抬起落下的速度或控制针臂在底部停留的时间.
硬件搭建:
8051单片机(STC89C52RC) + 若干杜邦线 + 虚拟接口卡 + 虚拟接口卡专用USB线 + 8051专用USB线.
连线对接:
P1.0 -> P20
P1.1 -> P21
P1.2 -> P22
P1.3 -> P03
P0.0 -> P00
P0.1 -> P01
P0.2 -> P02
注: 左侧为虚拟接口卡接口, 右侧为STC89C52RC接口.
在此补充一下驱动系统的命令:
1. Start.E命令: 启动系统.
2. Stop.E命令: 在一个周期序列动作完成后, 停止系统.
3. Rotate 0/1.E命令: 命令主转盘以顺时针/逆时针方向转动.
4. Main motor runs X(0 ~ 9).E命令: 在一个周期序列动作完成后, 停止系统, 以给定参数决定的速度, 转动X步主转盘.(这里借用针臂步进电机的时延函数来驱动主步进电机).
5. Main motor runs XX(10 ~ 99).E命令: 和4功能一致, 在给定的步数为两位数时使用.
6. Reset.E: 命令: 系统未进入到Start命令模式下且针臂未在该模式下进入到上下移位过程中, 针臂抬至上限位, 主转盘转至0号瓶位置, 之后停止工作.
7. Arm speeds XX, XX.E命令: 命令针臂以XX XX决定的参数上下移动.
8. Arm delays XXX, XXX.E命令: 命令针臂在底部停留的时间.
#include <STC89C5xRC.h>
char tcount = 0;
char step = 0;//记录主电机走过的步数(走过的步数=step/2)
char buf[30];//存放命令
int en = 0;//en = 1 -> 系统工作, en = 0 -> 系统停止
int k = 0;
int len = 0;
int re = 0;//复位信号, 1 -> 复位, 0 -> 不复位
int direction = 0;//0 -> 顺时针, 1 -> 逆时针
int step_B = 0;//命令要求主电机转的步数
int motorRun = 0;// 1 -> 按命令转相应步数, 0 -> 无动作
int S1 = 300;//针臂在底部停留时间参数1
int S2 = 400;//针臂在底部停留时间参数2
int A1 = 40;//针臂电机参数1
int A2 = 40; //针臂电机参数2
void delay(int A1, int A2)
{
int i,j;
for(i = 0; i < A1; i++)
for(j = 0; j < A2 ; j++)
{
;//为针臂步进电机提供时延
}
}
void delay2(int S1, int S2)//针臂在底部停留时延
{
int i,j;
for(i=0;i<S1;i++)
for(j=0;j<S2;j++)
{
;
}
}
void motor_Control(int steps)//控制主转盘电机转动指定步数
{
int i;
for(i = 0; i < steps; i++)
{
P20 = 0;
delay(A1, A2);
P20 = 1;
delay(A1, A2);
}
}
void timer0() interrupt 1
{
int i = 0;
if(step == 0)
{
if(direction == 0)
{
P21 = 0;//顺时针
}
else if(direction == 1)
{
P21 = 1;//逆时针
}
}
TR0 = 0;//关闭定时器0
TH0 = 0x3c;
TL0 = 0xB0;//50ms
if(re == 1)//复位信号起作用
{
re = 0;
//针臂移至上限位, 转盘转回0号瓶
P03 = 0;//往上转
while(P01 == 1)//若未到上限位置,P0.1接单片机P01
{
P22 = 0;
delay(A1, A2);
P22 = 1;
delay(A1, A2);
}
while(P00 == 1)//若未到0号瓶位置
{
P20 = 0;
delay(A1, A2);
P20 = 1;
delay(A1, A2);
}
//霍尔传感器有误差, 还差2.5格左右, 再发20个脉冲
if(P21 == 1)//转盘逆时针转过来
{
while(i++ < 20)
{
P20 = 0;
delay(A1, A2);
P20 = 1;
delay(A1, A2);
}
}
else if(P21 == 0)//转盘顺时针转过来
{
while(i++ < 22)
{
P20 = 0;
delay(A1, A2);
P20 = 1;
delay(A1, A2);
}
}
tcount = 0;
en = 0;
step = 0;
goto END;
}
if(motorRun == 1)//电机按要求转命令起作用
{
motorRun = 0;
step = 0;
tcount = 0;
en = 0;
motor_Control(step_B);
step_B = 0;
goto END;
}
tcount++;
if(tcount == 2)//100ms = 0.1s
{
P20 = ~P20;//P20翻转,相当于发送脉冲
tcount = 0;
step ++;
if(step / 2 == 8)//电机走了8步(经历了8次高低电平的转换)
{
step = 0;//将步数归零
//P1.3=1代表向下,P1.3=0代表向上
P03 = 1;//往下转,P13接单片机P03
while(P02 == 1)//若未到下限位置,P0.2接单片机P02
{
P22 = 0;
delay(A1, A2);
P22 = 1;
delay(A1 ,A2);
}
delay2(S1, S2);//针臂在底部停留片刻
P03 = 0;//往上转
while(P01 == 1)//若未到上限位置,P0.1接单片机P01
{
P22 = 0;
delay(A1, A2);
P22 = 1;
delay(A1, A2);
}
}
}//1000ms = 1s 发送一个完整的脉冲
END: ;
TR0 = 1;//开启定时器0
}
void UART_INT() interrupt 4//串行通信中断处理程序
{
int len = 0;
int j = 0;
if(RI == 1)//如果收到数据
{
if(k == 30)
{
k = 0;//防止越界访问
}
RI = 0;
buf[k++] = SBUF;//将数据接收下来
if(buf[k - 1] == 'E')//到达结尾
{
len = k - 1;//记录数据长度
k = 0;
if(len == 6)
{
if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'a' && buf[3] == 'r' && buf[4] == 't' && buf[5] == '.')
{
//Start命令(开机)
en = 1;
P27 = 0;//D8亮
P26 = 1;
P25 = 1;
P24 = 1;
//再将en的值传回去
SBUF = en + 48;
}
else if(buf[0] == 'R' && buf[1] == 'e' && buf[2] == 's' && buf[3] == 'e' && buf[4] == 't' && buf[5] == '.')//主转盘回到原始位置,针臂抬到最高位置
{
//Reset命令(复位命令)
en = 1;
P27 = 1;
P26 = 0;//D7亮
P25 = 1;
P24 = 1;
SBUF = en + 48;
re = 1;//复位信号
}
}
else if(len == 5)//停机命令
{
if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'o' && buf[3] == 'p' && buf[4] == '.')
{
//Stop命令(停机命令)
en = 0;
P27 = 1;
P26 = 1;
P25 = 0;//D6亮
P24 = 1;
SBUF = en + 48;
}
}
else if(len == 19)//要求主转盘转动相应格数(>=10)
{
if(buf[0] == 'M' && buf[1] == 'a' && buf[2] == 'i' && buf[3] == 'n' && buf[4] == ' ' && buf[5] == 'm' && buf[6] == 'o' && buf[7] == 't' && buf[8] == 'o' && buf[9] == 'r' && buf[10] == ' ' && buf[11] == 'r' && buf[12] == 'u' && buf[13] == 'n' && buf[14] == 's' && buf[15] == ' ' && buf[18] == '.')
{
//Main motor runs命令,比如Main motor runs 22.
if(buf[16] >= '1' && buf[16] <= '9' && buf[17] >= '1' && buf[17] <= '9')//确定发来的步数是数字
{
en = 1;
P27 = 1;
P26 = 1;
P25 = 1;
P24 = 0;//D5亮
SBUF = en + 48;
step_B = 8 * (((buf[16] - 48) * 10 + (buf[17] - 48)));
motorRun = 1;
}
}
}
else if(len == 18)//要求主转盘转动相应格数(<=9) 或 设定针臂电机两速度参数
{
if(buf[0] == 'M' && buf[1] == 'a' && buf[2] == 'i' && buf[3] == 'n' && buf[4] == ' ' && buf[5] == 'm' && buf[6] == 'o' && buf[7] == 't' && buf[8] == 'o' && buf[9] == 'r' && buf[10] == ' ' && buf[11] == 'r' && buf[12] == 'u' && buf[13] == 'n' && buf[14] == 's' && buf[15] == ' ' && buf[17] == '.')
{
//Main motor runs命令,比如Main motor runs 22.
if(buf[16] >= '1' && buf[16] <= '9')//确定发来的步数是数字
{
en = 1;
P27 = 1;
P26 = 1;
P25 = 1;
P24 = 0;//D5亮
SBUF = en + 48;
step_B = 8 * (buf[16] - 48);
motorRun = 1;
}
}
//Arm speeds 40, 40.命令
if(buf[0] == 'A' && buf[1] == 'r' && buf[2] == 'm' && buf[3] == ' ' && buf[4] == 's' && buf[5] == 'p' && buf[6] == 'e' && buf[7] == 'e' && buf[8] == 'd' && buf[9] == 's' && buf[10] == ' ' && buf[13] == ',' && buf[17] == '.')
{
if(buf[11] >= '0' && buf[11] <= '9' && buf[12] >= '0' && buf[12] <= '9' && buf[15] >= '0' && buf[15] <= '9' && buf[16] >= '0' && buf[16] <= '9')
{
//确认发来的是数字
A1 = (buf[11] - 48) * 10 + (buf[12] - 48);
A2 = (buf[15] - 48) * 10 + (buf[16] - 48);
}
}
}
else if(len == 9)//要求主转盘转动的方向
{
//Rotate 0/Rotate 1命令
if(buf[0] == 'R' && buf[1] == 'o' && buf[2] == 't' && buf[3] == 'a' && buf[4] == 't' && buf[5] == 'e' && buf[6] == ' ' && buf[8] == '.')
{
if(buf[7] == '0')
{
direction = 0;//顺时针
}
else if(buf[7] == '1')
{
direction = 1;//逆时针
}
}
}
else if(len == 20)//要求针臂在底部停留时间的两参数
{
//Arm delays 200, 500.命令
if(buf[0] == 'A' && buf[1] == 'r' && buf[2] == 'm' && buf[3] == ' ' && buf[4] == 'd' && buf[5] == 'e' && buf[6] == 'l' && buf[7] == 'a' && buf[8] == 'y' && buf[9] == 's' && buf[10] == ' ' && buf[14] == ',' && buf[15] ==' ' && buf[19] == '.')
{
if(buf[11] >= '0' && buf[11] <= '9' && buf[12] >= '0' && buf[12] <= '9' && buf[13] >= '0' && buf[13] <= '9' && buf[16] >= '0' && buf[16] <= '9' && buf[17] >= '0' && buf[17] <= '9' && buf[18] >= '0' && buf[18] <= '9')
{
//确认发来的是数字
S1 = (buf[11] - 48) * 100 + (buf[12] - 48) * 10 + (buf[13] - 48);
S2 = (buf[16] - 48) * 100 + (buf[17] - 48) * 10 + (buf[18] - 48);
}
}
}
}
}
else if(TI == 1)//如果发送数据完毕
{
TI = 0;
}
}
int main()
{
TMOD = 0x21;
TH0 = 0x3C;
TL0 = 0xB0;
IE = 0x92;
P20 = 0;//给虚拟接口卡P1.0发脉冲,以驱动主转盘步进电机
P22 = 0;//给虚拟接口卡P1.2发脉冲,以驱动针臂步进电机
TR0 = 1;//启动定时器0
//
SCON = 0x50;
TH1 = 0xe6;
TL1 = 0xe6;
TR1 = 1;//启动定时器1
RI = 0;
TI = 0;
IP = 0x10;//提升串口中断的优先级
P21 = 0;//主转盘电机方向, 默认为顺时针
while(1)
{
//如果en = 1开启timer0的中断, 否则将timer0的中断关闭
if(en == 1)
{
IE = 0x92;
}
else if(en == 0)
{
IE = 0x90;
}
}
}
/*
P1.0:转盘电机Pulse信号
P1.1:转盘电机Dir -> P21
P1.2:针臂电机Pulse
P1.3:针臂电机Dir
P0口:输出口,连接虚拟软件中的传感器信号
P0.0:霍尔传感器信号,平时为高电平,有效时为低电平 -> P00
P0.1:针臂上限位信号
P0.2:针臂下限位信号
*/