简介:围绕单片机控制的粉料自动包装机系统,这份文档提供一套较完整的毕业设计式技术方案,适合自动化、电气工程及机电一体化专业学生和初入包装设备行业的工程师参考。内容从国内外粉料包装控制系统的发展现状与现存问题切入,梳理总体方案、工艺流程与设计步骤,再逐项展开硬件选型与电路设计,涵盖封口、装料、称重、光电检测、放大电路、显示模块、主处理器选型及系统原理图;软件部分结合 Keil 讲解包装袋制作、数码管显示、MAX485 与单片机间数据传递的程序分析,并给出系统调试流程与 Protel-DXP 软件介绍。资源包共 1 个 doc 文档,约 410KB,按绪论、方案设计、硬件、软件、调试分章编排,目录清晰,便于按模块查阅。目前已有 93 人学习下载,可帮助读者理解粉料称重与包装控制的关键环节,为课程设计、毕业设计或同类系统开发提供参考。
1. 粉料包装机为什么绕不开单片机:从称重闭环说起
一袋标称 25kg 的腻子粉,灌到 25.3kg 才关阀,一天 2000 袋就是 600kg 的偏差,对账时这笔账很难看。粉料包装机要解决的核心,就是物料还在下落的过程中判断"什么时候停"。链条是称重传感器 → 放大与 AD 转换 → 单片机滤波与阈值比较 → 关阀,任何一环慢半拍,精度都守不住。
不少人第一反应是上 PLC,稳定、抗干扰、组态方便。但单工位、200~600 袋/小时的小型粉料包装机,用 PLC 是杀鸡用牛刀,一套带称重模块的 PLC 够买几十片 STC 或 STM32。单片机的价值在于把称重采集、两级给料逻辑、串口参数下发、数码管或 LCD 显示全塞进一颗十几块钱的芯片,控制板成本压得住,批量出货才有利润空间。
适合谁:做包装机械的中小厂、机电专业的课程设计与毕业设计、老式机械秤包装机的电子称重改造。粉料之间差别很大,面粉、淀粉流动性好还能靠时序凑合;腻子粉、水泥扬尘重、下料冲击大,必须走称重闭环。下面从选型一路讲到产线验证。
2. 粉料包装机控制系统的硬件选型与称重信号链
粉料包装机的控制板,说穿了就是围着称重这条信号链搭起来的。选型阶段省下的时间,往往是后面现场跑不稳的根源:传感器量程选小被冲击力打坏,选大了分辨率不够;MCU 主频太低,滤波窗口一拉长采样就跟不上给料节奏。
2.1 单片机选型:51、STC 与 STM32 在粉料包装机上的取舍
先说 51 内核。STC89C52RC 是最常见的入门选择,价格低、Keil C51 教程满地都是、寄存器简单。它的短板也明确:片上 RAM 只有 256 字节,定时器只有 T0/T1 两个,串口一套,堆栈空间小。做一个纯时序控制(定时器到点就翻继电器)的机型够用,但要跑加权滤波、串口协议解析、数码管动态扫描三个任务并行,代码一写厚就容易出现"某一帧数码管闪一下"这类时序打架。
STC15/STC8 系列是 51 指令集的升级版,1T 内核在同频下比 12T 的老 51 快约 12 倍,片上还带 EEPROM。粉料包装机的标定系数、目标重量、粗给料提前量这些参数,直接写进 EEPROM 就能掉电不丢,比外挂 24C02 省一颗料、省两条 I2C 线。称重闭环 + 串口参数下发这种典型需求,STC8H8K64 这类 8KB RAM 的型号很舒服。
需要多工位、要接触摸屏、或者要做生产数据记录(比如按班次存到 SD/TF 卡里以表格形式导出),再考虑 STM32F103C8T6:72MHz、多路定时器、多路 12 位 ADC、DMA,可以把采样、通信、显示拆到不同外设上跑,不用再靠软件硬挤。
| 单片机 | 主频/内核 | RAM | 适合机型 | 注意点 |
|---|---|---|---|---|
| STC89C52RC | 12MHz / 12T | 256B | 单工位、时序为主 | T0/T1 别用满,留一个给串口波特率 |
| STC8H8K64 | 24MHz / 1T | 8KB | 单/双工位称重闭环 | EEPROM 写次数有限,标定参数别每袋都写 |
| STM32F103C8T6 | 72MHz / Cortex-M3 | 20KB | 多工位 + 触摸屏 | ADC 参考电压要单独稳,别直接吃 3.3V 数字电源 |
选型上我一般这样判断:如果目标重量只能写到 0.1kg 级、给料靠时间关阀,51 足够;如果要求 ±20g 以内、必须做两级给料加动态提前量,直接上 1T 的 STC 或 STM32,省得后期为了"能不能再快一点"来回改板。
2.2 称重传感器与 HX711 信号链的量程和接线
粉料包装机的称重核心是电阻应变式称重传感器配 HX711 这类 24 位专用 AD。量程选择有个常用经验:传感器额定容量取包装目标值的 1.5~2 倍。做 25kg 包装,选 30kg 或 50kg 量程。选 30kg 是因为满量程接近工作点,有效分辨率利用率高;选 50kg 是留抗冲击余量,代价是同样的 AD 位数下每克对应的码值更少。
算一下分辨率。假设 30kg 传感器、HX711 有效位数按 18 位估算(不是标称 24 位,实际噪声下有效位会掉),满量程码值约 262144,则每克约 8.7 个码值。25kg 目标 ±25g 的精度要求对应约 ±220 个码值,余量充足。换成 50kg 传感器,每克约 5.2 个码值,仍然够用。所以量程放大一档不至于让精度崩掉,但再大就要谨慎了。
接线方面,四线制称重传感器是 E+、E-、S+、S-,HX711 模块上对应 E+、E-、A+、A-,屏蔽线单端接地,走线尽量远离电机和变频器动力线。HX711 与 MCU 只要两根线:DOUT 和 SCK。
// HX711 读一次 24 位数据,通道 A 增益 128 // DOUT 接 P2.0,SCK 接 P2.1,STC8 引脚直接位操作 unsigned long HX711_Read(void) { unsigned long val = 0; unsigned char i; while (HX711_DOUT); // 等待 DOUT 拉低,表示本次转换完成 for (i = 0; i < 24; i++) { // 读 24 位,高位在前 HX711_SCK = 1; // 上升沿,芯片输出当前位 val <<= 1; if (HX711_DOUT) val++; HX711_SCK = 0; // 下降沿,准备下一位 } HX711_SCK = 1; // 第 25 个脉冲设定下一周期通道与增益 HX711_SCK = 0; val ^= 0x800000; // 24 位补码转原码,得到有符号差值 return val; }这段代码的关键点有三个。while (HX711_DOUT)是等转换结束,如果一直卡在这里,多半是 SCK 悬空或者传感器没供电。val ^= 0x800000这步不能省,HX711 输出的是补码,不做这步空秤时读出来会是一个接近 0x800000 的大数,标定时会以为传感器坏了。第 25 个脉冲决定下个周期的通道和增益,只读通道 A 增益 128 的话固定发一个脉冲就行,要切通道就得按芯片时序给不同脉冲数。
提示:HX711 的供电和参考电压共用 AVDD,如果直接用开关电源的 5V,纹波会直接进 AD。控制板上给它单独加一级 LC 滤波,或者用 5V 后接一颗低噪声 LDO 供 AVDD,读数稳定性差别很大。
2.3 给料执行机构与 IO 分配表
粉料给料一般分两种执行方式。一种是螺旋给料机,靠三相电机或者直流电机带动,控制上就是接触器或继电器的启停;另一种是振动给料,靠电磁振动器,用可控硅调压控制振幅。前者逻辑简单,后者的振幅可以直接映射成"下料速度",细给料阶段把振幅调小,冲击会更平缓。
包装动作一共就几个:夹袋气缸夹住袋口、粗给料开、细给料开、称重到位关给料、松袋、放袋。加上急停、启动、光电到位检测,一个单工位的 IO 表大致如下。
| 功能 | 方向 | 典型引脚 | 说明 |
|---|---|---|---|
| HX711 DOUT | 输入 | P2.0 | 需上拉,内部弱上拉可用 |
| HX711 SCK | 输出 | P2.1 | 推挽输出 |
| 粗给料继电器 | 输出 | P1.0 | 经 ULN2003 或光耦驱动 |
| 细给料继电器 | 输出 | P1.1 | 同上 |
| 夹袋电磁阀 | 输出 | P1.2 | 加续流二极管 |
| 松袋电磁阀 | 输出 | P1.3 | 与夹袋互锁 |
| 启动按钮 | 输入 | P3.2 | 外部中断 INT0,做急启 |
| 急停按钮 | 输入 | P3.3 | 常闭,断线也要停机 |
| 袋到位光电 | 输入 | P3.4 | 检测袋口是否夹好 |
| 蜂鸣器 | 输出 | P1.4 | 报警与到位提示 |
急停用常闭接法,是粉料包装机上很重要的一条。常开接法一旦线断了,MCU 读到的一直是"没按急停",等于保护失效。常闭接法断线读到的是"急停生效",宁可误停也不能漏停。
初始化阶段要注意:上电先关所有输出,再读一次 HX711 扔掉第一帧,最后才进主循环。继电器驱动的感性负载在断开瞬间会产生反压,输出脚和地之间并一颗续流二极管,或者直接用 ULN2003 这类带续流二极管的驱动芯片,能省掉不少"跑几天继电器就偶尔不吸合"的怪毛病。
3. 粉料包装机的定时器采样、滤波与两级给料逻辑
硬件定了,真正决定包装精度的是软件里那几条判断。粉料下落的惯性和空中余料是绕不过去的物理事实,控制逻辑要做的就是把"传感器现在多重"换算成"还能不能继续喂"。
3.1 两级给料:粗给料与细给料的阈值怎么定
单级给料的问题是:如果在接近目标时才关,冲击大、超差多;如果一开始就慢喂,效率太低。业内通行做法是两级:先粗给料把大部分料快速灌进去,到某个阈值(比如目标值的 85%~90%)切细给料,用低速把剩下那一小截喂准。
切细的阈值怎么定,跟物料流动性关系最大。面粉、淀粉流动性好,切细点可以设在 90%~92%,因为后面补料快、滞后小;腻子粉、碳酸钙这类粘性大、易结拱的粉料,切细点设在 80%~85% 更稳妥,宁可留多一点给细给料阶段,也别让大量料在最后一刻一起砸下来。
| 物料类型 | 粗/细切换阈值 | 细给料提前量(占目标值) | 备注 |
|---|---|---|---|
| 面粉、淀粉 | 目标值 × 0.90~0.92 | 0.3%~0.8% | 流动性好,提前量小 |
| 腻子粉、碳酸钙 | 目标值 × 0.80~0.85 | 1.0%~2.0% | 防结拱,留料多 |
| 水泥、干混砂浆 | 目标值 × 0.82~0.88 | 0.8%~1.5% | 扬尘大,检查密封 |
提前量的含义是:当称重读数还没到目标值,但已进入"目标值 - 提前量"这个区间时,就要提前关断给料,剩下的量靠空中余料自然落完。提前量设太小会超差偏高,设太大就会欠灌,这个数只能现场试出来。
3.2 51单片机定时器中断驱动的称重采样与滑动滤波
称重信号里混着给料振动带来的抖动,单次读数直接拿去比较,会在阈值附近来回跳。常见做法是用定时器固定节拍采样,再做滑动平均。STC 的定时器按 10ms 一次比较合适,既跟得上给料节奏,又不会让中断太频繁。
#define FILTER_N 8 static long filter_buf[FILTER_N]; static unsigned char filter_idx = 0; static bit sample_flag = 0; // 定时器 0 初始化,10ms 中断一次(1T 内核,24MHz) void Timer0_Init(void) { TMOD &= 0xF0; // 保留 T1 配置,清掉 T0 位 TMOD |= 0x01; // T0 工作在模式 1,16 位定时 TH0 = 0xD8; // 24000 计数对应 10ms,按实际主频核算 TL0 = 0xF0; ET0 = 1; // 允许 T0 中断 TR0 = 1; // 启动定时器 EA = 1; // 开总中断 } // 定时器 0 中断服务函数:只置标志,不在中断里做重活 void Timer0_ISR(void) interrupt 1 { TH0 = 0xD8; // 重装初值 TL0 = 0xF0; sample_flag = 1; // 交给主循环处理 } // 滑动平均滤波,返回处理后的重量码值 long Weight_Filter(long raw) { long sum = 0; unsigned char i; filter_buf[filter_idx] = raw; filter_idx = (filter_idx + 1) % FILTER_N; for (i = 0; i < FILTER_N; i++) { sum += filter_buf[i]; } return sum / FILTER_N; }这段代码里有两个容易踩点。一是中断里只置标志、不读 HX711,因为读一次 HX711 要等 24 个时钟周期加转换时间,放在中断里会把其它中断拖住;主循环看到sample_flag再读、再滤波、再做判断,节奏反而更稳。二是滑动平均窗口取 8 是经验值,窗口太短滤波不干净,太长会让重量读数整体滞后,细给料阶段判断"还剩多少"时就会偏乐观,最终超差。试出合适的窗口长度,一般用一串实际灌装数据回放对比最快。
提示:如果现场振动特别大,滑动平均之外可以再叠一个"限幅"——单次读数与上次滤波值的偏差超过阈值就认为是被干扰,直接丢弃这一帧。这个方法对继电器动作瞬间的尖峰抑制很有效。
3.3 用状态机把夹袋、灌装、放袋串起来
包装流程是典型的状态迁移,用一堆 if-else 堆时序会越写越乱。写成状态机之后,每个状态只关心自己这一段的进入条件、退出条件和超时保护,调试时看一个状态变量就知道流程卡在哪。
状态划分建议:待机 → 夹袋 → 粗给料 → 细给料 → 空中余料等待 → 称重确认 → 放袋 → 回到待机。其中"空中余料等待"是最容易被省掉的一步,但它是精度的关键:给料关断之后必须留一个稳定延时,等袋内物料落稳再读数确认,否则确认的时刻物还在空中飘,读出来永远偏低。
typedef enum { ST_IDLE, ST_CLAMP, ST_COARSE, ST_FINE, ST_SETTLE, ST_CONFIRM, ST_RELEASE } PackState; static PackState state = ST_IDLE; static unsigned long state_tick = 0; void Pack_Step(void) { switch (state) { case ST_IDLE: if (start_btn == 0) { CLAMP_ON(); state = ST_CLAMP; state_tick = 0; } break; case ST_CLAMP: if (++state_tick > 30) { // 300ms 夹袋到位 COARSE_ON(); state = ST_COARSE; state_tick = 0; } break; case ST_COARSE: if (weight_g >= target_g * 0.85) { // 切细给料阈值 COARSE_OFF(); FINE_ON(); state = ST_FINE; state_tick = 0; } break; case ST_FINE: if (weight_g >= target_g - lead_g) { // 提前量关断 FINE_OFF(); state = ST_SETTLE; state_tick = 0; } break; case ST_SETTLE: if (++state_tick > 50) { // 500ms 等余料落稳 state = ST_CONFIRM; state_tick = 0; } break; case ST_CONFIRM: record_weight(weight_g); // 记录本袋实际重量 state = ST_RELEASE; state_tick = 0; break; case ST_RELEASE: CLAMP_OFF(); RELEASE_ON(); if (++state_tick > 20) { RELEASE_OFF(); state = ST_IDLE; } break; } }几个参数对应关系要捋清:target_g是目标重量,lead_g是提前量,weight_g来自滤波后的码值换算。state_tick的单位是流程节拍,如果主循环里用 10ms 定时标志驱动Pack_Step(),那 30 个 tick 就是 300ms。所有延时都要有超时兜底——比如粗给料如果 10 秒还没到阈值,说明结拱堵料了,必须报警停机,不能无限等下去。
4. 粉料包装机控制板的串口参数下发与现场排错
成品包装机交付之后,客户换物料、换规格是家常便饭。如果每次改目标重量都要拆机壳重新烧录,售后成本会失控。把参数做成串口下发、存进 EEPROM,是一条省事又省心的路。这个串口通道同时还能承担固件升级,现场维护时不用把板子拆下来。
4.1 串口帧格式设计与上位机参数下发
串口协议不用做得复杂,但要能自校验。定长帧 + 帧头 + 校验和,是工控现场最稳的写法:上位机(PLC、组态屏、或者一台跑串口助手的笔记本)只要按格式发,MCU 收到后先校验再执行。
| 偏移 | 字节数 | 含义 | 示例 |
|---|---|---|---|
| 0 | 1 | 帧头 | 0xAA |
| 1 | 1 | 命令字 | 0x01 设目标重量 / 0x02 设提前量 / 0x03 读状态 |
| 2 | 2 | 数据高字节在前 | 25000 表示 25.000kg(单位 g) |
| 4 | 1 | 校验和 | 前 4 字节累加取低 8 位 |
| 5 | 1 | 帧尾 | 0x55 |
MCU 侧接收用串口中断,收满 6 字节再校验,不在中断里做 EEPROM 写操作。
#define FRAME_LEN 6 static unsigned char rx_buf[FRAME_LEN]; static unsigned char rx_cnt = 0; static bit frame_ready = 0; void UART_ISR(void) interrupt 4 { unsigned char c; if (RI) { RI = 0; c = SBUF; if (rx_cnt == 0 && c != 0xAA) return; // 不是帧头,直接丢弃 rx_buf[rx_cnt++] = c; if (rx_cnt >= FRAME_LEN) { rx_cnt = 0; if (rx_buf[5] == 0x55 && rx_buf[4] == (unsigned char)(rx_buf[0] + rx_buf[1] + rx_buf[2] + rx_buf[3])) { frame_ready = 1; // 校验通过,交给主循环 } } } if (TI) TI = 0; }主循环里判断frame_ready,按命令字写 EEPROM 并回一帧确认。这一套也顺便把固件升级打通了:上位机按固定帧格式把新固件分块发下来,MCU 先写进 EEPROM 缓存区,校验整体 CRC 通过后再跳转到升级引导程序擦写程序区,中途断电最坏也就是升级失败,旧程序还在,不会变砖。这种思路和 STC 单片机常见的串口在线升级架构是一个道理。
注意:写 EEPROM 只在参数变更那一刻做,别每袋都写。EEPROM 擦写次数一般十万次量级,按袋写几天就可能写坏。
4.2 称重标定与提前量参数整定
标定是精度能不能守住的前提。最常用的做法是两点标定:空秤读一次原始码值raw0,放上已知标准砝码再读raw1,两者对应的实际重量分别是 0 和W。
标定系数 = 砝码重量 / (raw1 - raw0)。之后任意读数的重量换算:
# 上位机侧做标定与验收数据的记录,串口读回的原始码值直接算 raw0 = 8312450 # 空秤码值 raw1 = 8720130 # 放上 20kg 砝码后的码值 W = 20000.0 # 砝码重量,单位 g k = W / (raw1 - raw0) def to_gram(raw): return (raw - raw0) * k print(to_gram(8720130)) # 输出接近 20000.0标定完不要急着上线,先做一轮空跑:用正常速度灌 20 袋,记录每袋实际重量。看偏差的分布形态。如果大部分偏高、随目标重量线性增大,先怀疑标定系数或传感器线性;如果整体偏低固定量,说明提前量设小了,往上调一档再试;如果忽高忽低、没有规律,那是滤波或干扰问题,先去查信号线走线和电源纹波,动参数没用。
提前量整定的实操做法是:从 1.0% 目标值开始,每灌 10 袋统计一次均值,偏差超过 ±10g 就调 0.2% 再试,直到连续 30 袋都落在 ±20g 以内。换物料后必须重新整定,因为流动性和堆积密度变了,原来的提前量不再适用。
4.3 扬尘、振动与常见故障定位
粉料现场比多数电子设备环境恶劣:粉尘细、湿度不定、周围有电机和变频器。故障定位顺着信号链走,效率最高。
| 现象 | 优先排查 | 处理方式 |
|---|---|---|
| 称重读数一直不动 | HX711 供电、传感器接线 | 万用表量 AVDD,检查 E+/E- 是否短路 |
| 读数跳动 ±100g 以上 | 电源纹波、屏蔽线接地 | 示波器看 AVDD 纹波,单端接地 |
| 空秤读数缓慢漂移 | 传感器受潮或温漂 | 加温度补偿,或更换防护等级高的传感器 |
| 串口偶尔丢帧 | 波特率偏差、线材过长 | 用 11.0592MHz 晶振算波特率,加隔离 |
| 输出继电器不吸合 | 驱动芯片或续流二极管 | 换 ULN2003,检查感性负载反压 |
| 急停不起作用 | 急停接法错误 | 改常闭接法,断线触发保护 |
串口波特率是常被忽略的一项。51 单片机用定时器产生波特率时,主频选 11.0592MHz 而不是 12MHz,就是因为 11.0592 能被标准波特率整除,误差最小。用 12MHz 硬算出来的波特率有固有误差,实验室看不出问题,到现场长线一跑就丢帧。这条经验在 STC 上依然成立,虽然 STC 内部时钟可以配置,但用外部晶振时还是优先 11.0592。
5. 粉料包装机控制系统的稳定性验证技巧
样机在实验室跑通,跟产线上连续三天不掉链子是两回事。稳定性验证里,我一般会做三件事:把参数拉出工作范围做边界测试、上真料连续跑一批记录偏差、再模拟断电和急停看复位行为。
边界测试是最快暴露问题的一步。把目标重量设到控制器允许的最小值(比如 5kg)跑 10 袋,再设到最大值(比如 50kg)跑 10 袋,看两级给料的阈值逻辑在小重量下是不是还成立——如果提前量按比例算,目标重量小的时候提前量也跟着变小,容易直接被忽略掉,导致超差。反过来,大重量时粗给料切细的阈值绝对量很大,如果细分给料能力不够,最后一个粗给料就把料砸过头了。
真料连续跑这一批,重点是记录每条袋子的实际重量和状态机走到的最后状态。把数据存到 SD/TF 卡里,按班次生成一张表格,出问题时直接对照时间戳看是哪一袋卡住、卡在哪个状态。这套数据记录不需要复杂,慢速串口打点或者简单 SPI 写卡都行,关键是能回溯。
断电复位行为要单独测。在粗给料中途直接拔电,重新上电时控制板必须先进待机、所有输出关闭,绝对不能带着上次的半袋料直接进下一次灌装。复位后如果检测到袋位传感器仍被挡住,应该先放袋清料,再回待机,不要自动续灌。这套逻辑在代码里体现为启动时先关输出、再判断传感器、最后才允许启动,写在与主循环并行的初始化函数里,代码不长但能挡掉不少现场事故。
最后一个技巧是把参数整定的流程也做成可复现的:目标重量、提前量、滤波窗口、串口波特率这几个值,全部通过上位机一键下发、存进 EEPROM,并在数码管上能逐项翻看当前生效值。换物料时操作员自己就能改,售后不用每单都跑现场,这套系统的维护成本才算真正压下来。
本文还有配套的精品资源,点击获取