当前位置: 首页 > news >正文

基于行空板与二哈识图的智能番茄钟盆栽制作指南

1. 项目概述:当桌面盆栽遇上番茄工作法

最近在捣鼓行空板,总想着用它做点既实用又有趣的小玩意儿。手边正好有个闲置的绿植盆栽,灵光一闪,为什么不把“番茄工作法”这个时间管理神器,和这个有生命力的桌面摆件结合起来呢?于是,“桌面番茄钟盆栽”这个想法就诞生了。它的核心很简单:一个能帮你专注工作25分钟、然后强制休息5分钟的智能计时器,但它的载体不是冰冷的手机App或塑料闹钟,而是一个会“呼吸”、能交互的盆栽。当你在专注时,盆栽的灯光会柔和地变化,提醒你时间在流逝;休息时间到,它会用更明显的方式“呼唤”你,让你离开屏幕,看看绿植,放松眼睛和大脑。更有趣的是,我加入了二哈识图(HuskyLens)这款AI视觉传感器,让它能识别一些简单的物体或手势,实现非接触式的控制,比如挥挥手就能开始下一个番茄钟,科技感和仪式感直接拉满。这个项目非常适合对物联网、MicroPython编程和AI应用感兴趣的创客朋友,无论你是想学习传感器集成,还是单纯想做一个提升幸福感的小工具,都能从中找到乐趣。

2. 核心思路与硬件选型解析

2.1 为什么是“番茄钟+盆栽”?

番茄工作法的精髓在于“专注”与“休息”的节奏化。然而,手机或电脑上的计时器很容易被其他通知干扰,或者因为太容易关闭而失去约束力。一个独立的物理设备,能创造更强的仪式感和边界感。选择盆栽作为载体,则引入了“自然”和“生长”的隐喻。绿植本身能舒缓压力,将其与计时功能结合,相当于给你的专注时间赋予了一个“生命体”见证者。从技术实现角度看,盆栽内部有空间容纳电路,土壤可以隐藏线缆,植物本身也能与灯光、雾气等效果联动,提供了丰富的感官反馈维度,比一个单纯的盒子更有创意和温度。

2.2 硬件核心三件套:行空板、二哈识图与外围模块

这个项目的硬件骨架清晰,主要围绕三块核心搭建:

  1. 行空板:我选择行空板作为主控,而不是常见的Arduino或树莓派Pico,主要看中它“开箱即用”的易用性。它集成了屏幕、Wi-Fi、蓝牙、多种传感器和丰富的扩展接口,省去了大量硬件连接和驱动调试的麻烦。其内置的Python环境(兼容MicroPython)对初学者非常友好,让我们可以更专注于功能逻辑,而非底层硬件调试。对于这个需要处理UI显示、网络时间同步(可选)和复杂传感器交互的项目,行空板的综合能力非常合适。

  2. 二哈识图(HuskyLens):这是一款“傻瓜式”的AI视觉传感器。它最大的优点是将复杂的图像识别算法固化在硬件里,我们通过简单的UART或I2C指令就能调用人脸识别、物体追踪、颜色识别、标签识别等功能。在这个项目里,我主要用它实现两种交互:

    • 手势控制:识别“手掌”或特定的手势(如OK手势),作为开始/暂停番茄钟的触发信号。
    • 物体识别:可以学习并识别一个特定的物体(比如一个放在桌面的小摆件),当把这个物体拿到摄像头前,就触发休息模式。这增加了项目的可玩性和个性化。 选择二哈,避免了在行空板上部署OpenCV等视觉库的复杂性和性能压力,让AI交互变得轻量而稳定。
  3. 外围反馈模块

    • RGB LED灯带/灯环:用于视觉反馈。我将灯带缠绕在盆栽内壁或花盆边缘。工作时,灯光可以是缓慢变化的呼吸灯(如从蓝到浅蓝),表示时间平稳流逝;休息时,灯光可以变为舒缓的绿色并闪烁,或呈现彩虹渐变,营造放松氛围。
    • 微型水泵与雾化器(可选进阶功能):如果盆栽是真植物,可以增加一个由继电器控制的小水泵,在休息时间自动浇水几秒;或者增加一个雾化片模块,在长时间工作后(比如完成4个番茄钟)制造一点水雾,增加趣味性。注意:此部分涉及水电,务必做好绝缘防水,建议新手先从纯灯光版本开始。
    • 蜂鸣器或微型扬声器:用于声音提示。工作开始、结束,或休息时间到,可以用不同的提示音效。行空板本身有扬声器,可以直接利用。

