基于S7-300与WinCC的三货物自动售货控制系统设计 1. 控制系统的整体架构设计与方案选型1.1 为什么选S7-300WinCC这个组合做三货物自动售货控制系统设计摆在面前的第一道题不是怎么编程序而是选什么平台。我之前见过不少学生和刚入行的工程师一上来就纠结“要不要换S7-1200”“是不是用精简面板组态更方便”。我的观点很直接如果这个项目是课程设计、毕业设计或者面向教学演示、存量产线改造S7-300搭配WinCC依然是目前最稳妥的组合没有之一。S7-300虽然是西门子的经典中型PLC已经不算最新产品线但它的存量市场非常庞大很多工厂、实训室、老旧产线里还在稳定运行。你打开西门子官方手册和技术论坛S7-300的案例、库文件、FAQs几乎要多少有多少遇到问题时随便一搜就能找到对应的解决方案。这一点对初学者极其友好因为你踩的坑大概率别人早就踩过了。WinCC作为上位机组态软件和S7-300之间的通讯是“原配”关系走的是西门子自家的S7协议不需要额外买驱动不需要写一堆底层通讯代码。你只需要在WinCC里添加SIMATIC S7 Protocol Suite驱动配置好PLC的IP地址或者DP地址变量就能直接对上。三货物版的控制系统比单货物版多出了货物选择、多路输出、找零状态管理这些逻辑但又比全尺寸售货机动辄十几个货道、带制冷和触摸屏简单得多正好卡在“能学到完整设计流程”和“不被复杂度淹没”的平衡点上。1.2 三货物版控制系统的功能边界很多初学者拿到这个题目之后第一反应是“三个货物那不是很简单嘛三个输出口各接一个电机搞定收工”。实际做下来你会发现真正的难点根本不在出货而在“钱”的处理上。自动售货控制系统本质上是一个有限状态机待机、投币检测、金额累计、货物选择、出货执行、找零结算、故障报警。三货物版本对每一个状态都要有完整的逻辑闭环只是在货物选择部分从“多选一”简化成了“三选一”在I/O规模和变量数量上做了减法。以我这次做的设计为例系统的功能边界如下支持两种硬币投币识别例如5角和一元的硬币能够实时累加金额并显示在面板上三个货道各自独立选择对应货物后只有金额充足才允许出货出货动作由PLC输出控制直流电机转动将货物推落到取货口出货完成后自动扣减金额余额累计继续购买按下找零按钮后系统按最少硬币数原则退币光眼检测卡货等异常状态并声光报警。这套功能逻辑如果拆开看每一个都不难但放在一起就需要你认真规划数据结构和程序结构。整个过程做下来基本上能把PLC编程中的位逻辑、定时器、计数器、比较指令、数据块操作全都过一遍。1.3 设计方案的总体流程系统启动后先复位所有输出进入待机状态。当投币检测传感器检测到有硬币投入PLC读取当前硬币面值并累加到余额变量里WinCC通过变量连接同步显示余额变化。用户按下某个货物选择按钮或者在WinCC画面上点击货物图标PLC先比较“余额是否大于等于货物单价”条件满足则启动对应货道电机。电机运转一定时间后停止货物掉落经过取货口光眼确认后系统自动扣款并更新库存数量。如果用户不再继续购买按下找零按钮PLC按照预设的硬币面额组合计算退币数量驱动退币电磁执行机构。整个过程通过HMI和指示灯实时反馈状态。在实际设计时我建议把PLC程序和WinCC组态并行开发不要等PLC写完再去做上位机那样会很浪费时间。WinCC的变量表和PLC的符号表在功能上是一一对应的你先在PLC里把符号表建好后面WinCC的变量全部从这里直接映射效率和准确度都能提升不少。2. 硬件配置与I/O分配详解2.1 S7-300核心模块选型S7-300是一个模块化系统不像S7-1200那样CPU自带集成IOS7-300的每个模块都需要单独选型。对于三货物版自动售货机我不建议选太大规模的配置够用就好留出10%到20%的余量就可以。我这次选用的模块配置如下模块型号推荐说明电源模块PS 307 5A给CPU和IO模块供电前端接220V交流CPU模块CPU 314C-2PN/DP自带DI 24点/DO 16点集成PN口和DP口通讯方便数字量输入模块SM 321 DI16扩展投币、选择按钮、光眼等输入点数字量输出模块SM 322 DO16扩展货道电机、退币电磁铁、报警灯输出点有人会问CPU 314C的集成IO已经不少了为什么还要扩展SM321和SM322原因很简单集成IO虽然够用但如果你把所有信号都压在CPU自带端子上一旦某个点烧掉修起来特别麻烦。而且扩展模块可以让你把“控制类信号”和“执行类信号”分开布局接线整齐排查问题的时候也更容易分区域处理。CPU 314C-2PN/DP这个型号我一定要多说一句它自带两个通讯口一个PROFINET口一个DP口。做WinCC通讯时直接用PN口走以太网把PLC和装WinCC的电脑接到同一个交换机或者直连网线就能通讯非常方便。如果以后想挂远程IO站或者变频器DP口也还有富余。2.2 I/O点位的规划原则三货物版系统的I/O分配看起来简单但规划得好不好直接影响后续编程和接线。我见过太多人上来就乱接最后程序写完发现点位乱了又回去改接线费时费力。正确的做法是先列I/O清单再动手接线。我这次的I/O分配如下输入信号DII0.0五角硬币投币检测I0.1一元硬币投币检测I0.2货道1出货光眼确认I0.3货道2出货光眼确认I0.4货道3出货光眼确认I0.5货物选择按钮1I0.6货物选择按钮2I0.7货物选择按钮3I1.0找零按钮I1.1卡货故障复位按钮输出信号DOQ0.0货道1电机正转Q0.1货道2电机正转Q0.2货道3电机正转Q0.3退币电磁铁Q0.4运行指示灯绿色Q0.5故障报警灯红色Q0.6蜂鸣器这里有一个容易忽略的细节货道电机的限位问题。直流减速电机如果通电时间太长会把货物推过头甚至卡死。我实际设置的是通电2秒后自动停止并结合光眼信号判断货物是否掉落。如果2秒后光眼还没检测到货物判定为卡货立即停止电机并报警。2.3 投币识别与找零机构的硬件处理投币识别在最简单的三货物系统里可以不做光电识别的复杂算法直接用机械币道配合传感器即可。比如5角和一元硬币在币道里的直径不同可以分别在币道不同位置安装光电传感器硬币滚过哪个传感器就累计对应面值。这种方式虽然不能做到“全币种识别”但对于课程设计和教学演示来说完全足够。配套的找零机构可以用“退币电磁铁多币道”的方案。当PLC计算需要退几枚5角硬币时会输出脉冲信号驱动电磁铁打开对应币道的挡板硬币掉落到退币口。这里要特别注意电磁铁不能长时间通电否则线圈会发热烧毁一般用0.5秒的短脉冲即可。3. PLC程序结构梯形图核心逻辑逐段拆解3.1 数据结构与变量规划S7-300编程我建议用Step 7软件它支持LAD梯形图、FBD功能块图、STL语句表三种语言。三货物版程序规模不算大用LAD完全能表达清楚也比STL更直观方便后面答辩或者交接的时候给人讲。程序结构上用“主程序OB1 子功能FC”的方式组织这样每个功能独立调试时可以单独测试某个模块不用一跑就是整个程序。我规划的功能块如下FC1投币处理和余额计算FC2货物选择和出货控制FC3找零计算和退币执行FC4库存管理与故障报警全局变量使用数据块DB来保存比如DB1里放余额、货物单价、库存数量、出货状态等。用DB而不是M区存放业务数据好处是数据组织清晰、断电保持可控而且WinCC直接读DB变量特别方便地址一目了然。DB1的内容大致如下DB1.DBD0当前余额实数单位元DB1.DBD4货道1单价DB1.DBD8货道2单价DB1.DBD12货道3单价DB1.DBW20货道1库存DB1.DBW22货道2库存DB1.DBW24货道3库存DB1.DBX30.0出货中标志位3.2 投币检测与金额累加投币检测的梯形图逻辑并不复杂核心是边沿检测。当I0.0或I0.1从0变1说明有一枚硬币投入这时候把对应的面值加到余额上。注意这里一定要用上升沿不能用电平。如果用电平触发硬币卡在传感器前后持续产生信号金额会被反复累加从1块变10块。以五角硬币为例FC1局部A I0.0 // 读取五角投币传感器 FP M0.0 // 上升沿检测 JCN M001 // 没检测到上升沿就跳转 L DB1.DBD0 // 加载当前余额 L 0.5 // 五角面值 R T DB1.DBD0 // 存回余额 M001: NOP 0如果你习惯用LAD拖拽逻辑是一样的I0.0串一个P上升沿后面接ADD指令把0.5加到DBD0里。为什么我比较推荐DBD0用实数因为单价可能是2.5元、3元这种带小数的值用整数就还得乘以10或者100来换算多一层逻辑还容易算错。直接实数运算画面显示和比较指令都省事。3.3 货物选择与出货执行三货物版的出货逻辑核心是“比较 互锁”。用户按下选择按钮PLC判断这个货道是否还有库存、余额是否充足条件全部满足才启动电机。如果余额不足可以选择闪烁提示或者通过WinCC弹窗提示用户继续投币。我写这段逻辑时特别加了一个“出货中状态位”做防重入保护。目的很简单在电机运转期间即使再按其他按钮程序也不会重复执行出货动作。这个保护在真实设备上极其重要因为按钮被多次触发或者WinCC脚本被重复点击都会导致设备同时启动两个电机故障风险极高。下面以货道1的逻辑为例说明FC2节选启动条件选择按钮I0.5按下并产生上升沿DB1.DBW20库存1 0DB1.DBD0余额 DB1.DBD4单价1出货中标志位DB1.DBX30.0 0满足条件后置位出货中标志位置位Q0.0货道1电机输出同时调用TON定时器设定2秒2秒到后复位Q0.0读取取货口光眼确认信号I0.2如果为1说明货物掉了做扣减余额和库存的处理如果为0判定卡货置位报警标志并触发Q0.5报警灯和Q0.6蜂鸣器这里有一个我踩过好几次的坑光眼确认信号不能放在定时器结束后才检测应该在定时器运行期间持续检测否则会出现“货物已经掉落但光眼信号只是一瞬间的短脉冲等定时器结束时已经错过了”这种问题。正确的做法是在定时器到点之前的整个过程中只要光眼有一次为1就记录到M区的一个“出货成功”标志里定时器结束后再检查这个标志进行扣款。3.4 找零计算与退币执行找零计算是很多人容易写乱的地方核心是贪心算法的PLC实现先用最大面额的硬币去凑找零金额不够再用小面额补。三货物版一般只需要退5角硬币所以逻辑简化成“需要退的枚数 找零金额 / 0.5”。找零按钮按下后PLC先把余额里的整数元部分登记为“应退金额”然后拿应退金额除以0.5得到需要退的5角硬币枚数存放在DB里。退币执行时不能一次性把所有硬币同时弹出这样会卡币。正确做法是用一个定时器循环每弹出一枚硬币电磁铁通电0.5秒然后断电等一秒钟再弹下一枚。这个节奏可以通过比较指令和计数器实现也可以用循环指针来实现推荐用计数器方式逻辑更清晰。退币完成后一定记得把余额清零并复位“找零中”状态位。别小看这一步如果不复位下一次投币时找零机构的输出还会保持在通电状态。3.5 库存管理和故障报警三货物版本的库存管理属于锦上添花但对于卖点和答辩加分非常有用。库存数量在初始化时预设比如每个货道放10瓶饮料每次出货成功扣1当库存为0时该货道的选择按钮失效甚至在WinCC画面上直接显示“售罄”状态。故障报警这里我做了三级处理不算复杂但很实用轻微提示WinCC画面文字提示“余额不足”不产生声光报警一般故障卡货红灯常亮、蜂鸣器间断鸣响需要操作人员到现场处理并按下复位按钮严重故障投币口卡币程序立刻封锁所有投币和操作逻辑持续报警等待维护。4. WinCC上位机组态与脚本实现4.1 WinCC变量建立与通讯连接WinCC组态的第一步不是画画而是建立变量连接。在变量管理里添加“SIMATIC S7 Protocol Suite”通道然后在通道下新建连接填写PLC的IP地址如果走PN口通讯就是CPU的IP机架号和槽号按照S7-300的标准配置填通常机架0槽2。我在这个项目里用到的WinCC变量主要有这几类WinCC变量对应PLC地址数据类型用途BalanceDB1.DBD0浮点数当前余额Price1DB1.DBD4浮点数货道1单价Stock1DB1.DBW20无符号16位货道1库存Vending_StateM10.0二进制出货中状态Fault_FlagM10.1二进制故障标志WinCC读S7-300的DB块变量时地址格式要写对。实数对应DBD16位整数对应DBW位对应DBX。我在实际项目里见过不少人把实数地址写成DBW导致画面显示乱码或者一直闪烁跳变其实是变量类型和地址没对应上。通讯连接建好后可以先在WinCC的变量模拟器里测试变量变化确认链路没问题再开始做画面。4.2 画面设计与基本交互功能WinCC画面设计这块核心原则是“信息不过载”。三货物版要显示的信息其实不多当前余额、三个货物的图片和价格、库存状态、出货按钮、找零按钮、故障状态指示。把这些元素排好就行不要堆太多的装饰和特效运行稳定性优先。我做的画面布局是上下两栏顶部一行显示余额、运行状态、故障状态中部三个货物卡片横排每个卡片上有货物名称、价格、库存数量、购买按钮底部一个大的“找零”按钮和“故障复位”按钮。货物的图片可以用WinCC的图形编辑器直接画矩形加文字也可以导入PNG图片。我建议直接画简洁图块加载速度快也不容易出现图片路径丢失的问题。交互按钮的用途不同实现方式也不同。购买按钮如果直接在按钮属性里做“按”和“释放”动作很容易造成误触发。我推荐用C脚本实现购买逻辑按钮事件选择“单击”触发这样按下抬起才算一次有效点击。4.3 C脚本实现二次确认功能WinCC的C脚本可以放在按钮的事件里运行。之前有个朋友问过我“我在WinCC画面里点出货按钮不小心多点了两下结果直接出了两瓶饮料怎么防”这就是典型的缺少二次确认的案例对于实际的售货机来说虽然按钮误触不算大问题但在工业控制里点击“启动”就是切换一台几百千瓦的电机必须有二次确认。在自动售货系统里我给购买按钮加了一个二次确认弹窗脚本效果是用户点击购买按钮后不是直接启动而是先弹出一个对话框显示“确认购买XX商品”点击“是”才执行置位和复位动作。这样一来既能防止误触也能给用户一个确认的机会。C脚本核心逻辑如下#include apdefap.h void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) { int nMsgRet; nMsgRet MessageBox(NULL, 确认购买商品1将扣除相应金额。, 购买确认, MB_YESNO | MB_ICONQUESTION); if (nMsgRet IDYES) { // 触发PLC置位启动出货 SetTagBit(Start_Vend1, 1); Sleep(50); SetTagBit(Start_Vend1, 0); } }这里最关键的技巧是置位之后延时几十毫秒再复位做一个短脉冲给PLC。我之前见过有人写脚本直接对整个变量做“赋值1然后又赋值0”结果PLC那边根本接收不到脉冲因为两行代码执行得太快通讯周期还没跟上。加一个Sleep就能让通讯系统把状态切换完整传过去。4.4 数据归档和报表这部分在基础三货物版里不一定要求但如果做毕业设计或者实际商业化部署建议把每天的出货记录、金额收入、故障事件都归档到WinCC里。WinCC自带变量归档功能在变量管理里把需要记录的变量选中勾选“归档”系统就会按设定周期把数据写入归档数据库。归档最大的用处是做故障追溯。调试期间我遇到过一台售货机半夜自己报警看PLC程序看不出问题后来通过WinCC归档查历史趋势发现是凌晨的电压波动导致投币传感器误触发了一次。这种问题如果没有历史数据根本无从排查。5. 联调测试方法与常见问题排查5.1 仿真调试与实物调试的衔接三货物版控制系统调试阶段我非常推荐先做离线仿真再做实物联动。仿真阶段不需要把整套硬件都接好用Step 7自带的PLCSIM就能模拟PLC运行。但要注意PLCSIM和WinCC之间通过变量连接时需要在WinCC里把连接属性设置为“PLCSIM模拟通讯”否则WinCC连不到仿真PLC。调试顺序建议如下先用PLCSIM单步调试FC1投币逻辑用变量表强制输入I0.0、I0.1观察DB1.DBD0余额是否正确累加再调试FC2出货逻辑强制置位I0.5选择按钮观察Q0.0是否按时序动作、定时器是否准确接着调试找零逻辑强制把余额改成3.5元按下找零按钮观察退币计数器是否按0.5元递减以上逻辑验证通过后接入WinCC首先做变量通讯测试确认画面数值随PLC变量变化最后接实物按照I/O表逐点核对每根线的状态再做完整的投币-购买-出货-找零联动测试。5.2 常见问题速查表实际联调中我遇到或者见过的问题主要集中在通讯和时序两方面整理成表方便大家对照排查故障现象可能原因排查方法WinCC画面数值不刷新PG/PC接口设置错误变量地址类型不匹配在WinCC里用变量模拟器测试确认变量能读写检查TCP/IP通讯是否连通WinCC连不上PLC未添加S7 Protocol Suite驱动IP不在同一网段先Ping通PLC地址再检查连接配置的机架号和槽号投币金额重复累加用了电平触发而不是上升沿处理检查FP上升沿指令是否有效确保每投一枚只触发一次点击购买按钮无反应C脚本置位时间太短、PLC通讯周期未捕获增加Sleep延时建议50毫秒以上检查是否选中“单击”事件货物已掉出但系统未扣款光眼信号在定时器结束时已消失增加“出货成功”锁存标志在定时器运行期间检测到光眼就置位定时结束再判断退币数量不对找零算法顺序错误先除以大面额再取余数依次递减模拟各金额值验证报警频繁误报光眼被灰尘遮挡或安装角度偏调整光眼灵敏度增加滤波延时如持续0.3秒才确认卡货5.3 调试中的实战心得快做完这个项目的时候我踩了一个特别典型的坑写在这里给大家提个醒S7-300的定时器资源有限如果你用的是老型号CPU比如CPU 314定时器数量是有限制的。三货物版如果每个货道用一个TON加上找零节奏控制和光眼延时滤波整体定时器数量很容易超过软定时器可分配上限。解决方法是把定时器做成“复用”模式即用一个TON做时间基准然后用比较指令去分出多个时间段或者用FB块在里面定义多实例定时器。另外一个心得是关于WinCC画面刷新率的。三货物版的画面刷新率没有必要设太高200毫秒或者500毫秒完全够用刷新率太高反而会增加CPU负载特别是你同时开了变量归档的时候运行久了WinCC会变得越来越卡。我之前试过100毫秒刷新运行一晚上后WinCC的内存占用飙升到2个G起步改成500毫秒后稳定很多。还有一个被很多人忽视的细节WinCC和PLC的时钟同步。如果WinCC电脑和PLC的时间不一致归档数据和报警记录的时间戳就会对不上后面做故障复盘的时候会很痛苦。建议在WinCC里启用时间同步功能以PLC时间为准每次系统启动时自动校准。6. 项目扩展思路与商业化方向这个三货物版做到这里主体功能已经完整了但如果你还有余力我建议在下面几个方向做扩展第一是支付方式升级。现在的三货物版只支持硬币商业上肯定不够。可以考虑在系统中预留4G通讯模块接口通过HTTP接口调用云端支付API把“投币支付”扩展成“扫码支付”。PLC端只需要新增几个命令字变量和状态位WinCC端增加一个二维码显示区域复杂逻辑放在网关里而不是放在PLC里这样改动最小。第二是远程监控和数据管理。S7-300走PROFINET以后可以配合WinCC的Web发布功能做一个远程监控页面通过手机浏览器就能实时看到每个货道的库存和故障状态。运维人员不需要亲自跑到机器前面就能解决70%以上的排查工作这在散布式自动售货网点部署中特别实用。第三是多机联网管理。如果你有不止一台售货机可以做成“一台PLC控制一台售货机 一台WinCC服务器统一管理多台”的结构。WinCC支持多连接每台PLC的变量可以在同一个画面里分区域显示这样所有的在线状态、营业数据、故障信息都在一个平台里汇总。我记得有一次给一个实训基地做整套售货机教学系统用的就是S7-300三货物版的架构扩展出来的五机联网方案。每个学生小组负责维护其中一台机器的程序逻辑和画面所有机器通过交换机连到教师机的WinCC监控站。学生既能看到自己那一台的实时数据也能对比其他组的程序写法和画面布局教学效果比单机演示好得多。如果你是想把这个项目直接用在毕业设计或者课程作业里还可以考虑加上“电机转速控制”这一层货道电机如果使用变频器或者模拟量模块输出可以在投放不同重量货物时调节推送力度避免冲力太大把易碎商品砸坏。虽然三货物版用不到但答辩时提出来说明你考虑了实际工况印象分会好很多。