SICK LMS111激光雷达开发全攻略:从网络配置到Python数据解析
2026/9/7 6:41:28 网站建设 项目流程

简介:面向SICK LMS111激光扫描仪的开发程序包,适合需要与工业2D激光传感器进行数据交互的嵌入式、机器人及自动化工程师。压缩包共68个文件,其中31个头文件与28个C++源文件构成核心代码,另有3个文本文件、2个工程配置、2个解决方案文件,以及Doxyfile和CHM帮助文档;整体仅808KB,目录下分别存放源码、文档和工程文件,便于在Visual Studio中直接打开或按需集成。目前已有639人学习下载。SopasCommunication模块针对LMS100/LMS111系列封装了SOPAS协议通信与报文解析功能,覆盖串口参数设置、测量数据读取、扫描频率与分辨率配置等关键操作,并演示了从建立连接到获取扫描数据的完整流程,同时提供版本变更说明与代码注释。开发者通过研究源码,可以深入理解ASCII编码、串行通信、实时数据解析与错误处理等核心知识点,快速掌握LMS111的通信机制,大幅减少从零实现协议转换和容错处理的时间,为智能物流、安全监控和移动机器人等场景的二次开发打下坚实基础。 车间打电话过来说“传感器没数据了”,我到现场一看,SICK LMS111面板上红灯在闪,SOPAS里连不上,日志全是超时。后来问题倒是简单——PC网卡IP段没对上,但那次折腾让我把LMS111从硬件到通信协议彻底翻了个底朝天。这篇就是围绕SICK LMS111程序开发的一点积累,写给搞AGV防撞、区域监控、料位测量和各类外发项目的工程师,尤其是第一次接触LMS111、手上只有一本英文手册的朋友。

这篇不是把说明书翻译一遍,而是按“硬件脾气 → 网络准备 → 协议原理 → 数据解析 → 现场避坑”这条线走,保证你按步骤能跑通一套最简单的读数程序,再往后做区域判定、建图、多机同步都有基础。

1. 先搞清楚LMS111是什么脾气:扫描原理与两个关键参数

1.1 扫描原理

LMS111是一款2D单线激光雷达,用一个旋转棱镜把红外激光脉冲打出去,再接收来自物体的反射回波,通过飞行时间差算距离。它扫出来的是一圈平面点云,每圈都带角度信息,所以本质上它输出的是一组“距离+角度”的极坐标数据。

LMS111在SICK的LMS1xx系列里属于非常经典的型号,性价比高,网上资料也多。它的典型硬件参数如下表,不同批次以实际铭牌和手册为准:

参数典型值
供电10~30 V DC
接口以太网(部分型号带RS232/RS422)
扫描角度最大270°
测量距离0.5 m ~ 20 m(取决于目标反射率)
角分辨率0.25° / 0.5° / 1° 可配置
扫描频率常见25 Hz / 50 Hz
防护等级IP67

这里第一个关键参数是扫描角度和角分辨率。270°扫描角配合0.5°角分辨率,一圈就是541个测量点;如果配置成0.25°分辨率,点数翻倍到1081个。点数直接决定你通信带宽和程序内存里要开多大的缓冲区,写程序前必须先确定。

第二个关键参数是测量频率。25 Hz代表每秒钟传感器输出25圈数据,也就是40 ms一帧。如果你的控制周期是20 ms,就得考虑用最新一帧覆盖旧帧,而不是等数据阻塞。很多外发项目里“程序卡死”的假象,其实是读取线程没有处理好新旧帧关系。

1.2 写程序前必须先确认的三件事

第一,通信方式选以太网还是串口。LMS111主板上有以太网口,也有部分型号带RS232。我强烈建议用以太网,原因很简单:一次scan数据最多几十KB,串口9600/115200的波特率下传输延迟太明显,而且串口线上干扰问题多。以太网口默认TCP端口2111,后面所有程序都是基于这个端口。

