三层电梯模型完整实战:状态机控制与传感器布局全解析

发布时间:2026/10/18 7:42:25

三层电梯模型完整实战:状态机控制与传感器布局全解析 做一台“3层电梯”的完整模型核心难点其实不在机械结构而是藏在控制逻辑里。很多教程只让电机上下跑真正完整资料应该包含楼层呼叫、调度优先级、开关门时序、边界保护这一整套流程。这篇文章从机械选型、传感器布局、状态机设计到调试链路全部展开适合正在折腾嵌入式、自动化或者想把状态机思想落到实物的同学参考。1. 三层电梯模型到底在做什么需求拆解与方案选型1.1 从真实电梯反推模型的六个核心功能我很早以前也做过一台“三楼电梯”当时天真地以为只要让马达正反转再加上几个限位开关就能交差。等到实际跑起来发现想法错了电梯的价值在于正确响应所有人按下的按钮并且按照一套规则有条不紊地运行而不是单纯把轿厢移来移去。把真实电梯的功能逐条列出来对应到模型上至少要有六项基本功楼层呼叫每层都有上行/下行按钮轿厢内部有1至3层目标按钮。轿厢定位必须随时知道电梯当前停在哪个楼层、有没有到达目标层。开关门动作到层后开门、延时、关门关门到位后才能继续运行。运行方向指示灯或者数码管显示电梯正在上行还是下行。超行程保护防止程序逻辑跑飞后轿厢直接冲出导轨。调度规则同一时间出现多个请求时电梯要决定先响应谁、中途顺不顺路。如果你的项目资料里没有覆盖第一项到第五项的完整接线图和程序框架那就不能说“有完整资料”。我见过太多只给一段主循环代码、不给机械装配图也不给传感器安装位置说明的案例这种资料交给任何人二次复现时都容易踩坑。1.2 主控、驱动与传感器选型最稳妥的一套配置先聊核心器件的选型思路。只是做一个三层电梯模型不需要工业PLC级别也不需要跑Linux一小块嵌入式主控就能解决。我在对比后认为最稳妥的组合是STM32系列的入门款或Arduino类开发板作为主控一路PWM输出控制直流减速电机配一个电机驱动板楼层检测用槽型光电开关门机用舵机模拟。原因是这些器件单价低、资料多、接线直观任何一个初学者拿到手都能按图索骥。这里给出我实际对比过的几种选型关系方便你直接做决策功能模块可用方案优点缺点最终建议主控8位单片机、STM32、Arduino8位简单但外设弱STM32定时器丰富8位需要自己搭最小系统门槛略高STM32或Arduino升降驱动直流减速电机钢丝绳结构简单价格低断电后可能溜车定位需要传感器辅助蜗轮蜗杆减速电机更稳升降驱动备选步进电机丝杆定位可控反向零背隙成本升高控制逻辑变复杂预算充足可升级楼层传感器槽型光电开关、干簧管磁铁光电抗干扰好安装简单干簧管容易被电机磁干扰槽型光电开关门机舵机、电动推杆舵机角度可控易编程推杆行程和限位麻烦舵机模拟开关门为什么我不建议一上来就上闭环伺服或者视觉识别因为三层电梯模型的技术目标是把“响应-运动-停靠”这套有限状态机逻辑吃透对重复定位精度要求并不高。负载很轻、行程也就几十厘米完全可以用限位开关或光电定位实现“到达楼层后停车”的效果。先把逻辑跑通再去追求精度才是这个项目的正确打开方式。1.3 为什么用“位置开关点动控制”而不是闭环伺服这是很多初学者最容易纠结的地方。问“电梯靠什么知道自己在几楼”是很正常的疑问但答案不一定要是编码器。真实电梯因为速度高、高楼层的平层精度要求到毫米级才需要旋转编码器配合变频器做闭环控制。对于模型电梯楼层之间距离短、速度慢用槽型光电或者限位开关就足够定位了。当轿厢上的遮光片经过传感器槽口时主控捕获一次电平跳变再结合当前运行方向就能精确判断“刚刚经过了2层”。也就是说这个系统不需要实时修正误差只需要知道“当前在哪个楼层”和“是否经过了下一层”就能完成所有停靠判断。这大大降低了对电机和驱动的要求也让控制代码的边界清晰得多。2. 机械结构、传感器布局与接线细节2.1 升降机构的五金设计从钢丝绳到丝杆的取舍不少版本的“三楼层电梯模型”都采用铝型材或者木板搭框架用光轴加直线轴承作为轿厢导轨。这种结构做起来很快而且轿厢上下运行时的晃动也很小。我更建议在装配时给上下两端加橡胶缓冲垫防止调试的初期直接冲顶。升降机构如果要用钢丝绳和直流减速电机一定要选带蜗轮蜗杆的减速电机。原因很简单蜗轮蜗杆具有自锁特性电机断电后即使轿厢有一定重量也不会滑动这就天然实现了“机械刹车”。如果只用普通减速电机加牵引绳断电后轿厢多半会直接滑到底层轻则损坏传感器重则让模型散架。如果你愿意提高一点成本同步带加步进电机是更省心的组合。步进电机每发一个脉冲就走一步在程序里可以通过脉冲数知道当前位置电梯也就有了初步的开环定位能力。不过要注意失步问题依然存在极限保护开关依然不能省。至于丝杆方案我在第二次重做这台模型的时候用过一次。丝杆带来的好处是传动平稳、定位安静缺点是装配时对丝杆和导轨的平行度要求比较高如果两边不平行运行时间一长直线轴承会卡死。新手第一次上手我建议先用同步带方案。2.2 楼层定位传感器的安装位置与抗干扰处理三层的传感器安装布局一般是这样在框架的1层、2层、3层停靠位置各安装一个槽型光电开关轿厢侧边装一个长度足够的遮光片。当遮光片进入槽口输出电平拉低或拉高主控据此判断电梯到了那一层。安装时有几个实际细节普通资料很少明确讲清楚传感器安装高度要和轿厢平层后的门中心对齐误差尽量控制在2毫米以内。遮光片宽度要大于传感器槽口的有效检测宽度否则高速运动时会因为只扫过边缘导致信号抖动。遮光片不要只固定一端另一端最好有导向限位防止轿厢长期往复运行后遮光片晃到传感器检测区之外。接线距离超过20厘米时建议用带屏蔽的导线屏蔽层在主控端单点接地能明显减少电机启动瞬间带来的干扰。2.3 门机模拟与极限保护开关的接线思路模型电梯的门不需要做成自动平移门那难度太高了。主流的做法是轿厢外框留出一个门洞舵机的臂固定一块模拟门板舵机旋转一定角度门板跟着开合。这样做的好处是程序里只需要控制PWM占空比就能让门停在开或关的状态。为了检测开门和关门是否到位我建议在门洞上下轨位置安装微动开关。开关被门板压住时主控认为门已经到位此时才能允许电梯继续运动。这是安全逻辑的关键和真实电梯的“门锁闭合才可运行”是一个道理。极限保护开关则装在导轨的最顶端和最底端串联在电机的使能回路里或者直接接到主控的外部中断引脚。一旦电梯冲过了顶层或底层的正常停止位置开关会立刻切断电机动力并让主控进入故障状态。这个保护逻辑必须独立于软件调度不能依靠“反正程序不会跑飞”的假设。在接线阶段有一个非常容易忽略的坑电源的地线。电机启动瞬间电流可能达到几安培如果和主控共用一个电源电压跌落会让主控直接复位。我一般把电机驱动电源和主控逻辑电源分开只做单点共地连接。信号线不经过电机电缆也不和电机线扎在一起。3. 控制逻辑的核心电梯调度状态机怎么设计3.1 电梯运行的本质不是if堆叠而是一个有限状态机很多人第一次写电梯程序会尝试用一个大循环加一堆if判断覆盖所有可能性。但按钮事件的组合是无穷的1楼按了上行、2楼按了下行、轿厢内又按了3楼目标同时还发生了关门超时这些事件并发交织时if堆叠会导致代码越改越乱。电梯的本质是一个有限状态机它的全部行为可以收纳进有限个状态。我不妨列出设计模型时最核心的六个状态IDLE电梯静止等待新的任务。MOVING_UP / MOVING_DOWN电梯正在上升或下降。DOOR_OPENING正在开门等待舵机到达开门角度。DOOR_CLOSING正在关门等待舵机到达关门位置或超时保护。STOPPED_WAIT电梯已到楼层门已打开正在等待乘客上下车的时间。FAULT出现极限保护、堵转或门异常的故障状态。状态机的好处是任一时刻我们只关心当前状态遇到的事件对应做什么动作转移条件写清楚逻辑就非常清晰。你在最终整理资料时也应该把状态转移表画出来给读者这个比贴一堆注释乱飞的代码更让人看得懂。3.2 三层电梯的简化调度规则同向优先、远端反向模型电梯虽然只有三个楼层但调度规则不能省。简化版的调度规则有三条和我实际写过的代码完全一致电梯启动后先确定一个“目标方向”。如果当前楼层下方存在请求就下行如果上方存在请求就上行。运行过程中只响应与当前方向一致的请求。例如电梯正在上行就只有上行呼梯和轿厢内的目标楼层可以登记停靠下行呼梯会被记住但是要等电梯到达当前方向上最远的登记楼层之后再换向处理。高层楼的最远反向请求决定电梯是否换向。假如电梯从1层出发应答到3层的外呼同时在2层有人按了下行呼梯电梯从1层直上3层完成3层的任务后如果发现3层没有其他上行请求而2层有下行请求就换向下行顺路把3层到2层这段完成。有些家庭式的简化模型为了让动作看起来更“积极”会在上下行过程中遇到同一楼层无论方向都停靠。这样做最容易导致一个问题电梯明明正在下行1层有人按了上行呼叫电梯经过1层时停下开门结果关门后又要上行等于刚开门就折返看起来非常怪也违背真实电梯的用户预期。所以我还是坚持“同向优先”的规则。3.3 开门、关门、延时、防夹的时序安排程序里最忌讳用delay死等因为delay会阻塞整个状态机按钮和传感器的事件全部无法响应。开门延时、关门到位等待、超时判断都应该基于定时器或者系统运行的Tick计数。我在代码里通常用一个uint32_t的时间计数变量每隔1毫秒加一。每个需要延时的状态只记录“期望到的绝对时间”然后每次主循环检查当前时间是否大于期望值而不去调用阻塞等待函数。这样做的意义是门在打开和关闭的过程中如果用户按了新的呼救按钮状态机依然可以处理登记或者更新目标。门的时序我一般这样设定开门动作舵机从关门角度转到开门角度大约需要0.8秒但是不直接睡0.8秒而是等开门到位微动开关触发。开门停留保持3秒到5秒。如果在这段时间内有当前方向上的新请求登记则重新开始计时。关门动作舵机转回关门角度直到关门到位微动开关触发。关门超时如果关门动作持续超过3秒还没到位说明可能有物体卡住门此时停止关门重新开门并点亮故障指示。在模型上没有真实人流所谓“防夹”可以简化成这个重开门的逻辑。但保留这个时序对最终“完整资料”来说其实是把真实电梯的一个安全逻辑完整复现了价值远高于只做“开关门动画”。4. 程序实现细节状态机代码让模型真正跑起来4.1 数据结构按钮登记表与电梯状态联合管理代码的第一步是把现实世界的信号抽象成数据。按钮的物理抖动、传感器的瞬时误触都不应该直接驱动逻辑而是先读到一个输入层经过消抖后写进登记表。下面是我推荐的数据结构以C语言风格表达可以在任一主流嵌入式开发环境里直接套用typedef enum { IDLE, // 待机 MOVING_UP, // 上行中 MOVING_DOWN, // 下行中 DOOR_OPENING, // 正在开门 DOOR_OPEN, // 门已开等待 DOOR_CLOSING, // 正在关门 FAULT // 故障保护 } ElevatorState; typedef struct { uint8_t currentFloor; // 当前楼层1、2、3 ElevatorState state; // 当前状态 uint8_t direction; // 0停止、1上行、2下行 uint8_t carCall[4]; // 轿厢内目标登记下标1~3 uint8_t upHallCall[4]; // 各层上行呼梯登记下标1~3 uint8_t downHallCall[4]; // 各层下行呼梯登记下标1~3 uint32_t doorTimer; // 门状态计时用的绝对时间戳 uint32_t motionTimer; // 运行保护计时 } Elevator;登记表用数组的好处是只需要把对应下标位置写成1或者0就能表示“这个楼层有没有这种请求”。比如upHallCall[2]等于1表示2层有上行呼梯等待。取消呼叫就直接清零。楼层编号我建议从1开始不要从0开始。因为现实世界的1层就是1层程序里强行减1反而容易让自己困惑。4.2 主循环与状态转移代码骨架主循环的逻辑用一个伪代码概括就是收集事件 → 管理输入消抖 → 调用状态机处理函数 → 执行实际电机和门输出。核心的状态机部分可以这样组织void elevator_fsm_run(Elevator *elev) { switch (elev-state) { case IDLE: // 查找当前楼层上方/下方是否有登记请求 if (find_request_above(elev, elev-currentFloor)) { elev-direction DIR_UP; elev-state MOVING_UP; motor_up(); } else if (find_request_below(elev, elev-currentFloor)) { elev-direction DIR_DOWN; elev-state MOVING_DOWN; motor_down(); } break; case MOVING_UP: // 到达目标楼层先判断是不是当前应停楼层 if (elev-currentFloor find_next_stop_up(elev)) { motor_stop(); elev-direction DIR_NONE; elev-state DOOR_OPENING; door_open(); } break; case DOOR_OPENING: // 等待开门到位信号或超时 if (door_open_done()) { elev-doorTimer get_tick() 3000; // 开门停3秒 elev-state DOOR_OPEN; } break; case DOOR_OPEN: // 停留期间如果时间到开始关门 if (tick_exceed(elev-doorTimer)) { elev-state DOOR_CLOSING; door_close(); } break; case DOOR_CLOSING: if (door_close_done()) { elev-state IDLE; } else if (tick_exceed(elev-doorTimer 3000)) { // 关门超时重新开门 elev-state DOOR_OPENING; door_open(); } break; default: break; } }很多新手会犯一个错误在主循环里用delay等待电机运行到某层。这会导致舵机开关门时按钮完全没有反应。正确做法是在MOVING_UP状态下依赖楼层传感器中断或者快速扫描更新currentFloor每次主循环都检查currentFloor是否等于目标楼层。4.3 防冲顶、防溜车的边界处理边界处理是一个项目从“能跑”到“靠谱”的分水岭。在这个模型里我至少实现了三类边界保护第一类行程极限保护。顶层和底层的极限开关一旦触发使能脚立刻切断电机电源。这一步既可以用软件判断也可以用硬件直接串到电机驱动使能引脚上。我建议双管齐下因为如果只是软件判断万一主控跑飞位或者WiFi中断保护就失效了。第二类运行超时保护。电梯从一层移动到相邻楼层正常不会超过3秒。程序里开始移动时记录motionTimer如果过了5秒都没有触达楼层传感器认定电机堵转或者皮带打滑主动停车进入FAULT状态避免电机长时间堵转过热。第三类溜车检测。如果采用蜗轮蜗杆自锁电机这个现象不明显但如果你用了普通直流电机加同步带断电瞬间轿厢可能会反向滑动。我在程序中设置了一个后备逻辑当主控收到停止命令后如果在200毫秒内检测到传感器顺序与预期相反立即封住电机驱动并通过指示灯报警。这套逻辑其实模拟了真实电梯防溜车的核心思想非常推荐列入资料内容。5. 实物调试的完整排查链路从“电机不动”到“逻辑抽风”5.1 第一轮排查供电、接线和传感器电平我做得最频繁的错误项目早期故障有一半以上是供电问题。不要一上来就怀疑代码。排查链路第一步确认主控板上状态指示灯正常运行。第二步测试电机驱动板单独供电时能否正反转第三步看看所有光电开关在没有遮挡时输出高电平遮挡时输出低电平。这三步做完大概需要十分钟可以筛掉一大半焊接和接线问题。传感器电平的检查尤其容易被忽略。有些槽型光电开关输出的是PNP有的输出NPN如果买的模块上有信号指示灯遮挡时灯亮、不遮挡时灯灭就可以接进主控的GPIO。程序里要搞清楚逻辑电平遮挡到位到底是上升沿还是下降沿。我见过有人把“检测到楼层”和“离开楼层”写反导致每次经过楼层时电梯觉得自己到了上一层。在调试阶段强烈建议所有楼层传感器、按钮、到位开关都选择性的用串口打印函数输出日志例如在每次检测到遮挡时打印当前楼层编号。没有日志的嵌入式调试等于闭着眼睛走夜路。5.2 第二轮排查抖动、误触发与顺序错误如果供电和基础电平都没有问题下一步就是传感器信号质量。最经典的故障现象是电梯明明停在2层主控却认为自己在1层和3层之间反复横跳。原因通常是两个一是遮光片宽度不够经过传感器槽口时产生的电平变化时间太短没有达到程序的稳定读取周期二是传感器输出脚没有做好上拉或者滤波电机启动时电磁干扰直接叠加到了信号线上。针对抖动我建议在传感器信号和GND之间并联一个10到100纳法的小电容同时程序里做20毫秒连续稳定才确认状态。这个时间又短、又不会错过楼层停靠非常适合电梯这个低速应用。还有一个很容易掉进去的逻辑陷阱传感器顺序错误。电梯从1层到3层经过传感器应该是1层信号先触发2层信号再触发3层最后触发。如果机械装配时把2层和3层传感器接线弄反电梯会在到达2层时认为自己到了3层然后直接停车开门。排查这类故障时用串口记录“当前楼层变化序列”是最快的方法。5.3 第三轮排查调度策略导致的“幽灵等待”当机械和传感器都正常后剩下的问题九成是调度逻辑。我给出几个适合三层模型的组合测试用例你可以在串口日志里逐条验证测试场景预期行为常见错误行为停在1层轿厢内按3层电梯上行到3层开门等待然后返回1层或停在3层到2层就停然后原地换向在1层按上行呼梯系统时间推进电梯从1层开门等待3秒关门继续等待新任务开门后直接跑向最高层电梯在2层下行同时1层有上行呼梯电梯到达1层后开门关门后反向响应1层上行电梯在下行过程中先处理1层呼梯导致开门后立刻调头电梯在3层2层按下行呼梯且轿厢内按1层电梯先下到2层处理下行呼梯继续下到1层再关门待命电梯到2层后直接返回3层休息调试这类逻辑问题我的习惯是打印一行完整的“信息包”格式大致是当前状态、当前楼层、方向、目标楼层、各登记表的0/1值。逻辑正确性不需要靠眼睛盯着机械来回跑看日志序列就能判断出问题出在“没有响应”还是“响应顺序错误”。如果发现登记表里目标楼层已经被清除说明你在状态机某个分支里提前清了呼梯标记。修复原则是只有当电梯在该楼层且已经开门的一瞬间才清理对应登记位绝不能一经过就清除。一个小经验完整资料的可复现性才是项目真正的交付物做完整套三层电梯模型后我最大的体会是完整资料不等于散装代码加若干张照片而应该是机械尺寸图、接线表、传感器安装位置、状态转移表、程序源码、测试用例六样东西放在一起。别人拿到你的资料能在一周之内把你的模型复刻出来才说明这套配置和逻辑是站得住脚的。如果下一步还想继续扩展我会优先加两样东西一是给每层呼梯按钮加灯光反馈让电梯响应呼叫时灯亮、服务完成时灯灭二是增加一个外部呼不响应的测试模式用脚本模拟大量随机按钮事件自动化检验调度逻辑有没有死锁。这两项扩展比换更高级的主控或电机更有学习价值也更接近真实电梯系统的调试方式。最后再补充一条实际操作建议正式跑整机测试前先把电机速度调到最慢用手扶着轿厢运行一个完整往返确认三个传感器都按顺序触发再逐步提高速度。低速五分钟能发现的问题高速跑一个小时都未必排查得清楚。
延伸阅读

更多相关文章

2026/10/18 7:37:25

人工智能技术与应用:从入门路线到项目实战的完整学习指南

人工智能这个词现在已经不算什么新鲜概念了,但真正把它学懂、用起来,跟刷几篇科普文章、看看新闻报道是两回事。我接触AI学习也有几年时间了,中间走过不少弯路,也积累了一些自己觉得还算管用的方法。这篇文章就围绕“人工智能技术…

2026/10/18 7:37:25

上线漏测的根因与对策:从用例设计到复盘改进

项目上线当晚,群里消息炸了:用户反馈下单后库存没扣减,或者扣了两次。开发查了半小时,定位到“并发请求下同一个订单被重复提交,库存被减了两次”。然后所有人的目光转向测试:“这个场景你们没测吗&#xf…

2026/10/18 8:47:29

从召回、排序到重排:X平台For You推荐算法全链路解析

聊算法的人很难不注意到X平台那套“For You”信息流。它是目前社交平台里少有的把推荐系统全链路公开讨论过的案例,从候选生成、排序到重排都值得拆一拆。不管你是做推荐系统的新人,还是已经在信息流业务里摸爬滚打多年,把这条链路的每个环节…

2026/10/18 8:47:29

视频回放轴VideoLineForJS:监控回放时间轴组件实战指南

简介:VideoLineForJS 是一款针对海康威视视频回放场景的 JavaScript 时间轴组件,视频轴也称回放轴,常作为录像时间选择的交互核心,面向需要快速实现 Web 端历史视频回放界面的开发者。组件在页面中生成可点击/拖动的视频轴&#x…

2026/10/18 8:47:29

DotNET Reactor混淆实战:CI/CD集成与WPF/MAUI兼容性避坑指南

简介:本资源为DotNET Reactor最新破解版工具包,面向.NET开发者与逆向分析学习者,用于C#、VB.NET等托管代码的混淆、加密与反调试保护,解决商业软件作者对源码泄露与非法篡改的核心防护需求。压缩包共105个文件,含18个可…

2026/10/18 8:47:29

从模型实验到AI生产系统:企业大模型管理平台落地指南

自去年开始,我陆续帮几家企业搭过内部的大模型应用,从最初的“跑通一个Demo给领导看”,到后来真正上线承载业务流量,这中间的路远比想象中难走。今天想聊的就是这个分水岭:当你的团队还在用脚本调模型、拿Excel记Key、…

2026/10/18 8:42:28

ILSpy汉化版实战指南:无源码.NET程序集反编译与工程导出

简介:ILSpy中文汉化版是一份面向.NET开发者的反编译工具资源,专为需要阅读闭源程序集的开发场景设计。该工具能将.dll/.exe等编译后的程序集还原为可读的C#或VB.NET源代码,并提供逐类逐方法的可视化浏览、嵌入资源查看、元数据查询和全局搜索…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