2.3 系统工作流程设计

整个系统的运行逻辑是一个状态机,清晰定义了不同状态下的设备行为:

  1. 待机状态:盆栽灯光处于低亮度待机色(如暖黄色)。屏幕显示待机界面(当前时间、植物表情等)。
  2. 启动识别:用户做出预设手势(如对着二哈摄像头比“OK”),二哈识别后通过串口发送指令给行空板。
  3. 工作状态(25分钟):行空板收到指令,进入工作倒计时。灯光切换为“工作模式”(如蓝色呼吸)。屏幕显示大大的倒计时和“专注中”。开始播放一段白噪音或环境音(可选)。
  4. 休息状态(5分钟):25分钟倒计时结束,自动切换。灯光变为“休息模式”(如绿色闪烁或彩虹渐变)。屏幕显示“休息一下”,并提示可以活动身体、看看远方。蜂鸣器播放愉悦的提示音。
  5. 循环与重置:休息时间结束后,系统自动返回待机状态,等待下一次手势启动。也可以通过识别特定物体(如“休息令牌”)提前结束工作或进入长休息。

3. 硬件连接与软件环境搭建

3.1 硬件接线图与要点

硬件连接并不复杂,关键在于给各个模块稳定供电和正确连接数据线。下图展示了核心的连接关系:

[行空板] | |-- (I2C 或 UART) --> [二哈识图传感器] // 用于发送识别指令和接收结果 | |-- (GPIO 或 专用接口) --> [RGB LED灯带] // 如WS2812B,只需一个数据线 | |-- (内部) --> [扬声器/屏幕] // 行空板内置,无需额外连接 | |-- (USB 5V) --> [供电] // 为整个系统供电,注意电流需求

具体接线步骤与注意事项:

  1. 二哈识图连接:这是最关键的一步。二哈识图支持UART和I2C两种通信方式。我推荐使用I2C,因为行空板的I2C接口更稳定,且可以并联多个设备(虽然本项目只有一个)。将二哈的GND、VCC、SDA、SCL分别连接到行空板的GND、3.3V/5V(注意二哈的电压要求)、I2C的SDA和SCL引脚。务必在行空板设置中开启I2C功能
  2. RGB LED灯带连接:WS2812B灯带只需连接三根线:VCC(+5V)、GND、DIN(数据输入)。将DIN连接到行空板的一个GPIO口(如P21),并在代码中为该GPIO口设置一个上拉电阻(软件设置即可),以提高信号稳定性。如果灯带较长(超过30颗灯珠),建议在VCC和GND之间并联一个470μF以上的电容,靠近灯带接入端,以防止上电时的电流冲击导致行空板重启。
  3. 供电考量:行空板通过USB供电,通常足够带动板子本身、二哈和一小段灯带。如果灯带很长(灯珠多),或者连接了水泵等大电流设备,务必使用外部5V电源单独为灯带或电机供电,并共地。避免因电流不足导致行空板运行不稳定或损坏。

注意:所有杜邦线连接处,最好使用热熔胶或电工胶带进行固定,防止因桌面震动导致接触不良。接线完成后,务必再三检查VCC和GND是否接反,接反必烧模块。

3.2 行空板软件环境准备

