
简介面向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软件自带设备搜索功能能自动扫出网段内所有传感器。第一次调试我建议这么走电脑网线直连LMS111的以太网口其他网络暂时断开。把电脑有线网卡配置成固定IP网段和传感器一致。比如传感器常用地址是192.168.0.1那电脑就设192.168.0.100、掩码255.255.255.0。关掉Windows防火墙或者至少允许SOPAS和后续的Python进程通过专用网络访问。打开SOPAS选“Search/Scan”扫描设备等它列出传感器。双击设备进入参数页面确认当前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), timeout5) sock.sendall(bsRN 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), timeout5) sock.sendall(bsRN 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, errorsignore).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这种问题我在现场遇到过。不要急着改代码先去查传感器状态打开SOPAS查看扫描输出和传感器状态标志。检查Display/Contamination窗口脏污值。传感器窗口沾灰、被遮挡测量数据会变成无效值或全零。检查传感器安装位置是否正对强反射物体或者安装在阳光直射的位置。LMS111的红外激光受强环境光影响耀光严重的场合数据会跳动明显。确认被测物体表面反射率。黑色哑光物体反射率低同样距离下回波弱可能出现距离值偏短或波动。数据跳变的处理手段可以在程序里加滤波。我常用中值滤波配合滑动平均先在一个窗口内排序取中值滤掉单点尖刺再对连续几帧做平均平滑动态噪声。但要注意滤波会引入滞后做高实时性防撞时别把滞后做得太大。5.3 多机串扰当现场有多台LMS111并排安装、扫描平面重叠时一台传感器可能接收到另一台的激光回波表现为距离值突然变成某个固定值或者出现大量随机点。这个问题的排查很费时间因为不是每次都复现。我的建议是优先从安装层面解决调整设备角度让扫描平面尽量错开或者在两台设备之间加物理遮光板。软件层面可以通过错开扫描频率或使用外部触发信号让设备轮流扫描。LMS111支持通过命令配置测量周期用外部触发同步多台设备时要保证触发相位错开避免同时扫描。另外程序里可以发送sMN LMCsetmeascycle来调整测量周期这种改动会直接影响数据输出频率改完务必在SOPAS里验证。多机同步是一个比较大的话题这里先把坑点出来真遇到时不会手足无措。我个人在实际操作中的体会是LMS111这台传感器虽然老但特别稳协议也不算复杂第一次接触时花半天把SOPAS和COL-A命令跑通后面写任何上位机程序都会快很多。最后再分享一个小技巧正式写解析程序前先用SOPAS确认传感器的角分辨率和起始角把这两个值写进配置项然后拿一帧真实数据对比解析结果确认点数对得上再往下做功能否则后面排查起来会非常痛苦。本文还有配套的精品资源点击获取