胡选仲,张 鹏,陈景光,陈 城
(中机试验装备股份有限公司,吉林 长春 130103)
随着科技的不断发展,对校直机(车桥校平类)的需求日益增加。由于此类设备之前应用进口光栅尺,成本较高,不利于校直机(车桥校平类)设备的应用。经过多年的研发,国产光栅尺现已可以满足校直产品的应用需求。
本文根据实际情况和对光栅尺应用情况的综合评估,选择国产光栅尺和对应的采集盒,并将其应用于校直设备。国产光栅尺系统在校直机产品上的成功应用,标志着国产光栅尺可以代替进口光栅尺产品,这会极大地降低此类产品的成本、缩短此类原材料的采购周期,具有重要的应用价值。
针对适配器多路国产光栅尺数据采集进行针对性的开发,利用串口(RS485)进行适配器与上位机通信,获得采集盒采集到的原始光栅尺数据,再将采集到的数据进行解析与处理,最终得到多路光栅尺中每路光栅尺的具体数据。把这些数据作为校直产品的基本数据,再根据校直的具体需求进行运算处理,最终达到完成校直产品的目的,硬件构成如图1所示。
图1 硬件构成
2.2.1 上位机
配置要求:上位机需具备串口通信接口,如果上位机只有RS232串口接口,那就需要外部连接一个RS232转RS485的硬件(如图2所示)。
图2 RS232转RS485的硬件
2.2.2 适配器
功能:首要任务是适配器进行光栅尺数据采集工作,这也是适配器的基本工作,适配器与光栅尺交互数据信息如图3所示。适配器完成数据采集后,将数据提供给上位机。上位机利用串口通信的方式,从适配器读到当前所有光栅尺的数据,间接获得光栅尺数据。适配器在光栅尺数据的采集过程中,起到了承上启下的作用。
图3 适配器与光栅尺交互数据信息
2.2.3 光栅尺
精度:分辨率0.01μm级别;功能:利用光栅的光学原理工作,能够精密反馈位移,其数据是校直软件中测量数据的基础值,所以要求较高,必须准确无误地反馈位移值,才能为保证校直精度和节拍提供基本保障。
系统:Windows7;软件:Visual Studio 2017、DevExpressComponentsBundle-18.1.6;语言:C#语言;描述:利用DevExpressComponentsBundle-18.1.6控件中的串口控件,通过C#语言进行光栅尺数据采集模块的编程与开发[1]。
通信模式:串口通信。
串口参数:
波特率:115200bps;停止位:1位;数据位:8位;校验位:无奇偶校验位。
协议类型:USART协议。
传输方式:RS485。
数据结构介绍与描述:数据ID和数据域的关系如图4所示。
图4 数据ID和数据域
数据描述:
帧头:0X1A;STA:状态域;EA:错误及报警;D00~D03:编码器0数据(数据全0XFF表示编码器未连接,数据全为0XEE表示CRC错误);D10~D13:编码器1数据(数据全0XFF表示编码器未连接,数据全为0XEE表示CRC错误);D20~D23:编码器2数据(数据全0XFF表示编码器未连接,数据全为0XEE表示CRC错误);D30~D33:编码器3数据(数据全0XFF表示编码器未连接,数据全为0XEE表示CRC错误)。
首先是硬件的搭建,把多路光栅尺与适配器相连接,再把适配器和上位机连接,这样就可以利用串口通信协议[2,3],使上位机和适配器之间建立通信及信息交互。具体交互信息是利用上位机向适配器发送事先定义的请求数据,适配器给上位机返回采集到的原始数据,上位机对数据进行分析,最终解析出每个光栅尺的数据,完成上位机与适配器接口之间信息交互。
主要设置串口通信参数,然后再打开串口,程序如下:
var port = new SerialPort {PortName = "COM" + (GlobalParametersManager.SysS etting.SensorComPort + 1), };
port.BaudRate = 115200;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = 0; GlobalParametersManager.serialPortManager.OpenSerialPort(port, s =>
{
try
{
s = s.Trim();
if (s.Length != 11)
{
LoggingHelper.Error(string.Format(LNG._("光栅尺错误"), s), true);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
});
Thread.Sleep(10);
通过串口读取数据,再进行数据处理(读取每个光栅尺数据并转换数据单位到μm)。校直软件要求数据采集过程中不能有错误,故采用了报错机制,不论哪一路数据异常,都会通过软件界面报错提示客户,并附带处理建议和方法,具体程序如下:
private void ComReceive(object sender, SerialDataReceivedEventArgs e)
{
int data1 = 0, data2 = 0;
ReceiveCompleted = false;
if (_recStaus) //如果已经开启接收
{
try
{
Thread.Sleep(50);
ReceivedDataPacket = new byte[CurrentSerialPort.BytesToRead];
ReceivedDataPacketChar = new char[CurrentSerialPort.BytesToRead];
// change to char datas
if (ByteMode)
{
CurrentSerialPort.Read(ReceivedDataPacket, 0, ReceivedDataPacket.Length);
if (ReceivedDataPacket.Length == 12)
{
string strTemp = "";
if (ReceivedDataPacket[0] == 26)
{
string[] abc = new string[4];
int[] abcd = new int[4];
if ((ReceivedDataPacket[5]) == 255) //判断1号光栅尺错误
{
strTemp = "1号光栅尺错误,";
LoggingHelper.Error(LNG._(strTemp + "请检查1号光栅尺是否连接正常"), true);
return;
}
else if (ReceivedDataPacket[5] == 0) //1号光栅尺返回正常数据
{
for (int k = 0; k < 4; k++)
{
abc[k] = ReceivedDataPacket[1 + k].ToString();
abcd[k] = Convert.ToInt32(abc[k]);
}
data1 = abcd[3] + abcd[2] * 256 + abcd[1] * 256 * 256 + abcd[0] * 256 * 256 * 256;
//光栅尺每变化一个分辨率大小,串口数据增加1(29Bit 分辨率:10μm)
data1 = data1 / 100;
GlobalParametersManager.IntParas[0] = data1;
ErrCount = 0;
}
else//判断1号光栅尺错误
{
strTemp = "1号光栅尺错误,";
LoggingHelper.Error(LNG._(strTemp + "关闭软件后对光栅尺重新上电"), true);
return;
}
if ((ReceivedDataPacket[10]) == 255) //判断2号光栅尺错误
{
strTemp = "2号光栅尺错误,";
LoggingHelper.Error(LNG._(strTemp + "请检查2号光栅尺是否连接正常"), true);
return;
}
else if (ReceivedDataPacket[10] == 0) //2号光栅尺返回正常数据
{
for (int j = 0; j < 4; j++)
{
abc[j] = ReceivedDataPacket[6 + j].ToString();
abcd[j] = Convert.ToInt32(abc[j]);
}
data2 = abcd[3] + abcd[2] * 256 + abcd[1] * 256 * 256 + abcd[0] * 256 * 256 * 256;
data2 = data2 / 100;
GlobalParametersManager.IntParas[1] = data2;
ErrCount = 0;
}
else//判断2号光栅尺错误
{
strTemp = "2号光栅尺错误,";
LoggingHelper.Error(LNG._(strTemp + "关闭软件后对光栅尺重新上电"), true);
return;
}
}
else//判断光栅尺错误
{
LoggingHelper.Error(LNG._(strTemp + "关闭软件后对光栅尺重新上电"), true);
return;
}
}
else if (ReceivedDataPacket.Length > 1) //判断光栅尺错误
{
LoggingHelper.Error(LNG._("光栅尺异常,关闭软件后对光栅尺重新上电"), true);
}
}
else
{
CurrentSerialPort.Read(ReceivedDataPacketChar, 0, CurrentSerialPort.BytesToRead);
string strTemp = "";
foreach (var b in ReceivedDataPacketChar)
{
strTemp += string.Format("{0}", b);
}
LoggingHelper.Message(LNG._("接收到串口数据:") + strTemp);
_action?.Invoke(strTemp);
}
ReceiveCompleted = true;
}
catch (Exception)
{
if (CurrentSerialPort.IsOpen == false) //如果ComPort.IsOpen == false,说明串口已丢失
{
SetComLose(); //串口丢失后相关设置
}
else
{
LoggingHelper.Error(LNG._("不能接收数据"));
}
}
}
else //暂停接收
{
CurrentSerialPort.DiscardInBuffer(); //请接收缓存
}
}
通过串口进行数据发送,如果上位机想要得到光栅尺数据,就需要上位机向光栅尺采集盒发送固定的数据(光栅尺采集盒已经定义的协议),具体代码程序如下:
var rc = false;
Byte[] WriteBuffer00 = new byte[1];
WriteBuffer00[0] = 0X1A;
rc = GlobalParametersManager.serialPortManager.SendDataPacket(WriteBuffer00); //向适配器发送数据
if (!rc) //返回值异常
{
LoggingHelper.Error(LNG._("采集光栅尺指令发送异常"), true);
return;
}
本文详细介绍了光栅尺数据采集过程,并成功地将国产光栅尺应用于校直设备。通过此次产品开发,可以极大地降低生产成本、缩短采购周期,从而有效提高此类校直机的市场竞争力。通过已经在部分项目上的成功应用,证明国产光栅尺完全可以广泛地应用在此类校直机产品上。