1. 项目概述从“挤洗洁精”到智能化的第一步每次洗碗你是不是也烦透了那个黏糊糊的洗洁精瓶子要么按半天不出要么“噗嗤”一下挤出一大滩用量完全凭手感不仅浪费瓶口还总是油腻腻的。这个看似不起眼的生活痛点恰恰是动手改造的绝佳起点。今天要聊的就是一个基于树莓派 Pico 的自动洗洁精分配器项目。它远不止是“按一下出一点”那么简单而是一个融合了传感器感知、微控制器决策和电机精准控制的完整嵌入式系统原型。这个项目的核心价值在于它用一个非常生活化的场景串联起了嵌入式开发中几个最基础、最关键的模块微控制器编程Python、数字信号输入超声波传感器 HC-SR04、以及功率驱动输出电机驱动模块。无论你是刚接触树莓派 Pico 和 MicroPython 的新手想找个有趣的项目练手还是有一定经验的开发者希望深入理解传感器时序控制和电机 PWM 调速的细节这个项目都能提供一条清晰的学习路径。最终你将得到一个能通过检测手部距离自动定量挤出洗洁精的智能装置把日复一日的琐事变得有点酷。2. 核心硬件选型与电路设计思路为什么是这些零件这绝不是随便抓几个模块拼在一起。每个元件的选择背后都对应着要解决的具体问题并直接决定了系统的稳定性、成本和可实现性。2.1 控制核心为什么是树莓派 Pico在众多微控制器中选择树莓派 PicoRP2040作为大脑是基于多重考量。首先极低的入门门槛是关键。Pico 官方支持 MicroPython这意味着你可以用熟悉的 Python 语法快速实现逻辑无需面对传统嵌入式开发中复杂的 C 语言环境配置、寄存器操作和编译流程。对于快速原型验证和初学者来说这大大降低了心理和技术壁垒。其次充足的 GPIO 和硬件资源。RP2040 芯片提供了 26 个多功能 GPIO 引脚足以轻松连接传感器、电机驱动并留有扩展余地。其硬件 PWM 通道多达 16 个这对于需要平滑控制电机速度的场景至关重要。相比一些更简单的单片机Pico 的性能双核 Arm Cortex-M0133MHz足以流畅处理超声波测距、状态判断和电机控制等任务不会出现卡顿。最后是强大的社区和生态。Pico 拥有庞大的用户群和丰富的教程、库文件支持。遇到任何问题几乎都能在社区找到解决方案。综合来看Pico 在易用性、性能、扩展性和学习资源上取得了最佳平衡是此类创意项目的不二之选。2.2 感知单元HC-SR04 超声波模块的工作原理与局限HC-SR04 是本项目的“眼睛”负责检测手是否靠近以及距离。其工作原理是典型的“发射-接收-计时”控制端给 Trig 引脚一个至少 10us 的高电平脉冲模块会自动发射 8 个 40kHz 的超声波脉冲并开始计时。当接收到回波时Echo 引脚会输出一个高电平其持续时间与距离成正比。我们通过测量 Echo 高电平的时间t单位微秒代入公式距离 (t * 0.0343) / 2单位厘米即可算出距离。注意HC-SR04 的测量精度容易受环境因素干扰。光滑的碗碟表面、泡沫、甚至是空气流动都可能影响回波导致读数跳动。在实际部署时不能只依赖单次读数做判断必须进行软件滤波。常见的做法是连续采样 5-10 次去掉最大最小值后取平均或者使用中值滤波才能得到一个相对稳定的距离值。这是保证触发可靠性的关键一步否则会出现“手还没到就乱喷”或者“手到了没反应”的尴尬情况。2.3 执行机构电机驱动模块的选型与电路连接洗洁精瓶的按压动作需要一定的推力通常我们会选择一款微型直流减速电机并通过螺杆或凸轮结构将旋转运动转化为直线按压。而微控制器的 GPIO 引脚驱动能力极弱通常只有几毫安根本无法直接驱动电机因此必须借助电机驱动模块。L298N vs. TB6612FNG如何选择这是两个最常用的直流电机驱动芯片。它们的核心区别决定了你的选择L298N经典、皮实、易得。但它采用的是双极型晶体管BJT作为开关元件其饱和压降较大通常1.5V-2.5V这意味着在电机工作时芯片本身会消耗较多功率并发热严重效率较低。它需要外接散热片且逻辑电源和电机电源最好隔离。TB6612FNG更现代的选择。它使用 MOSFET 作为开关元件导通内阻极低因此功耗和发热都远小于 L298N效率高体积也更小巧。它还集成了待机STBY控制安全性更好。对于本项目驱动的微型电机电流通常不会超过 1A。从效率、发热和体积综合考虑TB6612FNG 是更优的选择。它能让你的装置更紧凑电池续航更久且不用担心过热问题。电路连接要点电源隔离务必为驱动模块提供独立的、功率足够的电源如 3节AA电池或锂电池。严禁使用 Pico 的 USB 或 VSYS 引脚为电机供电电机启动和堵转时的大电流会严重干扰微控制器导致复位或损坏。共地将驱动模块的电源地GND与 Pico 的 GND 可靠连接这是所有信号电平参考的基础。信号连接将 Pico 的 GPIO 连接到驱动模块的控制引脚如 TB6612 的 AIN1, AIN2, PWMA。PWM 引脚用于控制电机速度实现“慢按快回”等效果。续流二极管高质量的驱动模块如 TB6612内部已集成。如果自行搭建 H 桥电路必须在电机两端反向并联续流二极管以吸收电机线圈断电时产生的反向电动势保护驱动管。3. 软件架构与核心代码实现解析硬件是骨架软件才是灵魂。整个系统的逻辑流程可以概括为循环监测距离 - 判断触发条件 - 驱动电机动作。下面我们拆解关键部分的代码实现。3.1 超声波测距的稳健实现直接读取 Echo 引脚高电平时间的方法在 MicroPython 中容易受其他中断或任务影响。更稳健的方法是使用machine.time_pulse_us()函数它专门用于测量脉冲宽度。import machine import utime # 引脚定义 trig machine.Pin(2, machine.Pin.OUT) echo machine.Pin(3, machine.Pin.IN) def measure_distance(): # 确保 Trig 先拉低 trig.low() utime.sleep_us(2) # 发出 10us 的触发脉冲 trig.high() utime.sleep_us(10) trig.low() # 测量 Echo 高电平持续时间超时设为 30000us (约5米) pulse_time machine.time_pulse_us(echo, 1, 30000) # 计算距离 (单位厘米) # 声速 343 m/s 0.0343 cm/us 来回距离所以要除以2 distance (pulse_time * 0.0343) / 2 return distance # 滤波函数示例中值滤波 def get_filtered_distance(sample_size5): samples [] for _ in range(sample_size): dist measure_distance() if 2 dist 30: # 只采集有效范围内的样本 samples.append(dist) utime.sleep_ms(10) # 每次测量间隔一小会儿 if not samples: return None samples.sort() return samples[len(samples)//2] # 返回中值实操心得machine.time_pulse_us()在脉冲到来前会阻塞程序。如果传感器故障或超出量程未返回信号函数会一直等待直到超时。因此务必设置一个合理的超时参数如 30000 us。同时在循环中调用测距函数时要加入适当的延时如utime.sleep_ms(50)避免给传感器带来过高的负载也能让 CPU 有机会处理其他任务。3.2 状态机设计让逻辑清晰可控如果只是简单地“距离小于阈值就启动电机”系统会非常脆弱且难以管理比如手一直放在下面怎么办。引入一个简单的状态机是让程序逻辑变得清晰、健壮的最佳实践。我们可以定义几个状态IDLE空闲等待手靠近。TRIGGERED已触发检测到手进入预设范围准备启动电机。DISPENSING挤出中电机正在正向旋转挤出洗洁精。RETRACTING回位中电机反向旋转让压杆复位。COOLDOWN冷却一次完整动作后进入短暂休眠防止连续误触发。class DispenserStateMachine: def __init__(self): self.state IDLE self.last_trigger_time 0 self.dispense_duration 1000 # 挤出持续时间 ms self.retract_duration 800 # 回位持续时间 ms self.cooldown_period 2000 # 冷却时间 ms self.trigger_distance 10 # 触发距离 cm def update(self, current_distance): now utime.ticks_ms() if self.state IDLE: if current_distance is not None and current_distance self.trigger_distance: self.state TRIGGERED self.last_trigger_time now print(手部检测准备挤出) elif self.state TRIGGERED: # 可以在这里加入一个防抖延时确认手稳定停留 if utime.ticks_diff(now, self.last_trigger_time) 200: self.state DISPENSING self.start_dispense() elif self.state DISPENSING: if utime.ticks_diff(now, self.last_trigger_time) self.dispense_duration: self.state RETRACTING self.start_retract() self.last_trigger_time now # ... 其他状态判断使用状态机后每个状态该做什么、何时转换都非常明确便于调试和扩展功能比如增加双击出量、长按持续出等。3.3 电机 PWM 调速与动作控制为了让按压动作更柔和、更像人手而不是生硬的“撞上去”我们需要使用 PWM 来控制电机的速度。通常可以设计为启动时缓慢加速中间匀速按压返回时快速复位。from machine import Pin, PWM # 假设使用 TB6612连接 Pico 的 GP6, GP7, GP8 ain1 Pin(6, Pin.OUT) ain2 Pin(7, Pin.OUT) pwma PWM(Pin(8)) pwma.freq(1000) # 设置 PWM 频率为 1kHz def motor_stop(): ain1.low() ain2.low() pwma.duty_u16(0) # 占空比设为0 def motor_dispense(speed_percent80): 正向转动挤出洗洁精 ain1.high() ain2.low() # duty_u16 范围 0-65535, 对应 0%-100% pwma.duty_u16(int(65535 * speed_percent / 100)) def motor_retract(speed_percent100): 反向转动快速复位 ain1.low() ain2.high() pwma.duty_u16(int(65535 * speed_percent / 100)) # 一个带软启动的挤出函数示例 def smooth_dispense(): for duty in range(0, 40000, 2000): # 缓慢加速 pwma.duty_u16(duty) utime.sleep_ms(20) pwma.duty_u16(50000) # 保持匀速 utime.sleep_ms(800) for duty in range(50000, 0, -5000): # 减速停止 pwma.duty_u16(duty) utime.sleep_ms(20) motor_stop()通过调整speed_percent和duty_u16的值你可以精确控制按压的力度和速度找到既能挤出足够洗洁精又不会溅得到处都是的最佳参数。切记电机从高速到停止时不要直接切断 PWM 而是应逐步降低占空比否则可能会因为惯性对机械结构造成冲击。4. 机械结构设计与组装要点电子部分工作正常后如何将电机的旋转转化为对瓶子的稳定按压是项目成功落地的最后一道关卡。这里有几个经过验证的设计思路和避坑指南。4.1 传动方案对比螺杆 vs. 凸轮 vs. 连杆螺杆传动这是最直观、最精准的方案。用一个螺母套在螺杆上电机带动螺杆旋转螺母就做直线运动。优点是推力大、行程精确、自锁性好断电后位置保持。缺点是速度较慢需要购买或加工螺杆/螺母组件成本稍高。凸轮传动结构简单。电机带动一个偏心轮凸轮推动一个滑块或压杆做往复运动。优点是结构紧凑、动作快。缺点是推力较小且压杆的行程和力度是固定的由凸轮形状决定不易调节。连杆/曲柄滑块机构类似火车轮子的传动方式。可以将电机的旋转通过一个连杆转化为近似直线的按压。DIY 乐趣高但设计计算稍复杂运动轨迹未必是纯直线。对于洗洁精分配器我强烈推荐螺杆传动方案。因为它能提供稳定、可控的直线推力并且通过控制电机的旋转圈数可以精确控制挤出的量例如旋转2圈出1ml这是其他方案难以实现的。你可以在网上购买现成的“直线滑台模组”它通常集成了螺杆、螺母、导轨和滑块虽然成本高一些但省去了大量调试和加工的麻烦可靠性极佳。4.2 固定与对齐稳定性的基石整个装置的稳定性90%取决于固定是否牢靠。你需要考虑几个固定点Pico 和驱动板的固定使用尼龙柱和螺丝将它们固定在一块亚克力板或塑料底板上。避免只用双面胶电机震动迟早会让它脱落。电机的固定微型直流电机通常有安装孔。务必使用螺丝将其牢牢固定在底座或支架上。电机空转时可能感觉震动不大但一旦带上负载开始按压瓶子松动的电机会产生巨大的噪音和位移。传动机构与瓶子的对齐这是最关键的步骤。压杆或螺母的运动中心线必须与洗洁精按压头的中心线严格对齐。哪怕只有一两毫米的偏差在多次按压后也会导致机构卡死、磨损或者瓶子被推歪。在组装时可以使用直角尺或激光水平仪辅助对齐。一个技巧是先手动将压杆推到按压位置然后调整整个机构或瓶子的位置确保对正后再紧固所有螺丝。4.3 瓶身适配与按压头改造市面上的洗洁精瓶按压头千差万别。你需要针对你的瓶子进行改造。方案A无损设计一个“卡箍”或“抱箍”式的结构将整个分配器固定在瓶身上。按压杆的末端做一个柔软的硅胶头或小滚轮直接去压原装的按压头。优点是无需破坏瓶子通用性强。缺点是对机械结构的刚性和对齐要求更高。方案B改造直接将原装按压头拆掉用一根软管如硅胶管一端插入瓶口的吸管另一端接到一个由你的压杆控制的微型泵或注射器结构上。通过推动注射器活塞来挤出液体。这种方式出量更精确且不受原装按压头弹簧力度的影响但改造工作量较大。注意事项无论哪种方案请务必在正式安装前进行长时间的空载和负载测试。空载测试不装瓶子检查电机、传动是否顺畅。负载测试装上水或稀释的洗洁精检查推力是否足够出液是否流畅并校准出液量。测试时密切观察电机和驱动芯片的温升如果烫手说明电流过大需要检查是否有机械卡阻或者考虑降低 PWM 占空比速度。5. 系统集成、调试与功能优化当硬件组装完毕代码也准备就绪就到了最激动人心也最考验耐心的系统集成与调试阶段。这一步的目标是让所有部分协同工作稳定可靠。5.1 上电顺序与电源管理一个良好的上电习惯能避免很多灵异问题。建议顺序如下首先确保所有控制信号线GPIO连接线已正确连接。然后为电机驱动模块接上独立的电池电源。最后再通过 USB 线为树莓派 Pico上电。为什么如果先给 Pico 上电而电机驱动电源未接或电压不稳Pico 的 GPIO 引脚可能处于不确定状态浮空万一输出一个高电平可能导致驱动模块瞬间导通电机“抽搐”一下。虽然不一定会损坏但不是一个好实践。关于电源如果你的电机工作电流较大500mA强烈建议为 Pico 和驱动模块使用两套独立的电池组并通过一个共地连接。如果必须使用同一电源务必选择一个能提供持续2A以上电流的优质适配器或电池并在电源入口处并联一个大电容如 1000uF来缓冲电机启停造成的电压波动。5.2 调试技巧从“不动”到“稳定工作”电机不转遵循“由简到繁”的排查原则第一步硬件分离。断开电机与驱动板的连接用万用表测量驱动板输出端电压。在代码中控制电机正反转看输出电压是否正常变化。这可以排除电机本身故障。第二步信号追踪。使用逻辑分析仪或一个简单的 LED电阻连接到 Pico 的 PWM 输出引脚观察在电机应该动作时LED 是否闪烁。这可以验证代码逻辑和 GPIO 配置是否正确。第三步电源检查。测量电机驱动板的电源输入电压在电机启动瞬间电压是否被拉低过多如从5V掉到4V以下。如果是说明电源带载能力不足。超声波读数乱跳物理隔离确保传感器探头前方没有障碍物并且安装稳固没有震动。软件滤波如前所述务必实现中值滤波或均值滤波。这是解决跳数的根本软件手段。供电干扰尝试为 HC-SR04 模块的 VCC 引脚并联一个 10uF 和 0.1uF 的电容滤除电源噪声。触发间隔确保两次测量之间至少有 60ms 的间隔。HC-SR04 模块需要时间处理上一次的回波。出液量不准机械回差螺杆传动机构可能存在“回差”即电机反转初期螺母可能不会立即反向运动。解决方法是在每次挤出动作完成后让电机多反转一点点例如多转 5 度确保压杆完全离开瓶盖下次动作时从真正的“零点”开始。瓶子内压变化随着洗洁精减少瓶内气压会变负导致越往后挤越费力出液越少。可以在瓶盖上钻一个非常小的通气孔或用针扎一下原装吸管上的进气口平衡内外气压。注意孔要小防止漏液。5.3 功能扩展与优化思路基础功能稳定后你可以考虑加入更多智能元素定量出液利用 Pico 的 ADC模数转换器引脚连接一个流量传感器如霍尔水流传感器实现真正按毫升出液。或者通过精确控制电机旋转圈数步进电机更适合来间接定量。多种清洁模式通过增加一个按钮或触摸传感器实现“单次轻按出少量”、“双击出标准量”、“长按持续出”等多种模式。低液量提醒在瓶底或侧面安装一个红外对管或超声波传感器监测液面高度当低于阈值时让 Pico 板载 LED 闪烁报警。无线控制与统计为 Pico 增加一个蓝牙模块如 HC-05或 WiFi 模块如 ESP-01S通过手机 App 远程控制、设置出液量甚至统计使用次数估算剩余量。这个自动洗洁精分配器项目就像一把钥匙为你打开了嵌入式开发与智能硬件的大门。从读懂传感器数据到驱动外部执行器再到处理现实世界中的机械和可靠性问题你走过的每一步都充满了挑战和收获。它教会你的不仅仅是几行 Python 代码或如何连接导线更重要的是一种系统化的工程思维如何定义问题、分解模块、选择方案、集成调试。当你看到自己亲手制作的装置稳稳地、准确地为你挤出一份洗洁精时那种成就感远非购买一个成品所能比拟。动手去实现吧下一个让你生活更便利的创意或许就诞生在你的工作台上。