转自:http://www.cnblogs.com/qq78292959/archive/2009/09/22/2077085.html
SICK LMS200激光数据采集程序说明
1.设计功能
SICK LMS200激光扫描仪是将扫描得到的距离数据通过COM端口传送到接收端,再由终端设备对数据进行处理,完成对周边空间的探测。本程序分以下几部分:
一、串口通讯功能:发送、接收、显示数据;
二、数据处理功能:周期数据的截取,十六进制转十进制;
三、坐标标定功能:将距离数据标定在坐标系中;
2.串口通讯功能
2.1简介
由于激光扫描仪的数据量大,而且是实时产生的。为了提高串口读取数据的高速实时性,本程序的串口通讯部分是基于CSerialPort类完成的。该类支持线连接的串口编程,而且是基于多线程的。
2.2函数功能介绍
1.设置串口参数函数原型:
BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
UINT portnr, // portnumber (1..4)
UINT baud, // baudratechar parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etcUINT writebuffersize) // size to the writebuffer
2.串口监测线程:
BOOL CSerialPort::StartMonitoring()
BOOL CSerialPort::RestartMonitoring()
BOOL CSerialPort::StopMonitoring()
void CSerialPort::WriteChar(CSerialPort* port)
void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)
void CSerialPort::WriteToPort(char* string)
3.监测线程接收事件信息,再进行消息处理即可
2.3串口设置界面类
CconfigDlg完成串口的设置和事件的处理,设置界面如下图。
2.4发送数据
LMS200只识别十六进制的数据,因此在发送控制指令前要把指令转为十六进制。发送数据有单次发送,定时发送两张模式。
工作流程:
1:在“发送指令”编辑框中输入控制指令;
2:在“发送设置”中选择发送类型;
3:点击“单次发送”或“定时发送”根据选择的发送模式发送指令;
实现函数:
////////////////////////////////////////////////
将发送数据转为十六进制
void CSerialTestDlg::SendHexData(char*buf)
////////////////////////////////////////////////
将发送数据转为ASCII码
void CSerialTestDlg::SendAsciiData(char *buf)
2.5接收数据
终端接收到的数据形式如下:
06 02 80 03 00 A0 00 10 16 0A 02 80 D6 02 B0 69 41 20 02 15 02 F2 01 99 01 61 01 30 01 0D 01 06 01 F4 00 DC 00 D3 00 D1 00 C3 00 CF 00 CC 00 D3 00 C7 00 D3 00 D0 00 D0 00 D6 00
CserialPort类中监视线程接收事件信息WM_COMM_RXCHAR与CSerialTestDlg::OnCommunication(WPARAM Char, LPARAM num)函数建立消息响应,接收LMS200返回的数据,然后根据用户要求转换为十六进制和ACII码。
实现函数:
////////////////////////////////////////////////
接收串口数据
LONG CSerialTestDlg::OnCommunication(WPARAM Char, LPARAM num)
3.数据处理功能
LMS200返回的数据结构如下:
3.1.具体说明
1:发送启动指令后LMS200首先是返回一个06 02 80 03 00 A0 00字符串 10位。 因采样角频率而不同。
2:校验位3位,每个周期都不一样;
3:返回数据6位,每个周期都不变;
4:距离数据722位;
5:下一周期重复2-4步;
3.2.数据处理
以采样角频率为10 为例,对数据的分析可知,距离数据的字符串长度为722*3=2166(含有空格),本程序的是按每行51个字符串显示如图所示。这样我们可以知道需要44行的数据才包含一个周期的数据,44*51=2244即存储这段数据的字符串的总长度是2244,而有效的距离数据是从51~2215这段字符串。总字符串转化成字符数组,用数组char array[2245],arraydata[2166]分别来存储总的字符和距离字符。
现在就是对距离字符数组进行处理,每两个十六进制表示一个返回的距离数据,低位在前,高位在后。所以处理第一步先把高低位互换,再把十六进制转为十进制。
1:0F 02 12 02 E7 01
2:02 0F 02 12 01 E7
3:020F 0212 01E7
4:527 530 487
接着把一个周期的数据存储在Data[361](0.50)或Data1[181](10)中,完成对一个周期数据的截取。
3.3实现函数
////////////////////////////////////////////////
将接收到的十六进制数据转换为十进制
void CSerialTestDlg::HexToDec(CString str){}
////////////////////////////////////////////////
完成对应采样角频率的处理
if(m_angleComb.GetCurSel()==0){} 0.50
if(m_angleComb.GetCurSel()==1){} 10
////////////////////////////////////////////////
截取需要的字符串长度
StrData.GetLength()==2244
////////////////////////////////////////////////
高位,低位换位
for(k=0;k<=2160;k+=6){}
////////////////////////////////////////////////
十六进制转为十进制
do
{}
while(j
4.坐标标定
根据采样角频率的不同,一个周期的距离数据分别有181个(10 )和361个(0.50 )数据。如下图所示:d为我们得到的数据,a为对应的角度,对应到笛卡尔坐标中:
x=d*cosa (1)