行空板默认搭载了基于Python的交互环境,我们需要进行一些初始化设置和库安装。

  1. 连接与初始化:通过USB线连接行空板至电脑,按照官方指南配置Wi-Fi,使其和你的电脑处于同一局域网。通过浏览器访问行空板的IP地址,进入Web编程界面。
  2. 安装必要库:行空板的Python环境已经内置了很多库,但我们还需要管理WS2812B灯带的库。在行空板的“应用商店”或通过终端使用upip安装。通常,neopixel库是控制WS2812B的标准选择。在行空板终端中,可以尝试upip install neopixel进行安装。
  3. 配置I2C:在行空板的“设置”或“硬件”菜单中,找到I2C选项并启用它。系统通常会分配好SDA和SCL的引脚,记住这些引脚编号,后续代码中会用到。
  4. 二哈识图固件与配置:确保二哈识图传感器固件是最新的(可通过官方工具升级)。首次使用时,需要通过二哈上的按钮和屏幕,将其通信协议设置为“I2C”模式,并记下它的I2C设备地址(默认是0x32)。

4. 核心代码实现与分步解析

项目的软件逻辑是核心,我们将分模块构建。这里假设你已经熟悉行空板的基本编程和文件管理。

4.1 二哈识图驱动与手势识别

首先,我们需要一个与二哈识图通信的类。行空板没有专用的HuskyLens库,但我们可以通过machine库的I2C功能直接与其通信,协议是公开的。

# huskylens_i2c.py import time from machine import I2C, Pin class HuskyLens: def __init__(self, i2c_bus=1, i2c_addr=0x32): # 初始化I2C,行空板的硬件I2C(1)引脚是固定的,通常是 SDA=6, SCL=7,请根据实际板卡说明确认 self.i2c = I2C(i2c_bus, scl=Pin(7), sda=Pin(6), freq=100000) self.addr = i2c_addr self._algorithm = 0 # 默认算法 def _write_to_husky(self, cmd, p1=0, p2=0, p3=0, p4=0): # 根据二哈协议封装命令 data = bytearray([0x55, 0xAA, 0x11, cmd, p1, p2, p3, p4]) checksum = (0x55+0xAA+0x11+cmd+p1+p2+p3+p4) & 0xFF data.append(checksum) try: self.i2c.writeto(self.addr, data) time.sleep(0.1) except Exception as e: print(f"Write error: {e}") def _read_from_husky(self): # 读取二哈返回的数据 try: data = self.i2c.readfrom(self.addr, 10) # 读取足够长度的数据 if len(data) >= 5 and data[0] == 0x55 and data[1] == 0xAA: # 简单的头部校验 return data except Exception as e: print(f"Read error: {e}") return None def set_algorithm(self, algo): """设置识别算法: 0=人脸, 1=物体追踪, 2=物体识别, 3=颜色识别, 4=标签识别, 5=线条追踪, 6=分类识别""" self._algorithm = algo self._write_to_husky(0x2D, algo, 0x00, 0x00, 0x00) time.sleep(0.5) # 给传感器切换算法的时间 def get_blocks(self): """获取识别到的结果块""" self._write_to_husky(0x21, 0x00, 0x00, 0x00, 0x00) data = self._read_from_husky() blocks = [] if data and len(data) >= 7: num_blocks = data[5] # 第6个字节是块数量 if num_blocks > 0: # 简化解析,实际应根据协议完整解析坐标、ID等信息 # 这里假设我们只关心有没有识别到东西 blocks.append({'id': data[6], 'count': num_blocks}) return blocks # 手势识别逻辑封装 def check_start_gesture(husky): """检查是否为开始手势(例如,识别到特定ID的物体或人脸)""" husky.set_algorithm(1) # 切换到物体追踪算法 blocks = husky.get_blocks() # 假设我们之前已经让二哈学习了一个“开始令牌”物体,其ID为1 for block in blocks: if block.get('id') == 1: # 识别到ID为1的物体 return True return False

关键点解析

  • 协议对接:二哈识图有固定的命令帧格式(以0x55AA开头),我们需要按照其文档封装读写函数。上述代码是一个极简化的示例,实际应用中需要根据协议文档完整解析返回数据中的坐标、大小、ID等信息。
  • 算法切换:在检查不同功能前,必须用set_algorithm切换到对应的模式。比如,手势识别可能用“物体追踪”或“分类识别”(如果你训练了手势模型)。
  • 学习功能:二哈的“物体识别”模式需要先“学习”。在代码运行前,你需要手动按下二哈上的学习键,让它对着你的手势或特定物体学习,并分配一个ID。这个ID就是代码中判断的依据。

