matlab机器人 联合单片机仿真

matlab机器人 联合单片机仿真
文章图片


%这里的每个连杆的数据是和下一个坐标系之间的关系,也就是求得的是机械手末端的坐标系
L{1} =link([-pi/20pi/2000.00001 0 0 0 0 0 0 0 0 0 0 0],'sta')% 0.00001是连杆质量
L{2} =link([0149043200.0000001 0 0 0 0 0 0 0 0 0 0 0],'sta')
L{3} =link([pi/20pi/2-2000.0000001 0 0 0 0 0 0 0 0 0 0 0],'sta')
L{4} =link([-pi/24330000.0000001 0 0 0 0 0 0 0 0 0 0 0],'sta')
L{5} =link([pi/200000.0000001 0 0 0 0 0 0 0 0 0 0 0],'sta')
L{6} =link([0560000.000004 0 0 0 0 0 0 0 0 0 0 0],'sta')
p560m=robot(L);
c=[0 0 pi/2 0 0 0];
T1=fkine(p560m,c);
T2=T1-[0 0 0 500; 0 0 0 -200; 0 0 0 0; 0 0 0 0];
t=0:0.056:10;
T=ctraj(T1,T2,length(t));
p=ikine(p560m,T);
%%%%%%%%%%%%%%%%%%%%%%%%%%添加的求步进电机所需脉冲
bjj=pi/180*5.625*1/64; %步进角度pi/180是matlab1的1个度的角度值1/64是减速比
p1=p(length(t),:)-c; %取得 目标时的关节角 与 初始关节角 之差
p2=rem(p1,pi*2) ; %对差角取余数 得到一圈之内的角度
for i1=1:6%把反转角改为统一正转
ifp2(1,i1)<0
p2(1,i1)=2*pi+p2(1,i1);
end
end
mcf=round(p2/bjj); % 得到要输入的脉冲个数

%%%%%%%%%%%%%%%%%%%%%%%%%%%5%%%%%%%%创建端口
%也可以用scom=serial(‘COM1‘,‘BaudRate‘,9600,‘Parity‘,‘none‘,‘DataBits‘,8,‘StopBits‘,1)

scom=serial('com1'); %创建串口1的设备对象scom%%%%%使用的是虚拟串口com1
scom.Terminator='LF'; %设置终止符为CR(回车符),缺省为LF(换行符)
scom.InputBufferSize=1024; %输入缓冲区为256B,缺省值为512B
scom.OutputBufferSize=1024; %输出缓冲区为256B,缺省值为512B
scom.Timeout=0.5; %Y设置一次读或写操作的最大完成时间为0.5s,缺省值为10s
scom.BaudRate=9600; %波特率
scom.Parity='none'; %无奇偶校验位
scom.StopBits=1; %%停止位
scom.ReadAsyncMode='continuous'; %(缺省方式)读取连续接收数据 自动地存入输入缓冲区
scom.BytesAvailableFcnMode='byte'; %中断触发事件为 接收到的字符数达到人工设定的数目时
scom.BytesAvailableFcnCount=16; %接收缓冲区每收到16个字节时,触发回调函数
scom.BytesAvailableFcn=@instrcallback; %得到回调函数句柄
fopen(scom); %连接串口设备对象

fwrite(scom,mcf,'uint16'); % 每个数据以16 位 写入单片机
out=fread(scom,1,'uint8'); %读取返回的检测值
kg=1;
whilekg==1%检测是否发送成功
if out(1,1)==255%说明没有发送成功
for i=1:1000;
aaaa=0;
end
fwrite(scom,mcf,'uint16');
out=fread(scom,1,'uint8')
elseifout(1,1)==254
break
end
end
%当不再使用该串口设备对象时,顺序使用3条命令,可以将所创建的串口对象对象清除,以免占用系统资源。
fclose(scom); %关闭串口设备对象
delete(scom); %删除内存中的串口设备对象
clear scom; %清除工作空间中的串口设备对象