第二,应用模式。LMS111可以用来做区域监控(在SOPAS里画防撞区域、输出开关量),也可以纯做测量输出(把每圈点云数据交给上位机自己算)。两者的程序侧重点完全不同。如果你只是要“前方有障碍物就停车”,那用区域监控更快,不一定需要写数据解析程序;如果你要做导航、建图、轮廓识别,就必须自己解析测量数据。这篇重点是后面的测量输出。

第三,安全边界。这里必须泼一盆冷水:LMS111本质是测量型激光雷达,不是完全符合功能安全认证的安全防撞雷达。如果项目涉及人员安全保护,请选择SICK带有安全等级认证的扫描仪型号,或者按设备供应商的安全评估结果来设计。这种“等出了问题再加安全措施”的教训我在现场见得太多了。

2. 连不上传感器?网络准备这一步挡了很多人

2.1 先别死记IP,用SOPAS扫描是最快的

很多人拿到LMS111第一件事是看铭牌上的IP地址,然后照着配电脑网卡,连不上就崩溃。SICK的SOPAS软件自带设备搜索功能,能自动扫出网段内所有传感器。第一次调试我建议这么走:

  1. 电脑网线直连LMS111的以太网口,其他网络暂时断开。
  2. 把电脑有线网卡配置成固定IP,网段和传感器一致。比如传感器常用地址是192.168.0.1,那电脑就设192.168.0.100、掩码255.255.255.0。
  3. 关掉Windows防火墙,或者至少允许SOPAS和后续的Python进程通过专用网络访问。
  4. 打开SOPAS,选“Search/Scan”扫描设备,等它列出传感器。
  5. 双击设备进入参数页面,确认当前IP、子网掩码、网关,然后在“Service”里重新规划所有设备的IP。

这里有个很容易踩的细节:如果电脑开了无线网卡,无线网卡和有线网卡同时活跃时,Windows可能把流量走到无线网卡上,导致SOPAS搜不到设备或者不稳定。调试时最好把无线网卡禁用,只保留有线连接。

2.2 SOPAS窗口里几项必须会看

SOPAS是SICK传感器的通用调试软件,界面信息很多,不用全懂,但下面几处建议熟记位置:

  • Device Measurement Setting:设置扫描频率、角分辨率、扫描区域起始角/终止角。注意改完分辨率后,点数会变化,后续程序解析的预期点数也要同步改。
  • Network Settings:修改IP、掩码、网关。建议正式上线前给每台传感器分配固定IP,并且做一个简单表格管理这些IP,避免多台设备混乱。
  • Display/Contamination:显示窗口脏污程度。这个很多人忽略,等数据全零才去查,其实这里很早就会报警。
  • Access Level / Password:改配置需要登录,常见维护密码是F4724744。读取测量数据通常不需要登录。

在SOPAS里改完参数,记得执行“Download to Device”把配置写入传感器,否则断电重启后参数又回到旧值。这个“改完不下载”的问题,几乎每个现场都会出现一次。

3. COL-A协议拆解:从一条echo命令到读懂返回数据

3.1 COL-A是什么

LMS111支持SICK的COL-A协议(Cola-ASCII),本质上就是基于TCP的文本命令协议,端口2111。它的好处是可读性强,你用telnet都能直接敲命令看返回,非常适合调试理解。

协议里两种常用命令:

  • sRN xxx:读取参数或请求数据。比如sRN LMDscandata请求一帧扫描数据。
  • sMN xxx:调用方法。比如sMN GetDeviceState获取设备状态。

请求扫描数据时,传感器返回以sRA LMDscandata开头的一长串ASCII字段,所有字段用空格分隔。这就是我们要解析的原始数据。

很多网友问“为什么我的Python连上2111端口后发sRN没反应”,常见原因有两个:一是命令末尾没有加换行符LF,传感器不识别;二是发送后没有持续接收,数据帧较大,一次recv读不完就以为没返回。

下面是我常用的最小验证流程:Windows Telnet连上后手动敲命令,或者用Python几行代码直接发。