4.2 番茄钟状态机与灯光控制

接下来是主程序,它管理番茄钟的状态、计时和灯光效果。

# main.py import time import _thread from huskylens_i2c import HuskyLens, check_start_gesture from neopixel import NeoPixel from machine import Pin # 常量定义 WORK_DURATION = 25 * 60 # 25分钟,单位秒 BREAK_DURATION = 5 * 60 # 5分钟,单位秒 LED_PIN = 21 LED_NUM = 16 # 灯珠数量 # 初始化 husky = HuskyLens() np = NeoPixel(Pin(LED_PIN, Pin.OUT), LED_NUM) state = "IDLE" # 状态: IDLE, WORK, BREAK remaining_time = 0 timer_thread_running = False def led_effect_idle(): """待机效果:暖黄色呼吸灯""" for i in range(LED_NUM): np[i] = (30, 15, 0) # 暖黄色 np.write() def led_effect_work(progress): """工作效果:蓝色呼吸,progress是0-1的进度""" import math brightness = int(50 + 50 * math.sin(progress * 2 * math.pi)) # 正弦波变化 color = (0, 0, brightness) # 蓝色 for i in range(LED_NUM): np[i] = color np.write() def led_effect_break(): """休息效果:绿色渐变闪烁""" for i in range(LED_NUM): np[i] = (0, 50, 0) np.write() time.sleep(0.5) for i in range(LED_NUM): np[i] = (0, 10, 0) np.write() time.sleep(0.5) def timer_countdown(): """倒计时线程函数""" global state, remaining_time, timer_thread_running while timer_thread_running and remaining_time > 0: time.sleep(1) remaining_time -= 1 # 更新屏幕显示(此处省略屏幕代码) print(f"State: {state}, Time left: {remaining_time}s") if state == "WORK": progress = 1 - (remaining_time / WORK_DURATION) led_effect_work(progress) elif state == "BREAK": # 休息时灯光效果独立循环 pass # 倒计时结束 if remaining_time <= 0: if state == "WORK": switch_to_break() elif state == "BREAK": switch_to_idle() def switch_to_work(): global state, remaining_time, timer_thread_running state = "WORK" remaining_time = WORK_DURATION print("切换到工作状态!") # 启动倒计时线程 if not timer_thread_running: timer_thread_running = True _thread.start_new_thread(timer_countdown, ()) def switch_to_break(): global state, remaining_time state = "BREAK" remaining_time = BREAK_DURATION print("切换到休息状态!") # 休息状态灯光效果在主循环中控制 def switch_to_idle(): global state, timer_thread_running state = "IDLE" timer_thread_running = False print("返回待机状态。") led_effect_idle() # 主循环 led_effect_idle() # 启动时待机 print("番茄钟盆栽已启动,等待手势...") while True: if state == "IDLE": # 检查手势,开始工作 if check_start_gesture(husky): print("检测到开始手势!") switch_to_work() time.sleep(2) # 防抖,避免连续触发 elif state == "BREAK": # 休息状态,灯光闪烁 led_effect_break() # 休息期间也可以检测手势提前结束休息(可选) # if check_stop_gesture(husky): # switch_to_idle() time.sleep(0.1) # 主循环延迟,降低CPU占用

代码逻辑精讲

  • 状态机模式:使用state变量清晰划分IDLE、WORK、BREAK三种状态,每个状态有对应的入口、出口动作和循环行为。这是嵌入式系统常见的编程模式,逻辑清晰,易于维护和扩展。
  • 多线程计时:倒计时timer_countdown在一个独立的线程中运行,这样主循环可以继续响应传感器输入(如手势)而不被阻塞。行空板的_thread模块提供了基本的线程支持。注意:多线程共享变量(如remaining_time)时,在复杂场景下需要考虑锁机制,本例中因为只有一个写线程,暂时安全。
  • 灯光算法led_effect_work函数根据工作进度计算灯光亮度,使用了正弦函数模拟呼吸效果。progress从0到1,对应正弦波的一个周期,使得灯光变化平滑自然。你可以调整函数内的参数来改变颜色和动态效果。