%%fprintf(scom,'%d',fff); %写串口,发送握手信号0xFF(等价于十进制下的数值255)
% fprintf,写函数,以字符方式写
% fwrite(obj,A),写函数,以二进制方式写,A为写入的数据,以数组形式存储
% out=fscanf(scom,'%d',[1,6])读函数,以字符方式读,以Terminator为 结束符,带有超时返回功能
%out=fread(scom,4,‘uint8‘)%接收单片机发送的4个数据(8位),并存入out数组中
% fread(obj,size),读函数,以而进制方式读,读指定字符数
% fgets,读函数,以字符方式读,包括Terminator
% fgetl,读函数,以字符方式读,忽略Terminator

for i=1:10:length(t)% 正常轨迹 i=1:length(t)
x(i)=T(1,4,i);
y(i)=T(2,4,i);
z(i)=T(3,4,i);
end
%plot3(x,y,z)%画出运动轨迹
%plot(p560m,p)
%plot(p)% 画出各个关节角的变量图
%drivebot(p560m)

t1=t'
%B1=[t1 F]%电机输出力矩
%B2=[t1 U]%电机控制电压
a1=p(:,1)
a2=p(:,2)
a3=p(:,3)
a4=p(:,4)
a5=p(:,5)
a6=p(:,6)
%输出到 simulink的变量 [t1,a1]
%plot(F)

