基于单片机的称重打包机设计与实现:从硬件选型到调试避坑
简介本资源是一套完整的基于单片机的称重打包机毕业设计/课程设计方案面向电子信息、自动化、机电类专业本科生及实践教学指导教师解决智能称重与自动打包系统从原理设计到功能验证的全流程学习需求。压缩包共26个文件涵盖Protues仿真工程.pdsprj/.pdsbak、Keil工程源码.uvproj/.c/.h/.hex、原理图.SchDoc/.PDF、器件清单.xls、功能说明文档.txt、程序流程图.png/.bmp及仿真结果图.png全面支撑硬件设计、软件编程与系统联调。已有52人下载学习适合开展课程设计、毕设开发或单片机综合实训。用户可直接导入Keil与Protues进行编译与仿真复现自动校准、实时称重显示、按键控制打包、故障自检等核心功能并参考流程图与模块化C代码深入理解HX711称重传感器驱动、LCD1602显示及电机执行机构控制逻辑。先想清楚再动手这个称重打包机到底在做什么做单片机项目最怕一上来就写代码、焊板子结果做到一半发现方案有问题。基于单片机的称重打包机这个题目本质上是把一个工业现场很常见的“称重 定量下料 封包”动作用单片机这套低成本方案完整复现出来。它解决的问题是人工称重打包效率低、误差大而工业PLC成套设备又太贵所以用单片机做一套简易但功能完整的自动称重打包机既适合毕业设计、课程设计也适合真正想搞小规模自动化产线的人做原型验证。这个项目适合谁三类人第一类是电子信息、自动化、机械电子专业的本科生做毕设或者课设第二类是刚接触单片机、想做一个带传感器和电机控制的综合项目的学习者第三类是小型工厂、作坊的技术人员想低成本实现定量包装。看完这篇内容你不仅能搞懂硬件怎么搭、代码怎么写还能避开我在实际调试中踩过的那些坑——尤其是称重数据漂移和电机干扰这两个老大难问题。1. 系统整体设计与方案选型1.1 核心需求拆解先把题目拆开看。称重打包机核心动作是把物料放到称重平台上传感器检测到重量单片机读取重量数据显示给操作员看同时判断是否达到设定值达到之后控制打包机构的电机动作完成封口、切断或者压紧然后进入下一次循环。这里有三个关键环节称重需要称重传感器把重量变成电信号。判断与控制需要单片机读取数据和设定值比较输出控制信号。执行需要电机驱动机构完成打包动作。所以整个系统最少得有这几块称重传感器 信号调理电路 单片机最小系统 显示模块 按键输入 电机驱动。缺一块这个系统就转不起来。1.2 方案对比单片机 vs PLC vs 嵌入式Linux很多人在方案选型时纠结我直接做个对比表你自己判断。方案成本开发难度实时性适用场景8位单片机51/AVR/PIC极低整套几十元中低适合学习好微秒级响应简单称重打包、教学演示STM32等32位单片机较低带ADC性能更好中等很好精度要求更高、多任务场景PLC 称重仪表高几千到上万低梯形图拖拽很好工业现场、可靠优先嵌入式Linux 触摸屏高启动慢高一般非实时需要人机界面、数据上云的复杂系统这套设计选8位单片机具体是STC89C52或者AT89S52这种51内核的性价比最高。有人问为什么不用STM3251单片机完全够用而且相关资料多、上手快。搞设计不是越高级越好而是越匹配越好。称重传感器的信号经过HX711这个24位ADC转成数字量单片机只需要用IO口模拟时序去读这个组合在称重类项目里几乎成了标准答案方案成熟、代码好写、调起来也容易。1.3 整体硬件架构系统框图在脑子里过一遍不需要画图工具思路是这样的一条链路压力/重量 - 电阻应变式称重传感器 - HX711放大器24位ADC - 51单片机 - LCD1602显示 LED指示灯操作员 - 矩阵键盘/独立按键 - 51单片机 - 继电器 - 直流减速电机带动打包机构蜂鸣器 - 语音提示或报警为什么用HX711而不是单片机自带的ADC51单片机内部没有ADC就算用带ADC的增强型51或者STM32内置ADC的精度也一般做到12位就算不错了。而HX711是专门为称重设计的24位高精度ADC内部还集成了可编程增益放大器PGA能直接把传感器输出的毫伏级差分信号放大到单片机可以处理的数字量误差小、稳定。这块芯片淘宝几块钱一片外围电路简单基本不需要额外调试硬件用谁谁知道。2. 核心硬件设计与选型细节2.1 称重传感器的原理与选型称重传感器是整套系统里“最贵也最玄”的部分。市面上最常见的称重传感器是电阻应变式核心原理是弹性体受力后发生形变贴在弹性体上的电阻应变片跟着拉伸或压缩电阻值发生变化。把四片应变片接成惠斯通电桥供电后桥路输出一个与受力成正比的差分电压信号。这里要注意传感器输出的信号非常微弱。一个典型的量程5kg的传感器激励电压5V时满量程输出大约10mV到20mV。这个信号太小了单片机直接读根本读不到必须经过仪表放大器放大。HX711内部集成的PGA正好干这个活增益一般设在128倍把信号放大到可以分辨的程度。选传感器只看三点量程、精度、结构。量程不要选刚好等于最大称重量的最好留出1.5到2倍余量。比如最大要称2kg的物料选5kg量程的传感器防止超载损坏弹性体。精度传感器输出的灵敏度参数常见有1mV/V、2mV/V数值越大同样受力下输出越大。结构平台式还是悬臂梁式取决于你的机械设计。课程设计一般用悬臂梁式的铝制传感器好安装四个角有固定孔接线颜色也标准红色接E、黑色接E-、绿色接S、白色接S-。2.2 HX711的硬件接线与注意事项HX711模块现在大部分都是现成的电路板引脚也就那么几个VCC和GND电源模块一般支持2.6V到5.5V直接接到单片机的5V。SCK时钟和DOUT数据和单片机IO口连接注意这两个脚是双向的DOUT是开漏输出单片机的IO口用准双向口模式就行不需要额外上拉51单片机自带的弱上拉够用。HX711的24位输出格式是二进制补码默认增益128。读数据的时候DOUT在数据准备好时拉低单片机给SCK脉冲每给一个脉冲读一位读24个脉冲完成一次数据读取。如果要切换增益到64或32就在24个脉冲之后再给相应数量的SCK脉冲。我用的时候固定用128增益代码就固定24个脉冲让它保持在转换状态。接线时还有两个细节经历过你就知道电源要干净。HX711是24位高精度ADC对电源纹波非常敏感。如果直接和电机共用一路电源电机一启动称重数据就会跟着乱跳。我做过测试电机启动瞬间5V电源电压跌落到4.6V左右HX711读数直接偏了十几个克。解决办法就是单片机、HX711单独用一路稳压电机驱动用另一路电源两路电源共地。如果条件限制只能一路电源至少要在HX711的电源引脚旁边加100uF电解电容和104陶瓷电容滤波并且用DC-DC隔离模块把电机电源和逻辑电源分开。传感器信号线要屏蔽。DOUT和SCK信号线尽量短不要和电机驱动线扎在一起走线。如果实在绕不开用双绞线传输信号或者加磁环。这个项目里DOUT和SCK走线不超过10cm问题不大但如果是实际工程就要注意长了信号容易受干扰。2.3 单片机最小系统与显示方案单片机最小系统说穿了三件事电源、时钟、复位。电源5V稳压。如果是USB供电稳压芯片用AMS1117-5.0就行记得在输入输出端各加一个10uF电解电容和104电容。时钟51单片机用12MHz晶振两个20到30pF的负载电容。有人算过12MHz一个机器周期是1us定时器初值好算比如1ms定时就用模式1初值0xFC67。这个频率对HX711通信也足够快SCK时钟在50kHz左右随意满足。复位经典的上电复位电路10uF电容串联10k电阻到地复位脚接高电平。这个不用多说了照着常用电路画就行。显示方案选LCD1602。为什么不选数码管数码管简单但是显示内容有限LCD1602两行每行16个字符可以同时显示“当前重量”和“设定重量”还能显示单位、状态人机交互体验好。LCD1602标准库代码到处都是初始化时序固定照着写就行。唯一要注意的是LCD1602的对比度调节脚VO要接一个10k电位器不然屏幕可能出现“全白的屏幕”或者“完全看不清字”的情况这个也是新手经常踩的坑之一。还有如果用的是3.3V的LCD1602模块和5V单片机连接时要小心逻辑电平匹配不过大部分LCD1602都是5V版本这个问题少一些。2.4 电机驱动与打包机构执行打包机的执行机构一般是直流减速电机带动一个凸轮或者曲柄连杆机构完成压紧、封口、切袋的动作。动作过程里电机不需要精确调速只需要正转、反转、停止三种状态所以用继电器或者L298N驱动都可以。继电器方案最简单但有个致命问题继电器是机械触点通断瞬间有电弧而且吸合时间有几十毫秒响应慢。如果用PWM控制电机调速这个项目里不需要调速继电器就完全不行。实际我这套用的是MOS管 续流二极管的方案电机正极接12V电源负极接N-MOS管的漏极。MOS管栅极通过一个1k电阻接单片机IO口源极接地。电机两端反向并联一个IN5822或SS34肖特基二极管用来吸收电机断电时产生的反向电动势。如果电机功率比较大栅极还要加一个10k的下拉电阻防止单片机复位瞬间IO口悬空导致MOS管误触发。这个方案成本比继电器低寿命长开关频率高而且没有机械触点打火的问题。我个人强烈建议用MOS管代替继电器只要注意电机功率别超过MOS管的允许电流即可。比如AO3400这种小MOS管最大电流5.8A驱动一个小型直流减速电机绰绰有余。3. 软件设计与核心代码实现3.1 程序整体框架软件设计最怕一把梭把全部代码写在一个main函数里。我用的是“主循环 定时器中断”的结构main函数里初始化LCD、HX711、按键、电机IO口然后进入一个大的while(1)循环。循环里做这几件事调按键扫描函数更新设定值调HX711读取函数读取当前重量调显示刷新函数把重量显示到LCD上调电机控制函数根据当前重量和设定值决定电机动作。定时器0做1ms时基设置一个软件计数器用来做按键消抖的延时和ADC读取间隔控制。这个结构的好处是每个功能模块之间解耦出问题的时候好定位。比如显示不对先单独查显示函数重量不对单独查HX711读取和滤波函数。调试效率高很多。下面给出一个框架代码的伪代码结构void main() { System_Init(); // 初始化定时器、IO、LCD、HX711 Set_Weight 500; // 默认设定重量单位克 while(1) { Key_Scan(); // 按键扫描更新Set_Weight Current_Weight HX711_Read(); // 读取当前重量 Display_Update(); // 刷新LCD显示 Motor_Control(); // 电机控制 } }3.2 HX711读取与数字滤波HX711读取函数网上有很多现成的代码核心都差不多。我这里贴出我调试过可用的代码关键是读的时候时序要严格unsigned long HX711_Read(void) { unsigned long count 0; unsigned char i; HX711_DOUT 1; HX711_SCK 0; // 等待DOUT变低说明转换完成 while(HX711_DOUT); // 读取24位数据 for(i 0; i 24; i) { HX711_SCK 1; count count 1; HX711_SCK 0; if(HX711_DOUT) count; } // 第25个脉冲设置增益为128并进入下一次转换 HX711_SCK 1; count count ^ 0x800000; // 处理补码格式 HX711_SCK 0; return count; }读回来的数据是24位的裸数据范围大概是-8388608到8388607。这个裸数据不是重量必须经过标定转换成实际克数。转换公式很简单实际重量 (当前读数 - 零点读数) × 标定系数零点读数就是空载时读到的值标定系数就是往平台上放一个已知重量的砝码计算标定系数 砝码重量 / (砝码读数 - 零点读数)注意不要只读一次就完事。HX711输出有一定噪声最大的噪声来源是机械振动和电源纹波。我做了一次简单的移动平均滤波每读5次取平均刷新率大概10Hz这样显示的数字就非常稳定。你也可以用中位值平均滤波法把读到的5个值排序后去掉最大最小再平均效果更好。这里要特别提醒滤波这个环节不能省。如果不滤波显示器上的数字会一直在跳比如实际500g的砝码读数可能在498g到503g之间反复横跳给人感觉系统不稳定。加完滤波后读数基本稳定在500g偶尔跳一个克这是正常的。商用称重仪表还会加更复杂的滤波算法但我们这个项目级别移动平均足够了。3.3 按键输入与设置逻辑按键方案我用的是4个独立按键按键1设置键进入设置模式按键2加键设定值增加10g或100g按键3减键设定值减少10g或100g按键4启动/停止键按键消抖是老生常谈的问题硬件消抖可以用RC滤波加滞回比较器但最常见也最省事的还是软件消抖检测到按键按下后延时10ms再检测一次如果还是低电平就认为按键有效。这个10ms延时在轮询里可以用定时器计数实现不要在按键扫描函数里用延时死等否则整个主循环就被堵住了。我的按键处理代码核心逻辑void Key_Scan(void) { if(Key_Set 0) { Delay_MS(10); // 消抖 if(Key_Set 0) { Setting_Mode !Setting_Mode; // 切换设置模式 while(Key_Set 0); // 等待按键释放 } } // 设置模式下加/减设定值 if(Setting_Mode) { if(Key_Add 0) { Delay_MS(10); if(Key_Add 0) { Set_Weight 10; if(Set_Weight 5000) Set_Weight 5000; // 限幅 while(Key_Add 0); } } // 减键逻辑类似 } }这里有个小技巧长按加速。如果加键按住超过500ms就每50ms自动加一次而且步进从10g变成100g。这样设定大重量值的时候不用一下一下按几十次。实现方式就是用定时器记录按键按下的时间超过阈值后进入连加模式。这个小功能对实际使用体验提升很大推荐加上。3.4 电机控制与状态机设计电机控制的逻辑如果用一堆if嵌套代码会很难维护。推荐用状态机。整个系统可以分成四个状态等待状态IDLE系统上电初始化等待启动键。称重状态WEIGHING电机停止显示当前重量判断是否达到设定值。打包状态PACKING达到设定值电机正转执行打包动作。完成状态DONE打包动作完成电机反转或者停止蜂鸣器响一声提示回到称重状态或者等待下一个循环。状态机的好处是逻辑清晰每个状态下只处理该干的事不会出现“电机该转的时候没转不该转的时候乱转”这种问题。代码上就是一个switch语句switch(System_State) { case STATE_IDLE: Motor_Stop(); // 检测到启动键按下切换到称重状态 if(Start_Flag) System_State STATE_WEIGHING; break; case STATE_WEIGHING: Motor_Stop(); if(Current_Weight Set_Weight) { System_State STATE_PACKING; Pack_Timer 0; // 打包计时清零 } break; case STATE_PACKING: Motor_Forward(); // 打包动作持续2秒然后反转0.5秒回位 if(Pack_Timer 2000) { Motor_Reverse(); if(Pack_Timer 2500) { Motor_Stop(); System_State STATE_DONE; } } break; case STATE_DONE: Motor_Stop(); Buzzer_On(); Delay_MS(200); Buzzer_Off(); System_State STATE_WEIGHING; // 自动进入下一次称重 break; }打包时长的2秒和回位0.5秒不是拍脑袋定的是根据实际电机转速和打包机构的行程算的。你可以在调试时先用万用表或者示波器观察从按下启动到机构完全压紧需要多长时间然后把这个时间写进代码里。如果想更精确可以在打包机构上装限位开关碰到就停止这比定时器靠谱得多特别是机构行程偶发变化时。当然课程设计级别用定时器就够了毕竟限位开关还要多接两根线。4. 系统调试与标定的实操记录4.1 标定流程从裸数据到克数标定是整个项目最关键的环节标定错了后面全白搭。我自己的操作流程是这样的你照着做一遍就会了第一步空载采集零点。把平台上所有东西都拿掉让传感器空载程序里读取100次HX711数据取平均得到零点值。这个操作不能只在冷机时做一次实际用的时候最好每次上电都自动标定一次零点因为传感器会受温度影响零点会漂移。第二步放标准砝码。找几个标准砝码比如500g、1kg、2kg各一个。放上500g砝码读取数据按前面那个公式算出标定系数。注意砝码务必放在称重平台的中心位置放在边缘会有侧向力测出来的值不准。第三步验证。把砝码拿掉放上一个不同重量的物品看显示值和实际值差多少。如果误差在±2g以内基本合格。如果误差很大检查两点一是传感器的量程是不是选大了量程大的传感器在小重量时分辨率差二是机械结构有没有卡住传感器有没有被什么东西压着或者别着。4.2 我踩过的坑电机一响重量就跳这个是我最想分享的坑花了我整整一个下午才排查清楚。现象是这样的空载时HX711读数很稳定显示0g。但只要一按启动键电机转起来LCD上的重量立刻跳到几十克甚至上百克电机停了又慢慢回落。一开始我以为是传感器接线没接好重新焊了一遍没解决。后来怀疑是HX711模块电源不稳给模块加了电容还是没解决。最后用示波器测了电机电源和单片机电源的电压波形发现电机一启动两路电源电压都在抖动说明地线没做好隔离。单片机、HX711、电机驱动全部共地连在了一块地线细电机电流大在地线上产生了压降这个压降直接叠加到了HX711的输出上。解决办法就是前面说的电机电源和逻辑电源完全分开只在一点共地。我用了一个12V电源给电机供电一个5V稳压芯片单独给单片机、LCD、HX711供电两路电源的GND在单片机板的GND处单点连接。改完以后再测电机启动瞬间重量读数纹丝不动。如果你想验证自己的系统是不是有这个地线干扰的问题最简单的测试方法电机空转时用手按在传感器上看LCD显示是否正常。如果显示跳动大概率就是共地问题。4.3 常见问题速查表整理一个我在调试中遇到的问题表按出现频率排序问题现象可能原因排查方法LCD1602不显示对比度电位器没调好调VO脚电位器直到出现字符LCD显示乱码引脚接线错误或初始化时序不对检查DB0-DB7接线重看时序重量读数一直为0传感器接线错误、HX711供电问题查传感器四根线颜色量E和E-电压重量读数恒定不变HX711的SCK/DOUT接反或悬空用万用表量DOUT是否在拉低跳变读数跳动大滤波不够、电源不稳、传感器固定松动加滤波、检查电源纹波、重新固定传感器电机不转MOS管没导通、驱动IO口配置错误量MOS管栅极电压程序里置高电平测试电机转不停状态机逻辑错误、定时器溢出检查状态切换条件、定时器初值按了按键没反应消抖时间不够、IO口被复用示波器看按键电平变化检查IO配置还有一个容易忽略的点HX711模块工作要一点时间才能稳定上电后最好等500ms到1秒再开始读取数据让芯片内部电路和传感器稳定下来。我程序里专门做了一个延时函数上电后蜂鸣器响一声等1秒再进入主循环。别小看这个细节能避免很多莫名其妙的首次读数错误。4.4 关于精度做到什么程度算合格很多同学做这个项目开口就要“高精度”我觉得要先明确精度指标怎么定。称重打包机不需要达到实验室分析天平的精度。商用定量包装秤的精度一般在±5g以内而我们的目标是±2g就算很好了。用5kg量程的传感器配HX711 24位ADC理论分辨率可以达到5kg × (1 / (1 23)) ≈ 0.6g但这只是理论值实际受机械结构、温度漂移、电源噪声影响能做到±2g到±3g已经相当不错。如果你需要更稳定除了滤波之外还可以做一点线性补偿。传感器在满量程和低量程时标定系数不是完全一致的称重仪表里会做多点标定。你可以在500g、1000g、2000g三个点上各算一个标定系数然后在程序里做查表插值。课程设计做到这个程度已经远超大多数同学了。5. 项目扩展方向与个人经验总结5.1 数据上传把称重数据接到上位机打包机的数据如果能上传到电脑或手机就多了一个很有价值的扩展方向。最便宜的方案是加一个CH340的USB转串口模块单片机通过串口把每次的打包数据时间、重量发出去上位机用串口助手或者自己写个简单的Python程序接收。串口发送的程序很简单void UART_SendString(char *str) { while(*str) { SBUF *str; while(!TI); TI 0; } }然后每次打包完成拼一个字符串发出去比如PACK,20250119,123456,500g,OK上位机按逗号分隔解析就行。如果想做Excel数据记录Python的pyserial库加openpyxl库可以轻松实现。这步做完这个项目就从“能转的课程设计”升级成了“有点工业味道的数据采集系统”看起来完整度直接上一个档次。很多老师看到这个会很加分。5.2 触摸屏与多组配方更接近真实产品如果还想再进一步可以把LCD1602换成TFT串口屏比如淘系的2.4寸USART HMI屏幕。串口屏的好处是界面可以自己设计能显示中文、趋势曲线、操作按钮直接通过串口和单片机通信代码量大减体验提升很多。同时可以在程序里增加配方功能。什么叫配方就是加工A物料时设定500g加工B物料时设定1000g一键切换不用每次重新按。程序里用一个二维数组存几组设定值按键切换配方号显示在屏幕上。这个功能对于真实的包装场景非常实用也不是很难实现。5.3 最后再分享一个我个人的心得体会这个项目做完我对单片机项目开发最大的体会是软件永远比硬件好调试硬件问题才是真正磨人的地方。写代码时遇到问题逻辑上理一理总能找到原因但硬件问题比如地线干扰、传感器漂移、接线松动往往要拿万用表、示波器一点一点测特别磨练耐心。所以如果你打算做这个项目我的建议是先把硬件搭建好不要急着写完整代码。先写一个最简单的“读HX711并显示在串口”的程序验证传感器、ADC、单片机的链路是通的再做显示、按键、电机控制最后把所有功能整合在一起。每增加一个功能测试一次不要一口气全写完再测否则出了问题根本不知道是哪里引起的。另外一个很实用的小技巧在开发调试阶段把HX711的原始读数、滤波后的读数、标定系数这些中间变量通过串口发出来观察。这样你就能实时看到数据从传感器到显示值的完整链路哪里出问题一目了然。调试到后期把这些调试输出注释掉就行。按这个思路做下来整个项目从零到跑通正常情况下一个月左右就能搞定我已经验证过很多次了。希望这篇内容能帮你少走一些弯路有具体问题欢迎在评论区交流。本文还有配套的精品资源点击获取