4.3 行空板屏幕UI界面优化

行空板的屏幕是其一大优势,我们可以用unihiker库(行空板自带GUI库)来显示更友好的界面。

# 在主程序中集成屏幕显示 from unihiker import GUI gui = GUI() # 创建UI元素 time_label = gui.draw_text(x=120, y=80, text="25:00", font_size=80, color="#000000") state_label = gui.draw_text(x=120, y=180, text="准备就绪", font_size=30, color="#666666") hint_label = gui.draw_text(x=120, y=230, text="做出手势开始专注", font_size=20, color="#999999") def update_display(state, minutes, seconds): """更新屏幕显示""" time_label.config(text=f"{minutes:02d}:{seconds:02d}") if state == "WORK": state_label.config(text="专注工作中", color="#0066CC") hint_label.config(text="保持专注,避免干扰") elif state == "BREAK": state_label.config(text="休息一下", color="#00AA66") hint_label.config(text="活动身体,看看远方") else: # IDLE state_label.config(text="准备就绪", color="#666666") hint_label.config(text="做出手势开始专注") # 在 timer_countdown 线程和状态切换函数中调用 update_display # 例如,在 timer_countdown 中: # mins, secs = divmod(remaining_time, 60) # update_display(state, mins, secs)

屏幕UI的加入,立刻让项目变得直观和专业。你可以进一步添加进度条、可爱的植物动画等,让界面更具吸引力。

5. 组装、调试与效果优化

5.1 盆栽内部组装与走线

选择一个大小合适的陶瓷或塑料花盆。将行空板、二哈识图、扩展板(如果有)固定在花盆底部或侧面,可以使用尼龙柱或蓝丁胶。RGB灯带沿着花盆内壁上部环绕固定,确保光线能均匀透出。将二哈识图的摄像头镜头对准花盆外侧,确保识别区域无障碍。所有线缆用扎带捆好,从花盆底部的排水孔或专门开的小孔引出,连接到行空板。最后,放入植物(真植物或仿真植物),用土壤或装饰物遮盖电路部分。务必确保所有电路部分与土壤和水完全隔离

5.2 系统调试与问题排查

  1. 二哈识图无反应

    • 检查供电:首先用万用表测量二哈的VCC和GND之间电压是否为5V(或3.3V,取决于接线)。
    • 检查I2C连接:在行空板上运行一个简单的I2C扫描程序,查看是否能扫描到地址0x32(或你设置的地址)。
    import machine i2c = machine.I2C(1) print(i2c.scan())
    • 检查协议设置:确认二哈识图屏幕上的通信协议是否为I2C。
    • 检查代码地址:确认代码中的I2C地址与扫描到的地址一致。
  2. LED灯带不亮或颜色错乱

    • 检查数据线方向:WS2812B灯带有方向性,DIN(数据输入)必须接控制端,DOUT(数据输出)接下一段灯带。第一颗灯珠的DIN接行空板GPIO。
    • 检查电源功率:灯带全白时电流最大。如果灯珠很多,行空板USB供电可能不足,导致灯光暗淡或行空板重启。必须外接电源。
    • 检查接地:外部电源的GND必须和行空板的GND连接在一起,即“共地”,否则信号无法正确传输。
    • 检查代码引脚:确认NeoPixel初始化时使用的GPIO编号正确。
  3. 番茄钟计时不准

    • 行空板的time.sleep(1)并非绝对精确的1秒,尤其是当系统负载高时。对于长时间计时,建议使用time.ticks_ms()time.ticks_us()获取系统毫秒/微秒计时,进行差值计算,这样更准确。
    • 示例修正:
    start_ticks = time.ticks_ms() while timer_thread_running: time.sleep(0.1) # 短延迟降低CPU elapsed_seconds = time.ticks_diff(time.ticks_ms(), start_ticks) // 1000 remaining_time = total_duration - elapsed_seconds # ... 更新显示和灯光

5.3 功能扩展与个性化

