PLC
直播中

丁冬芹

7年用户 1236经验值
私信 关注

带有以太网接口的Fanuc数控系统的数据采集方法

FOCAS是什么?
FOCAS有哪些基本功能?
Fanuc数控系统的数据采集方法是什么?

回帖(1)

陈芳

2021-9-29 15:32:16
  1.1 Fanuc数控系统机床数据采集方法
  以下介绍的为带有以太网接口的Fanuc数控系统的数据采集方法,如果不带有以太网接口,需要采用串口通讯进行采集。
  1.1.1 FOCAS简介和基本功能
  采集Fanuc系列的机床数据,我们需要用到FOCAS1/2开发包,FOCAS是FANUC Open CNC API Specifications version 1 or 2的缩写,FOCAS1主要应用于0i和16i/18i/21i/系列,FOCAS2则针对30i/31i/32i系列CNC。
  CNC/PMC数据窗口功能可以通过HSSB或以太网(TCP/IP)接口在PC和CNC之间完成交换数据和信息共享,他的主要功能包括以下几部分:
  1:CNC:NC控制的伺服轴、主轴相关数据的读写。
  包括绝对坐标、相对坐标、机床坐标、剩余移动量以及实际进给速度等。
  2:CNC:加工程序的相关操作。
  这些操作包括NC程序的上传/下载、程序校检、查找以及删除。读取CNC程序目录以及通过电脑实现CNC加工。
  3:CNC:读写CNC文件数据。
  这些数据包括刀具偏置、工件坐标系偏置、参数、设定、用户宏程序变量、P-Code宏程序变量以及螺距误差补偿数值。
  4:CNC:读写刀具寿命管理信息。
  5:CNC:读取历史信息记录。
  这些信息包括操作历史记录和报警历史记录。
  6:CNC:读取伺服、主轴数据。
  7:CNC:读写数据服务器、DNC1、DNC2、OSI-Ethernet(只能使用HSSB)相关信息。
  8:CNC:读写波形诊断数据。
  9:CNC:读写冲床CNC数据。
  10:CNC:读写激光器CNC数据。
  11:CNC:读写伺服学习控制相关数据(只能使用HSSB)。
  12:CNC:读写其他数据。
  13:PMC:读写PMC相关数据。
  这些数据包括G、F、Y、X、A、R、T、C、D地址等。
  14:PMC:读写PROFIBUS-DP相关内容。
  1.1.2使用以太网方式连接的相关设定
  FOCAS 通过以太网方式连接电脑和 CNC 系统时,使用 TCP/IP 通讯协议。在 CNC 上通常使用 FANUC 以太网板,或者 FANUC 快速以太网板。对于 16i/18i/21i 系列或者 30i/31i/32i系列,还可以使用内嵌以太网功能。
  使用 FOCAS 通讯时,可以按照以下步骤进行设定:
  设定电脑 ip,网上邻居 -》 本地连接 -》 Internet 协议(TCP/IP)。
  2. 在 CNC 上设定以太网功能或者内嵌以太网功能相关参数,MDI 上 system 键 -》“向右” 扩展键 -》 “ETHPRM”软键 -》 “(操作)”软键 -》 “板卡”软键
  在这个画面设定端口号(TCP)8193,时间间隔10。
  3 。 使用网线连接电脑和 CNC。一般使用交叉线,如果通过集线器、交换机等设备,则使用直通线。
  1.1.3详细开发流程
  准备工作:FOCAS2开发包(包含Fwlib32.dll等需要用到的dll);
  VisualStudio 2017;
  FOCAS说明文档(所有机床相关数据函数调用方法 )
  FOCAS_Api_Help;(以XML文件形式提供一些接口上的帮助)
  2、开发流程
  (1)连接方式:采用以太网连接,实验采用的CNC的IP地址为192.168.0.1,端口号为8193,PC侧IP只要配在同一个局域网即可,实验用的PC机的IP为192.168.0.10。IP的配置方法这里不再赘述。
  (2)PC端工程搭建操作:使用visual studio 2017新建一个C# Windows窗体应用程序,如下图:
  
  然后进入工程文件,部署FOCAS文件,如下图所示:
  
  如上图所示,首先将将fwlib32.cs文件添加至工程文件,该文件在FOCAS2_LibrariesFwlibDot NET sample路径下。然后在你新建的项目的binDebug目录下将要用到的动态链接库全部考进去。如下图所示,所用到的dll在FOCAS2_Libraries下的Fwlib文件夹中,直接全部拷到工程目录下即可。
  做完以上的所有准备工作后就可以正式开始开发了。
  3、API函数的使用方法:API具体的函数调用方法可以参见FOCAS说明文档,如下图所示:
  
  
  这里只对一些常用的API函数进行介绍。
  与CNC建立连接:参考FOCAS说明文档中的Function related to library handle, node文件夹中的Function Reference related to library handle, node_cnc_allclibhndl3.doc.在测试与机床连接函数时,要首先建立机床与PC机的物理连接,保证他们之间能够ping通,具体方法这里不再赘述。参考代码如下:
  private void btnConc_Click(object sender, EventArgs e)
  {
  string ip = txtIp.Text;
  string port = txtPort.Text;
  string timeout = txtTimeOut.Text;
  int ret = Fanuc.cnc_allclibhndl3(ip, Convert.ToUInt16(port), Convert.ToInt32(timeout), out Fanuc.h);
  if (ret == Fanuc.EW_OK)
  {
  //“函数方法””
  }
  与CNC断开连接:参考FOCAS说明文档中的Function related to library handle, node文件夹中的Function Reference related to library handle, node_cnc_freelibhndl.doc,具体代码如下:
  private void btnDisConn_Click(object sender, EventArgs e)
  {
  int ret = Fanuc.cnc_freelibhndl(Fanuc.h);
  if (ret == Fanuc.EW_OK)
  {
  MessageBox.Show(“与机床断开连接”);
  }
  else
  {
  MessageBox.Show(ret + “”);
  }
  }
  采集坐标信息:我们需要参考FOCAS说明文档:
  Fanuc.ODBPOS fos = new Focas1.ODBPOS();
  public void get_postion()//获取位置信息
  {
  short num = Fanuc.MAX_AXIS;
  short type = -1;
  short ret = Fanuc.cnc_rdposition(Fanuc.h, type, ref num, fos);
  if (ret == 0)
  {
  //相对坐标
  label12.Text = fos.p1.rel.name.ToString();
  label13.Text = fos.p2.rel.name.ToString();
  //label14.Text = fos.p3.rel.name.ToString();
  label15.Text = fos.p4.rel.name.ToString();
  label16.Text = fos.p5.rel.name.ToString();
  X_Relative.Text = Convert.ToString(fos.p1.rel.data * Math.Pow(10, -fos.p1.rel.dec));
  Z_Relative.Text = Convert.ToString(fos.p2.rel.data * Math.Pow(10, -fos.p2.rel.dec));
  //textBox10.Text = Convert.ToString(fos.p3.rel.data * Math.Pow(10, -fos.p3.rel.dec));
  C_Relative.Text = Convert.ToString(fos.p4.rel.data * Math.Pow(10, -fos.p4.rel.dec));
  V_Relative.Text = Convert.ToString(fos.p5.rel.data * Math.Pow(10, -fos.p5.rel.dec));
  //绝对坐标
  label21.Text = fos.p1.abs.name.ToString();
  label20.Text = fos.p2.abs.name.ToString();
  label18.Text = fos.p4.abs.name.ToString();
  label17.Text = fos.p5.abs.name.ToString();
  X_Absolute.Text = Convert.ToString(fos.p1.abs.data * Math.Pow(10, -fos.p1.abs.dec));
  Z_Absolute.Text = Convert.ToString(fos.p2.abs.data * Math.Pow(10, -fos.p2.abs.dec));
  C_Absolute.Text = Convert.ToString(fos.p4.abs.data * Math.Pow(10, -fos.p4.abs.dec));
  V_Absolute.Text = Convert.ToString(fos.p5.abs.data * Math.Pow(10, -fos.p5.abs.dec));
  //机器坐标
  label26.Text = fos.p1.mach.name.ToString();
  label25.Text = fos.p2.mach.name.ToString();
  //label24.Text = fos.p3.mach.name.ToString();
  label23.Text = fos.p4.mach.name.ToString();
  label22.Text = fos.p5.mach.name.ToString();
  X_Machine.Text = Convert.ToString(fos.p1.mach.data * Math.Pow(10, -fos.p1.mach.dec));
  Z_Machine.Text = Convert.ToString(fos.p2.mach.data * Math.Pow(10, -fos.p2.mach.dec));
  C_Machine.Text = Convert.ToString(fos.p4.mach.data * Math.Pow(10, -fos.p4.mach.dec));
  V_Machine.Text = Convert.ToString(fos.p5.mach.data * Math.Pow(10, -fos.p5.mach.dec));
  //剩余移动距离
  label31.Text = fos.p1.dist.name.ToString();
  label30.Text = fos.p2.dist.name.ToString();
  label28.Text = fos.p4.dist.name.ToString();
  label27.Text = fos.p5.dist.name.ToString();
  X_DistanceToGo.Text = Convert.ToString(fos.p1.dist.data * Math.Pow(10, -fos.p1.dist.dec));
  Z_DistanceToGo.Text = Convert.ToString(fos.p2.dist.data * Math.Pow(10, -fos.p2.dist.dec));
  C_DistanceToGo.Text = Convert.ToString(fos.p4.dist.data * Math.Pow(10, -fos.p4.dist.dec));
  V_DistanceToGo.Text = Convert.ToString(fos.p5.dist.data * Math.Pow(10, -fos.p5.dist.dec));
  }
  }
  采集主轴转速:我们需要参考说明文档的Function related to controlled axis&spindle_cnc_acts.doc.以下为采集主轴转速的函数参考:
  采 Fanuc.ODBACT pindle = new Focas1.ODBACT();
  public void get_pindle()//获取主轴的转速
  {
  short num = 32;
  short ret = Fanuc.cnc_acts(Fanuc.h, pindle);
  if (ret == 0)
  {
  SpindleSpeed.Text = pindle.data.ToString();
  }
  }集主轴、伺服轴的负载:参考说明文档:
  Function related to controlled axis&spindle_cnc_rdspmeter.doc
  Function related to controlled axis&spindle_cnc_rdsvmeter.doc.参考代码如下:
  Fanuc.ODBSVLOAD sv = new Focas1.ODBSVLOAD();
  Fanuc.ODBSPLOAD sp = new Focas1.ODBSPLOAD();
  public void get_load()//主,伺服轴的加载计//测试成功
  {
  short a = 6;//伺服轴的数量
  short ret = Fanuc.cnc_rdsvmeter(Fanuc.h, ref a, sv);
  short ret2 = Fanuc.cnc_rdspmeter(Fanuc.h, 1, ref a, sp);
  if (ret == 0 && ret2 == 0)
  {
  SpindleLoad.Text =Convert.ToString(sp.spload1.spload.data);
  sv1_Load.Text = Convert.ToString(sv.svload1.data); //伺服轴1负载
  sv2_Load.Text = Convert.ToString(sv.svload2.data); //伺服轴2负载
  sv3_Load.Text = Convert.ToString(sv.svload3.data); //伺服轴3负载
  sv4_Load.Text = Convert.ToString(sv.svload4.data); //伺服轴4负载
  }
  采集主轴名称:参考说明文档的
  Function related to controlled axis&spindle_cnc_rdspdlname.doc。参考代码如下:
  //获取主轴名称
  Fanuc.ODBEXAXISNAME spindlename = new Focas1.ODBEXAXISNAME();
  public void get_spindlename()
  {
  short data_num = 32;
  short ret = Focas1.cnc_exaxisname(Fanuc.h,1,ref data_num, spindlename);
  if(ret==0)
  {
  Spindle_Name.Text = spindlename.axname1;
  }
  采集实际进给速度:参考说明文档的
  Function related to controlled axis&spindle_cnc_actf.doc。参考代码如下:
  Focas1.ODBACT odbact = new Focas1.ODBACT();
  public void get_actfeed() {
  short ret = Focas1.cnc_actf(Fanuc.h,odbact);
  if (ret == 0)
  {
  RelFeedRate.Text = Convert.ToString(odbact.data);
  }
  }
  获取机床的状态:参考说明文档的 Function related to others_cnc_statinfo.doc。参考代码如下:
  //机床状态
  Fanuc.ODBST obst = new Focas1.ODBST();
  public void get_state()//获取机器的状态
  {
  Fanuc.cnc_statinfo(Fanuc.h, obst);
  cnc_status.Text = Convert.ToString(obst.run);//0停止,1待机,开动
  Alarm_Status.Text = Convert.ToString(obst.alarm);//0没有警报,1表示有警报
  RunningMode.Text = Convert.ToString(obst.tmmode);
  }
  获取主程序号、正在运行的程序号:参考说明文档的
  Function related to CNC program_cnc_rdprgnum.doc。参考代码如下:
  Fanuc.ODBPRO pro = new Fanuc.ODBPRO();
  public void get_program()
  {
  short ret = Focas1.cnc_rdprgnum(Fanuc.h, pro);
  if (ret == 0)
  {
  CurrentRunningProgramNumber.Text = Convert.ToString(pro.data);
  MainProgramNumber.Text = Convert.ToString(pro.mdata);
  //}
  }
  获取报警类型:参考说明文档的Function related to others_cnc_alarm2.doc。参考代码如下:
  获取报警类型
  public void get_alarmtype() {
  int alarm = 0;
  short ret = Focas1.cnc_alarm2(Fanuc.h,out alarm);
  if (ret == 0)
  {
  switch (alarm)
  {
  case 0:
  listBox3.Items.Add(“Parameter switch on (SW)”);
  Global.AlarmType = “Parameter switch on (SW)”;
  break;
  case 1:
  listBox3.Items.Add(“Power off parameter set (PW)”);
  Global.AlarmType = “Power off parameter set (PW)”;
  break;
  case 2:
  listBox3.Items.Add(“I/O error (IO)”);
  Global.AlarmType = “I/O error (IO)”;
  break;
  case 3:
  listBox3.Items.Add(“Foreground P/S (PS)”);
  Global.AlarmType = “Foreground P/S (PS)”;
  break;
  case 4:
  listBox3.Items.Add(“Overtravel,External data”);
  Global.AlarmType = “Overtravel,External data”;
  break;
  case 5:
  listBox3.Items.Add(“Overheat alarm”);
  Global.AlarmType = “Overheat alarm”;
  break;
  case 6:
  listBox3.Items.Add(“Servo alarm”);
  Global.AlarmType = “Servo alarm”;
  break;
  case 8:
  listBox3.Items.Add(“Data I/O error”);
  Global.AlarmType = “Data I/O error”;
  break;
  case 9:
  listBox3.Items.Add(“Spindle alarm”);
  Global.AlarmType = “Spindle alarm”;
  break;
  case 10:
  listBox3.Items.Add(“Other alarm(DS)”);
  Global.AlarmType = “Other alarm(DS)”;
  break;
  case 11:
  listBox3.Items.Add(“Alarm concerning Malfunction prevent functions (IE)”);
  Global.AlarmType = “Alarm concerning Malfunction prevent functions (IE)”;
  break;
  case 12:
  listBox3.Items.Add(“Background P/S (BG)”);
  Global.AlarmType = “Background P/S (BG)”;
  break;
  case 13:
  listBox3.Items.Add(“Syncronized error (SN)”);
  Global.AlarmType = “Syncronized error (SN)”;
  break;
  case 14:
  listBox3.Items.Add(“reserved”);
  Global.AlarmType = “reserved”;
  break;
  case 15:
  listBox3.Items.Add(“External alarm message”);
  Global.AlarmType = “External alarm message”;
  break;
  case 16:
  listBox3.Items.Add(“reserved”);
  Global.AlarmType = “reserved”;
  break;
  case 17:
  listBox3.Items.Add(“reserved”);
  Global.AlarmType = “reserved”;
  break;
  case 18:
  listBox3.Items.Add(“reserved”);
  Global.AlarmType = “reserved”;
  break;
  case 19:
  listBox3.Items.Add(“PMC error (PC)”);
  Global.AlarmType = “PMC error (PC)”;
  break;
  default:
  listBox3.Items.Add(“No Alarm”);
  Global.AlarmType = “No Alarm”;
  break;
  }
  }
  }
  获取报警类型:参考说明文档的Function related to others_cnc_rdalmmsg2.doc。参考代码如下:
  Fanuc.ODBALMMSG2 msg = new Focas1.ODBALMMSG2();
  public void get_message()
  {
  short b = 8;
  short ret = Fanuc.cnc_rdalmmsg2(Fanuc.h, -1, ref b, msg);
  string str1 = “msg”;
  System.Type type = msg.GetType();
  if (ret == 0)
  {
  for (int i = 1; i 《 3; i++)
  {
  str1 = “msg” + i;
  object obj = type.GetField(str1).GetValue(msg);
  System.Type type1 = obj.GetType();
  AlarmNumber.Text = Convert.ToString(type1.GetField(“alm_no”).GetValue(obj));
  listBox4.Items.Add(type1.GetField(“alm_msg”).GetValue(obj).ToString());
  Global.AlarmMessage = type1.GetField(“alm_msg”).GetValue(obj).ToString();
  }
  }
  }
  获取循环时间:这个API采FOCAS说明文档中没有找到,但是在XML所提供的API Help中有介绍,这里我参考api help的介绍和对机床的一些基本了解写了一下采集循环时间的函数,可供参考,代码如下:
  public void get_circleTime()
  {
  Fanuc.IODBPSD_1 param6757 = new Fanuc.IODBPSD_1();
  Fanuc.IODBPSD_1 param6758 = new Fanuc.IODBPSD_1();
  short ret = Fanuc.cnc_rdparam(Fanuc.h, 6757, 0, 8, param6757);
  if (ret == 0)
  {
  int circlingTimeSec = param6757.ldata / 1000;
  ret = Fanuc.cnc_rdparam(Fanuc.h, 6758, 0, 8, param6758);
  if (ret == 0)
  {
  int circlingTimeMin = param6758.ldata;
  int workingTime = circlingTimeMin * 60 + circlingTimeSec;
  CirclingTime.Text = Convert.ToString(workingTime) + “秒”;
  }
  }
  }
  这里需要注意的是Fanuc.cnc_rdparam这个函数中的第二个参数要明白其含义,它代表的是机床PARAMETER参数表的序号,如下图所示,编号6757和6758表示的是循环时间,其中6757存储的值单位是ms,6758存储的值单位是min。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分