import socket sock = socket.create_connection(("192.168.0.1", 2111), timeout=5) sock.sendall(b"sRN LMDscandata\n") data = sock.recv(65535) print(data[:500])

如果能看到sRA LMDscandata开头的内容,协议链路就通了。

3.2 返回数据怎么读

关于响应字段,官方文档会列出几十个字段,第一次看很劝退。我的经验是抓几个关键位置就够了:

字段示例含义
sRA LMDscandata响应标识
第2~5个字段版本号、设备编号、序列号等
scanCounter扫描帧计数器,每次扫描累加,判断丢帧用
timeSinceStartup传感器上电以来的时间,可用于相对时间戳
1 DIST1数据块标识,表示接下去是距离数据块
数据块后的控制字段编码器位置、通道数、比例因子、测量点数
后面的十六进制值每个测量点的距离值

实际解析不推荐从0开始数固定下标。固件版本不同,前面的状态字段可能增删。更稳妥的策略是在字段列表里先找到DIST1关键词,从这个位置往后偏移固定长度拿到数据区。下面这章会写具体代码。

4. Python读取LMS111:从socket建立到坐标点输出

4.1 建立连接并请求一帧数据

用Python做设备调试是最快的,标准库的socket就够用。连接后注意两件事:一个是所有命令要带LF换行,另一个是recv循环要能接收完整的TCP分片。

import socket SICK_IP = "192.168.0.1" SICK_PORT = 2111 sock = socket.create_connection((SICK_IP, SICK_PORT), timeout=5) sock.sendall(b"sRN LMDscandata\n") buf = b"" while True: chunk = sock.recv(65535) if not chunk: break buf += chunk if b"\n" in buf: break resp = buf.decode("ascii", errors="ignore").strip() fields = resp.split(" ") print("总字段数:", len(fields)) print(fields[:20])

这段代码先建立一个TCP连接,发送读取命令,然后循环接收直到遇到换行。recv(65535)的单次缓冲区要足够大,因为一帧scan数据最长能达到几十KB,缓冲区太小会导致数据被截断。

4.2 定位DIST1数据块并解析距离值

收到响应后,用DIST1作为锚点定位。找到DIST1后,它后面的四个字段分别是:编码器位置、通道数量、比例因子、测量点数量。从测量点数量字段之后再往后数,才是每个距离值。距离值以十六进制字符串形式存在,需要转成整数。

# 定位 DIST1 dist_index = None for i in range(len(fields) - 1): if fields[i] == "1" and fields[i + 1] == "DIST1": dist_index = i break if dist_index is None: raise RuntimeError("未找到DIST1数据块,请检查协议返回") data_offset = dist_index + 2 # 跳过 "1" 和 "DIST1" # data_offset + 0: 编码器位置 # data_offset + 1: 通道数量 # data_offset + 2: 比例因子 # data_offset + 3: 测量点数量 count = int(fields[data_offset + 3], 16) ranges = [] for j in range(count): hex_value = fields[data_offset + 4 + j] val = int(hex_value, 16) if val >= 0x8000: val -= 0x10000 ranges.append(val) print("测量点数:", len(ranges)) print("前10个距离值:", ranges[:10])

这里有一个处理负值的技巧:LMS111的距离数据是16位有符号整数,当数值超过0x8000时表示负数。负数在正常距离测量中一般不会出现,但有些异常状态或者特定固件下会返回特殊值,提前做转换可以避免后面计算错乱。比例因子字段如果大于0,距离单位通常是毫米;如果是负数,说明测量值需要除以2的某个幂次,具体要在SOPAS里对照配置验证。

4.3 从距离到坐标

拿到距离数组后,还需结合角度信息才能变成二维坐标。LMS111默认扫描角270°,如果角分辨率是0.5°,则点数541个(含首尾),每个测量点对应一个角度:

angle = start_angle + index * angular_resolution

起始角从哪里来?最准确的办法是在SOPAS的Measurement Setting里查看“Start Angle”配置。程序里推荐把起始角和分辨率写进配置文件,因为现场改过扫描范围后,代码不用重新编译。

