1. 项目缘起:为什么我们需要一台硬币分拣计数机?
如果你经营着一家小超市、一家奶茶店,或者家里有个存钱罐已经满到快溢出来了,那你一定对处理大量硬币这件事深有体会。弯腰捡拾、手动分类、一枚一枚地数,这个过程不仅枯燥乏味,而且极其容易出错。我自己的经历是,在帮朋友的社区便利店盘点时,面对两大袋混合着1角、5角、1元的硬币,我们三个人数了整整一个下午,结果三个人数出了三个不同的总数,最后不得不重新来过。这种低效和不确定性,正是催生“硬币分拣计数机”这个项目的直接动力。
本质上,这是一个典型的机电一体化项目,它融合了简单的机械结构、基础的传感器应用和直观的逻辑控制。它的目标非常明确:将一堆杂乱无章的混合硬币,自动、快速、准确地按面值分拣开来,并分别统计出每种面值的数量及总金额。对于个人爱好者,这是一个绝佳的练手项目,能系统性地学习从设计到落地的全过程;对于小型商户,它则是一个能切实提升效率、减少人力成本的实用工具。今天,我就来详细拆解如何从零开始,打造一台属于你自己的硬币分拣计数机。
2. 核心设计思路:物理特性是分拣的天然钥匙
在开始动手之前,我们必须想清楚:机器凭什么能区分不同面值的硬币?答案就藏在硬币本身的物理属性里。我们不需要复杂的图像识别(那会增加成本和复杂度),最朴素、最可靠的方法是利用硬币的直径、厚度和材质。对于常见的硬币,直径是最显著且稳定的区分特征。
我的设计思路是一种经典的“筛选轨道”方案。想象一条略有倾斜的轨道,硬币从顶端入口放入,在重力作用下开始滑行。轨道的宽度是精心设计的,它会从宽逐渐变窄。当一枚硬币滑行时,一旦轨道的宽度小于硬币的直径,硬币就会被“卡住”并从这个缺口掉落,进入其对应的收集槽。直径最小的硬币(例如1角)能滑行最远的距离,直到轨道最窄处才掉落;直径最大的硬币(例如1元)则在轨道较宽的前段就被筛选出来。
这个方案的魅力在于其“被动式”工作原理。它不依赖电机主动推动分拣,而是巧妙利用重力、轨道几何形状和硬币的物理尺寸,实现了完全自动化的筛选。结构简单,可靠性高,几乎没有需要维护的活动部件。接下来,我们就基于这个思路,展开具体的设计与实现。
2.1 关键参数测量与轨道设计
一切设计的基础是精确的数据。你需要手头所有待分拣硬币的样本,并使用游标卡尺进行多次测量,取平均值以确保准确。
以当前常见的硬币为例(请注意,你的硬币版本可能略有差异,务必以实测为准):
- 1角硬币:直径约19毫米,厚度约1.67毫米。
- 5角硬币:直径约20.5毫米,厚度约1.65毫米。
- 1元硬币:直径约25毫米,厚度约1.85毫米。
轨道的设计是核心中的核心。我建议采用分层或并列的滑道设计。这里以单滑道渐变宽度方案为例:
- 轨道基板:选择一块表面光滑的亚克力板或中密度纤维板,长度约60-70厘米,宽度8-10厘米。足够长的轨道能确保硬币有充分的滑行距离进行分离。
- 轨道侧壁:使用两条L型铝合金型材或木条,平行固定在基板两侧,构成滑槽。关键技巧在于:其中一侧的轨道侧壁是固定的,而另一侧则是可调节的,或者直接按照设计好的曲线轮廓来制作。
- 宽度渐变曲线:从轨道入口开始,可调节侧壁与固定侧壁的间距(即轨道宽度)应略大于最大硬币的直径(例如26毫米),让所有硬币都能顺利进入。随后,轨道宽度开始线性或阶梯式递减。
- 分拣缺口定位:根据硬币直径,在特定位置设置掉落缺口。
- 第一缺口(1元硬币):当轨道宽度收窄至约25.5毫米时,设置第一个缺口。1元硬币(直径25mm)会被卡住,在重力作用下从缺口掉落。这里有一个重要细节:缺口宽度应略大于硬币厚度但小于其直径,确保硬币是“侧翻”掉落而非平着滑出,这有利于精准落入下方收集盒。
- 第二缺口(5角硬币):轨道继续收窄,在宽度约20.8毫米处设置第二个缺口,用于筛选5角硬币。
- 末端收集(1角硬币):轨道最窄处宽度约19.5毫米,1角硬币将一路滑行至此,最终落入末端的收集槽。
注意:实际制作时,轨道宽度要比硬币直径大0.3-0.8毫米作为“公差裕量”。太紧容易卡币,太宽则会导致分拣不准确。最好的办法是制作一个可微调的侧壁,用实际硬币进行反复测试来最终确定最佳宽度。
2.2 计数方案选型:红外对管 vs. 微动开关
硬币分拣开后,我们需要知道每种面值各有多少枚。主流的计数方案有两种:红外光电传感器和微动开关。我强烈推荐使用红外对管,因为它属于非接触式检测,寿命极长,且反应速度快。
红外对管的工作原理:它由一个红外发射管和一个红外接收管组成,相对安装在硬币掉落路径的两侧。当没有硬币通过时,发射管发出的红外光被接收管正常接收,电路输出一个状态(如高电平)。当硬币掉落穿过光束时,光线被遮挡,接收管信号发生变化(变为低电平),控制器通过检测这个跳变信号来计数。
安装要点:
- 在每个硬币掉落缺口的下方,单独安装一对红外对管。
- 确保硬币掉落时能完全、稳定地遮挡光束。可以将传感器安装在一个小型“检测隧道”里,避免环境光干扰。
- 调整传感器灵敏度,防止因硬币晃动产生多次误计数。在代码中,通常需要加入“消抖”逻辑,即检测到一次遮挡后,忽略接下来几十毫秒内的信号变化。
微动开关方案虽然成本更低,但需要硬币物理撞击触发,长期使用存在机械磨损和疲劳问题,对于需要处理大量硬币的场景,可靠性不如红外方案。
3. 控制系统搭建:让机器拥有“大脑”
分拣是机械的智慧,计数和统计则需要一个电子大脑来协调。这里我们选择最常见的Arduino Uno作为主控制器,它足以胜任这个任务,生态丰富,学习资料多。
3.1 所需材料清单
- 主控板:Arduino Uno R3 x1
- 传感器:红外光电传感器(槽型/对射型) x3 (对应3种面值)
- 显示模块:LCD1602液晶屏(带I2C接口,节省接线) x1
- 电源:9V直流电源适配器(给Arduino供电)或12V电源(如需驱动电机,本项目不需要)
- 结构材料:亚克力板、木板、铝合金型材、螺丝螺母、硬币收集盒(可用塑料盒改制)。
- 其他:杜邦线、面包板(用于测试)、焊接工具、导线等。
3.2 电路连接详解
接线是项目从图纸走向现实的第一步,清晰的连接是成功的一半。
- 红外传感器连接:三个红外传感器(我们假设它们输出数字信号)的VCC引脚接Arduino的5V,GND引脚接GND。信号输出引脚(OUT)分别接Arduino的数字引脚2, 3, 4。
- LCD1602连接(I2C模块):这是最简洁的方式。I2C模块通常只有4个引脚:
- VCC-> Arduino 5V
- GND-> Arduino GND
- SDA-> Arduino A4引脚
- SCL-> Arduino A5引脚
提示:在焊接或接线前,务必先用面包板搭建测试电路,确保每个传感器、显示屏都能正常工作。我曾因为一个接触不良的接口,调试了整整半天。
3.3 核心代码逻辑与编写
代码是机器的灵魂。它的逻辑非常清晰:持续监听三个传感器的信号,一旦某个传感器被触发(检测到硬币掉落),就将其对应的硬币数量加1,并更新总金额,最后刷新屏幕显示。
#include <Wire.h> #include <LiquidCrystal_I2C.h> // 初始化LCD,I2C地址通常是0x27或0x3F,需根据你的模块调整 LiquidCrystal_I2C lcd(0x27, 16, 2); // 定义传感器引脚 const int sensor_1yuan = 2; // 1元传感器 const int sensor_5jiao = 3; // 5角传感器 const int sensor_1jiao = 4; // 1角传感器 // 定义硬币面值(单位:分,便于计算) const int VALUE_1YUAN = 100; const int VALUE_5JIAO = 50; const int VALUE_1JIAO = 10; // 计数变量 int count_1yuan = 0; int count_5jiao = 0; int count_1jiao = 0; long totalMoney = 0; // 总金额,单位:分 // 传感器状态变量,用于消抖 int lastState_1yuan = HIGH; int lastState_5jiao = HIGH; int lastState_1jiao = HIGH; unsigned long lastDebounceTime = 0; const unsigned long debounceDelay = 50; // 消抖延时50毫秒 void setup() { Serial.begin(9600); // 初始化传感器引脚为输入模式,并启用内部上拉电阻 pinMode(sensor_1yuan, INPUT_PULLUP); pinMode(sensor_5jiao, INPUT_PULLUP); pinMode(sensor_1jiao, INPUT_PULLUP); // 初始化LCD lcd.init(); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("Coin Counter"); lcd.setCursor(0, 1); lcd.print("Ready..."); delay(2000); lcd.clear(); updateDisplay(); // 显示初始状态 } void loop() { // 读取当前传感器状态(由于启用上拉,无遮挡时为HIGH,遮挡时为LOW) int currentState_1yuan = digitalRead(sensor_1yuan); int currentState_5jiao = digitalRead(sensor_5jiao); int currentState_1jiao = digitalRead(sensor_1jiao); // 检查1元传感器是否有下降沿(从HIGH到LOW)变化,并消抖 if (lastState_1yuan == HIGH && currentState_1yuan == LOW) { if ((millis() - lastDebounceTime) > debounceDelay) { count_1yuan++; totalMoney += VALUE_1YUAN; updateDisplay(); lastDebounceTime = millis(); } } lastState_1yuan = currentState_1yuan; // 检查5角传感器 if (lastState_5jiao == HIGH && currentState_5jiao == LOW) { if ((millis() - lastDebounceTime) > debounceDelay) { count_5jiao++; totalMoney += VALUE_5JIAO; updateDisplay(); lastDebounceTime = millis(); } } lastState_5jiao = currentState_5jiao; // 检查1角传感器 if (lastState_1jiao == HIGH && currentState_1jiao == LOW) { if ((millis() - lastDebounceTime) > debounceDelay) { count_1jiao++; totalMoney += VALUE_1JIAO; updateDisplay(); lastDebounceTime = millis(); } } lastState_1jiao = currentState_1jiao; } // 更新LCD显示的函数 void updateDisplay() { lcd.clear(); // 第一行:显示各面值数量 lcd.setCursor(0, 0); lcd.print("1Y:"); lcd.print(count_1yuan); lcd.print(" 5J:"); lcd.print(count_5jiao); lcd.print(" 1J:"); lcd.print(count_1jiao); // 第二行:显示总金额(转换为“元”为单位) lcd.setCursor(0, 1); lcd.print("Total: "); lcd.print(totalMoney / 100.0, 2); // 显示两位小数 lcd.print(" Y"); }代码关键点解析:
- 消抖处理:
debounceDelay变量和millis()函数的使用至关重要。硬币掉落时可能产生轻微振动,导致传感器信号在短时间内多次跳变。消抖逻辑确保一次掉落只计一次数。 - 内部上拉电阻:
INPUT_PULLUP模式激活了Arduino引脚内部的上拉电阻,这样传感器信号线在无遮挡时会被拉至高电平,简化了外部电路,提高了抗干扰能力。 - 金额计算:在程序内部,我选择以“分”作为基本单位进行整数运算(如1元=100分),避免了浮点数计算可能带来的精度问题。只在最后显示时才转换为“元”。
4. 机械结构组装与调试:从散件到整机
有了设计图、电路和代码,接下来就是最考验动手能力的组装环节。这个过程需要耐心和细致。
4.1 分拣轨道制作与校准
- 切割与打磨:根据设计尺寸,切割好基板和侧壁材料。所有边缘,特别是硬币滑行的轨道面,必须用砂纸打磨光滑,任何毛刺都可能导致硬币卡住。
- 固定与倾斜:将轨道基板固定在机箱的骨架上,并确保有一个合适的倾斜角度(大约10-15度)。角度太小硬币无法自行滑落,角度太大会导致硬币速度过快,可能飞出轨或干扰计数传感器。一个实用的调试方法是:用一枚5角硬币从顶端放下,它能平稳、匀速地滑完全程即为最佳。
- 安装分拣挡板:在计算好的缺口位置,安装用于引导硬币侧翻掉落的挡板。挡板的高度应略高于硬币的半径,确保硬币能被其“绊倒”落入收集盒,而不是挤过去。
4.2 传感器与收集系统集成
- 搭建检测隧道:在每个硬币掉落口的下方,用黑色亚克力板或塑料片搭建一个小型暗箱,将红外对管分别安装在两侧。黑色内壁可以有效吸收杂散光,防止环境光干扰传感器。确保硬币掉落路径正好穿过红外光束的中心。
- 固定收集盒:在传感器下方放置三个独立的盒子,用于收集不同面值的硬币。盒子最好有一定深度,或者在入口处加一个缓坡,防止硬币弹出。
- 整体走线与固定:将所有传感器的线缆用扎带整理好,沿着机箱内壁固定,避免线材缠绕或垂落到运动部件中。将Arduino板和LCD屏幕安装在机箱前部或顶部易于观察和操作的位置。
4.3 系统联调与常见问题排查
组装完成后,进入调试阶段。这是发现问题、优化性能的关键步骤。
- 上电测试:接通电源,观察LCD是否正常点亮,显示初始化信息。
- 分拣功能测试:务必使用真实、干净的硬币进行测试。先不要混合,而是分别投入不同面值的硬币,观察它们是否能准确地在预设缺口掉落。常见问题及解决:
- 问题:硬币卡在轨道中间。
- 排查:检查轨道宽度是否均匀,是否有局部凸起或毛刺。检查倾斜角度是否足够。
- 解决:打磨光滑轨道,适当增大倾斜角度。
- 问题:硬币分拣错误(如1元币掉入5角槽)。
- 排查:测量硬币直径是否与设计值有出入。检查缺口位置对应的轨道宽度是否准确。
- 解决:微调可动侧壁,缩小该缺口处的轨道宽度。
- 问题:硬币卡在轨道中间。
- 计数功能测试:让硬币逐个通过,观察LCD上的计数是否准确增加。常见问题及解决:
- 问题:漏计数。
- 排查:硬币是否没有完全遮挡红外光束?传感器安装位置是否太偏?传感器本身是否损坏?
- 解决:调整传感器位置,确保光束横穿硬币中心。用一张纸片测试传感器信号是否正常。
- 问题:一次掉落多次计数(连跳)。
- 排查:这是典型的“抖动”问题。硬币掉落时可能旋转或摆动,导致光束被断续遮挡。
- 解决:首要方法是优化代码中的消抖延时,将
debounceDelay从50毫秒适当增大,如80或100毫秒。其次,可以优化“检测隧道”的形状,使硬币掉落路径更稳定。
- 问题:漏计数。
- 压力与连续运行测试:模拟真实场景,连续投入一小批混合硬币(例如20-30枚),观察分拣和计数的整体准确率。目标是将准确率提升至99%以上。
5. 优化与扩展思路:让机器更聪明、更好用
基础功能实现后,你可以考虑以下优化,让这台机器变得更加强大和人性化。
5.1 硬件层面的优化
- 防堵塞与清洁设计:在轨道入口处增加一个振动器或一个小型风扇,帮助硬币平铺开并单列进入轨道,防止多枚硬币并排卡死入口。定期清洁轨道,防止灰尘和污垢影响滑行。
- 材料升级:将轨道接触面更换为摩擦系数更小的材料,如特氟龙胶带或超高分子量聚乙烯板,可以使硬币滑行更顺畅,减少卡顿。
- 增加预分拣筛网:在硬币进入主分拣轨道前,先经过一个带有标准圆孔的倾斜筛网。这个筛网可以筛除直径明显小于1角硬币的异物(如纽扣电池、小石子),保护后续的精分拣轨道。
5.2 软件与功能扩展
- 数据存储与重置:为Arduino增加一个实时时钟模块和SD卡模块。每次工作完成后,可以将日期、时间、各种硬币数量、总金额保存到CSV文件中,方便后期对账和统计。同时,可以设置一个物理按钮,长按后清零所有计数。
- 声光提示:增加一个蜂鸣器和LED指示灯。当计数达到预设值(如100枚),或完成一次批量处理时,发出提示音和灯光,提升交互体验。
- 网络功能(进阶):替换为ESP32等带Wi-Fi的开发板。机器可以将每笔计数数据通过Wi-Fi发送到本地服务器或云平台,你可以在手机或电脑上实时查看数据看板,实现远程管理。
- 容错机制:在代码中增加“异常通道”检测。例如,如果一枚硬币在轨道上停留时间过长(可能卡住),可以触发一个警报或尝试通过微型振动电机将其震落。
6. 项目总结与个人心得
回顾整个项目,从最初被一堆硬币困扰,到设计、制作、调试出一台能自动分拣计数的机器,这个过程充满了挑战,也收获了巨大的满足感。它不仅仅是一个工具,更是一次对问题定义、方案设计、动手实现和持续优化全流程的完整实践。
我个人的几点深刻体会是:第一,机械结构的可靠性优先于一切。电路和代码出了问题可以快速修改,但一个设计不良的机械结构会让整个项目推倒重来。在切割和组装每一个部件时,精度和光洁度必须放在首位。第二,调试阶段要有耐心,用数据说话。不要凭感觉调整轨道宽度或传感器位置,每一次调整后,都用至少10枚硬币做一次统计测试,记录成功率,找到最优解。第三,从最小可行产品开始。先实现最核心的分拣和计数功能,让它能跑起来。之后再考虑添加数据存储、网络等扩展功能。这能帮助你快速获得正反馈,避免项目半途而废。
这台自制的硬币分拣计数机,虽然外观可能不如工业产品精致,但它的准确率和效率已经足以应对日常小店和家庭的需求。更重要的是,通过亲手打造它,你获得的对机电系统设计的理解,是任何现成产品都无法给予的。如果你也正被堆积如山的硬币所困扰,不妨就从测量手边的那枚硬币开始,踏上这个有趣的创造之旅吧。