=============================================================================================
==============================================================================================
单片机程序
【matlab机器人 联合单片机仿真】 ============================================================================================
==============================================================================================
/*************************************************************************************
*标题:步进电机试验二 *
* *
*; 单双八拍工作方式:*
*; A-AB-B-BC-C-CD-D-DA (即一个脉冲,转 3.75 度)
**************************************************************************************/
#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int
uchar Receive_Buffer[13]; //接收缓冲
uchar Buf_Index=0; //缓冲空间索引
int a1,a2,aa;
uchar code table1[4]={0x03,0x06,0x0c,0x09}; /*4节拍正转表*/
uchar code table2[4]={0x03,0x09,0x0c,0x06}; /*4节拍反转表*/
uchar code FFW[8]={0xfe,0xfc,0xfd,0xf9,0xfb,0xf3,0xf7,0xf6}; //八节拍
intzj16[6]; // //申请用于 保存合并好的16位数据
void delay(unsigned int t);
/// //
//void Serial_INT(); //测试
//uchar c; //测试
//数码管编码
//uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
//Motor
sbit F1 = P1^0;
sbit F2 = P1^1;
sbit F3 = P1^2;
sbit F4 = P1^3;
步进电机驱动
voidmotor_ffw()
{

//int i1=0; //最大脉冲
int i2=0; //当前脉
int j=0;

int kg=1; //循环结束开关
int PP1,PP2,PP3;
while(kg==1)
{
//0000000000000
if(i2<=zj16[0]&&i2<=zj16[1])
{PP1 = FFW[j]&0xf; //取节拍
PP2=PP1;
PP3=PP2<<4;
P0=PP1|PP3; // 给P0脚的两个电动机赋值
kg=1;
}
elseif(i2<=zj16[0])
{ P0 = FFW[j]&0xf; // 给p0角的 第1个电动机赋值
kg=1;
}
elseif(i2<=zj16[1])
{PP1 = FFW[1]&0xf;
PP2=PP1;
P0=PP2<<4; // 给p0角的 第2个电动机赋值
kg=1;
}
else {kg=0; }
//11111111111
if(i2<=zj16[2]&&i2<=zj16[3])
{ PP1 = FFW[j]&0xf;

PP2=PP1;
PP3=PP2<<4;
P1=PP1|PP3;
kg=1; //// 给P1脚的两个电动机赋值}
elseif(i2<=zj16[2])
{ P1 = FFW[j]&0xf;
kg=1;
}
elseif(i2<=zj16[3])
{PP1 = FFW[1]&0xf;
PP2=PP1;
P1=PP2<<4;
kg=1; 给p1角的 第二个电动机赋值
}
else {kg=0; }
//22222222222222222
if(i2<=zj16[4]&&i2<=zj16[5])
{PP1 = FFW[j]&0xf;

PP2=PP1;
PP3=PP2<<4;
P2=PP1|PP3; // 给P2脚的两个电动机赋值
kg=1;
}
elseif(i2<=zj16[4])
{ P2= FFW[j]&0xf;
kg=1;
}
elseif(i2<=zj16[5])
{PP1= FFW[1]&0xf;
PP2=PP1;
P2=PP2<<4; //给p2角的 第二个电动机赋值
kg=1;
}
else {kg=0; }
//----------------------------
//i1++;

j++ ;
if(j>=8){ j=0; }//在8拍内转
//if(i1>=0xffff){break; }//避免无限循环
delay(10); //调节转?
}

}


/////步进电机驱动 2222222222222 测试电机
voidmotor_ffw1()
{
unsigned char i;

for (i=0; i<8; i++)//一个周期转30度
{
P1 = FFW[i]&0x1f; //取数据
delay(4); //调节转速
}
}

/延时
void delay(uint ms)
{
uchar i;
while(ms--) for(i=0; i<100; i++);
}
///主程序
main()
{
uchar i=0;
uchar j2=0;
P0=0x00;
Receive_Buffer[0]=-1;
Receive_Buffer[12]=0;
SCON=0x50; // 串口模式1,允许接收
TMOD=0x20; //T1 工作模式2
TH1=0xfd; //波特率9600
TL1=0xfd;
PCON=0x00; //波特率不倍增
EA=1; EX0=1; IT0=1;
ES=1; IP=0x01;
TR1=1;
while(1)
{//motor_ffw1(); //测试电机

// c=1;
//for(i=0; i<12; i++){ Serial_INT(); }//测试 整个程序

if(Receive_Buffer[12]==-1)

{
j2=0;
for(i=0; i<6; i++)
{
a1=Receive_Buffer[j2];

a2=Receive_Buffer[j2+1];
a2<<=8;
aa=a1|a2; //合并为16位字节
zj16[i]=aa*2; //保存到数组*2是因为matlab按4拍计算,这里变为8拍
j2=j2+2;
}
motor_ffw();
Receive_Buffer[12]=0;
}
delay(4);
}
}
// 串口接收中断函数
void Serial_INT()interrupt 4
{
uchar c; //测试
if(RI==0) return; // 测试
ES=0; //关闭串口中断
RI=0; //清接收中断标志
c=SBUF; //测试
if(Receive_Buffer[12]==0)
{

Receive_Buffer[Buf_Index]=c;
Buf_Index++;
if(Buf_Index>=12)
{//缓存新接收每12个字符,在其后放-1 为结束标志

Receive_Buffer[12]=-1;
Buf_Index=0;
ES=1;
SBUF=0xfe; // //返回给matlab接收成功标志 oxfe
while(TI==0); //ti=1 表示发送完毕
TI=0;
}
}
else{//否者就返回一个oxff失败标志
ES=1;
SBUF=0xff; / //返回给matlab接收失败标志 oxff
while(TI==0); //ti=1 表示发送完毕
TI=0;
}
ES=1;
}


/// //外部中断0 发送函数
void EX_INT0() interrupt 0
{
uchar *s="这是由8051 发送的字符串!====";
uchar i=0;
while(s[i]!='\0')
{
SBUF=s[i];
while(TI==0); //ti=1 表示发送完毕
TI=0;

i++;
}
i=0;
while(Receive_Buffer[i]!='z'&&i<12)
{
SBUF=Receive_Buffer[i];
while(TI==0); //ti=1 表示发送完毕
TI=0;

i++;
}
}





    推荐阅读