极坐标转直角坐标,以传感器安装点为原点:

import math start_angle_deg = -45.0 # 示例,以SOPAS配置为准 angular_res_deg = 0.5 coordinates = [] for idx, dist_mm in enumerate(ranges): angle_deg = start_angle_deg + idx * angular_res_deg angle_rad = math.radians(angle_deg) dist_m = dist_mm / 1000.0 x = dist_m * math.cos(angle_rad) y = dist_m * math.sin(angle_rad) coordinates.append((x, y)) print("坐标点数:", len(coordinates)) print("第一个点:", coordinates[0])

如果只是做区域入侵判定,其实不需要转坐标。更快的做法是直接按“角度区间 + 距离阈值”判定,比如“角度在-30°到30°范围内,且距离小于3 m,就认为有障碍物”。坐标转换主要用于导航地图构建和轮廓显示,不要一上来就做重活。

5. 现场踩过的三个坑:IP冲突、数据全零、多机串扰

5.1 IP冲突和组网

外发项目里,传感器、PLC、工控机往往在同一个网段,如果两台设备用了同一个IP,表现就是数据时通时断、SOPAS搜到的设备信息错乱。这个问题的根源往往是调试时临时指定了IP,却没有记录。

我的做法是:上线前用SOPAS把所有传感器的IP重新规划一遍,统一写进一张设备清单表,并设置成固定IP,不使用DHCP。LMS111是工业设备,网络环境里如果存在DHCP服务器,可能有意外的地址变化,固定IP能少很多麻烦。另外,如果工控机装了多块网卡,要确认程序里连接的IP和网线实际插入的网卡一致,否则大概率连接超时。

5.2 数据全零和跳变的排查思路

程序能连上、能解析出点数,但所有距离值都是0,这种问题我在现场遇到过。不要急着改代码先去查传感器状态:

  1. 打开SOPAS,查看扫描输出和传感器状态标志。
  2. 检查Display/Contamination窗口脏污值。传感器窗口沾灰、被遮挡,测量数据会变成无效值或全零。
  3. 检查传感器安装位置是否正对强反射物体,或者安装在阳光直射的位置。LMS111的红外激光受强环境光影响,耀光严重的场合数据会跳动明显。
  4. 确认被测物体表面反射率。黑色哑光物体反射率低,同样距离下回波弱,可能出现距离值偏短或波动。

数据跳变的处理手段可以在程序里加滤波。我常用中值滤波配合滑动平均:先在一个窗口内排序取中值,滤掉单点尖刺,再对连续几帧做平均,平滑动态噪声。但要注意,滤波会引入滞后,做高实时性防撞时别把滞后做得太大。

5.3 多机串扰

当现场有多台LMS111并排安装、扫描平面重叠时,一台传感器可能接收到另一台的激光回波,表现为距离值突然变成某个固定值或者出现大量随机点。这个问题的排查很费时间,因为不是每次都复现。

我的建议是:优先从安装层面解决,调整设备角度,让扫描平面尽量错开,或者在两台设备之间加物理遮光板。软件层面,可以通过错开扫描频率或使用外部触发信号让设备轮流扫描。LMS111支持通过命令配置测量周期,用外部触发同步多台设备时,要保证触发相位错开,避免同时扫描。

另外,程序里可以发送sMN LMCsetmeascycle来调整测量周期,这种改动会直接影响数据输出频率,改完务必在SOPAS里验证。多机同步是一个比较大的话题,这里先把坑点出来,真遇到时不会手足无措。

我个人在实际操作中的体会是,LMS111这台传感器虽然老,但特别稳,协议也不算复杂,第一次接触时花半天把SOPAS和COL-A命令跑通,后面写任何上位机程序都会快很多。最后再分享一个小技巧:正式写解析程序前,先用SOPAS确认传感器的角分辨率和起始角,把这两个值写进配置项,然后拿一帧真实数据对比解析结果,确认点数对得上,再往下做功能,否则后面排查起来会非常痛苦。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询