基础版本完成后,你可以尽情发挥创意:

  • 网络时间同步:利用行空板的Wi-Fi,连接NTP服务器获取精确时间,在待机状态下显示实时时钟。
  • 数据统计:将每天完成的番茄钟数量记录到行空板本地文件或上传到简单的物联网平台(如SIoT),周末回顾一下自己的专注成果。
  • 多模式切换:通过二哈识别不同的物体(如不同颜色的卡片),切换不同的计时模式,例如“深度专注模式”(50分钟)、“短休息模式”(3分钟)。
  • 环境互动:增加一个土壤湿度传感器,在植物需要浇水时,屏幕显示一个水滴图标提醒你,把植物养护和休息提醒结合起来。
  • 音效升级:替换行空板内置的简单蜂鸣提示,播放存储在板载存储中的MP3文件作为提示音,甚至可以在工作时段播放白噪音。

这个项目从想法到实现,最有趣的不是最终那个会发光、能识别的盆栽本身,而是将硬件、软件、交互设计串联起来,解决一个具体小问题的完整过程。每一个环节的调试,每一次功能的添加,都像在给这个电子盆栽“浇水施肥”,看着它一点点“生长”出你想要的功能。过程中遇到的电源问题、信号干扰、代码bug,都是宝贵的经验。我建议你先跑通最核心的“手势识别-计时-灯光反馈”循环,获得正反馈后,再一步步添加网络、统计、多模式等进阶功能。最重要的是,让它真正服务于你的桌面,成为你高效工作和健康休息的小助手。

http://www.jsqmd.com/news/1284312/

相关文章:

  • 基于Arduino的智能水质监测船:触屏遥控与实时数据采集
  • 华为非AI方向笔试 7月24号 真题 【双11购物狂欢】
  • PTEN缺失前列腺癌患者新选择:FDA批准Truqap卡匹色替capivasertib联合阿比特龙显著延缓疾病进展
  • 嵌入式开发实战:SPI模式驱动TF卡存储方案详解
  • AI时代,中层管理者之危
  • C 语言数组从入门到精通:一维数组、二维数组与内存存储全解析
  • ClickHouse托管Postgres:OLTP+OLAP,新能力解锁最佳数据平台
  • 千问新人福利!8元无门槛优惠券直接领,输入 千问新人福利uqo6UY 免费领券,实测可用!
  • 北大等多机构联手破解AI视频“边想边画“难题:让机器先谋后动
  • 权限日志没搞定,GraphRAG 上线第一天就崩了:一次需求评审后的工程化反思
  • AI代理技能开发实战:从零搭建企业级智能任务处理系统
  • DIY桌面龙卷风发生器:从伯努利原理到流体力学实践
  • 智能导盲杖开发全解析:从传感器融合到嵌入式系统实现
  • 全自动评价系统账号封的太严重-----干不下去了
  • 2026 年更新:凤冈可靠的手动推拉雨棚加工厂怎么联系,你还在花大价钱焊固定棚?这玩意儿帮你省出半年房租,还能随用随收不占地方-新航户外遮阳 - 企业推荐官【认证】
  • 3步彻底解决ThinkPad风扇噪音:TPFanCtrl2智能控制方案
  • RAG文档切分
  • Halcon与WPF融合的机器视觉开发框架解析
  • 基于Arduino与3D打印的低成本四轴机械臂DIY全攻略
  • AI智能体时代已经到来 普通开发者如何抓住下一波技术红利
  • LTE Cat 1bis模块与ARM Cortex-M4的物联网通信方案
  • 国产高精度标定设备新选择:弘澧科技联合标定系统全解析(附性能对比与实测数据)
  • 2026 上半年论文降重行业全景盘点:主流 AIGC 检测平台算法迭代亮点与对应避坑方案
  • 技术选型年度复盘:2026年最值得投资的5个技术基础设施
  • 航空航天、低空与工业控制场景:泽天智航全域算力应用与市场观察
  • 麦小昆小车视觉巡线走方阵:从PID控制到状态机的完整实现
  • PyTorch 张量基础(一)
  • 微电网两阶段鲁棒优化调度与Matlab实现
  • 高效智能英雄联盟工具深度解析:League Akari完整实战指南
  • 网络上今年刚刚出现的新事物