
1. 项目概述用百元预算解决千元问题你是否也经历过这样的尴尬场景走到会议室门口门关着里面静悄悄的你犹豫着要不要敲门——万一里面正在开重要会议或者进行保密谈话贸然闯入就太失礼了。但万一里面没人你站在门口纠结的样子也挺傻的。商业级的会议室占用状态指示系统动辄几百甚至上千元对于预算有限的中小企业或学校实验室来说部署多个会议室是一笔不小的开销。今天分享的这个项目正是为了解决这个痛点而生。它基于 Adafruit 的 Trinket 微型微控制器和一颗常见的 PIR被动红外传感器加上一块双色 LED 点阵屏总成本可以控制在百元人民币以内。核心逻辑非常简单PIR 传感器持续监测会议室内的红外热辐射变化一旦检测到人体活动就向 Trinket 发送一个高电平信号Trinket 收到信号后驱动 LED 点阵屏显示一个醒目的红色“X”表示“占用中”。当一段时间内没有检测到活动具体时长可调Trinket 则控制屏幕显示一个绿色方块表示“空闲”。这个方案的价值不仅在于成本低廉更在于其高度的可定制性和 DIY 乐趣。你可以根据会议室门的材质和颜色定制不同外观的安装盒也可以修改代码让 LED 屏显示不同的图案或闪烁频率。对于物联网和嵌入式开发的初学者来说这是一个绝佳的入门项目涵盖了传感器数据采集、微控制器编程、外设驱动和简单的系统集成等多个核心环节。接下来我将从设计思路、硬件搭建、代码编写到调试部署完整拆解这个项目的每一个细节。2. 核心硬件选型与设计思路解析2.1 为什么选择 Trinket 和 PIR 传感器在开始动手之前理解每个核心元器件的选型理由至关重要。这决定了系统的稳定性、成本和可扩展性。微控制器Adafruit Trinket (5V)Trinket 是 Adafruit 推出的一款基于 ATtiny85 芯片的微型开发板。选择它主要基于以下几点考量尺寸与成本其体积非常小巧非常适合嵌入到紧凑的安装盒中。价格相比功能更全的 Arduino Uno 或 Nano 更有优势在批量部署时能显著降低成本。足够的功能尽管只有 5个 GPIO 引脚但对于本项目一个数字输入-PIR一个I2C接口-显示屏来说绰绰有余。它内置了 USB 接口编程方便。低功耗虽然本项目采用外部供电不特别强调功耗但 Trinket 本身的低功耗特性为未来改用电池供电的升级留下了可能。注意务必选择5V 版本的 Trinket而不是 3.3V 版本。因为后续使用的 LED 点阵屏和常见的 PIR 传感器模块通常工作在 5V 逻辑电平下选择 5V 版本可以省去电平转换的麻烦让电路更简洁。运动传感器被动红外 (PIR) 传感器PIR 传感器是检测人体移动的“黄金标准”其原理是探测特定波长人体红外辐射的变化。非接触与隐私友好它不发出任何射线如微波仅被动接收红外辐射不会对人体产生影响也避免了摄像头带来的隐私顾虑非常适合会议室场景。可靠性高技术成熟抗干扰能力较强不易受光线、声音等环境因素影响误报率相对较低。易于使用市面上常见的模块如 HC-SR501都集成了信号处理电路直接输出数字信号高/低电平微控制器无需处理复杂的模拟信号大大降低了开发难度。可调节模块背面通常有两个电位器分别用于调节灵敏度探测距离和范围和触发后的保持时间可以根据会议室大小灵活调整。显示单元8x8 双色 LED 点阵屏 I2C 背板直接驱动一个 8x8 的 LED 点阵需要 16个 GPIO 引脚这远远超出了 Trinket 的能力。因此使用带I2C 接口的背板驱动芯片如 HT16K33是关键。节省引脚I2C 总线只需两根线数据线 SDA 和时钟线 SCL即可控制完美适配 Trinket 有限的引脚资源。简化编程Adafruit 提供了完善的Adafruit_LEDBackpack和Adafruit_GFX库我们只需调用简单的函数如drawBitmap就能绘制图形无需关心底层扫描和刷新逻辑。双色显示红绿双色提供了直观的状态区分红停/占用绿行/空闲符合普遍认知习惯。2.2 系统架构与信号流整个系统的数据流非常清晰是一个典型的“感知-决策-执行”物联网终端模型感知层PIR 传感器作为系统的“眼睛”持续监测环境。当有人进入其探测区域时传感器内部的热释电元件因接收到变化的红外辐射而产生电荷变化经模块内部电路处理后输出引脚从低电平跳变为高电平。控制层Trinket 作为“大脑”通过其一个数字输入引脚本例中为 Pin 1循环读取 PIR 传感器的输出电平。程序内部维护一个状态变量pirState用于记录上一次的有效状态避免频繁刷新显示屏。执行层当 Trinket 判断状态发生变化时通过 I2C 总线向 LED 点阵屏的背板芯片发送指令控制 64 个 LED 中特定位置的灯点亮红色或绿色形成“X”或“方块”图案。这个架构的优点是各司其职耦合度低。例如如果你想更换为超声波传感器判断更精确的距离只需替换感知层并修改 Trinket 上对应的读取代码如果想将显示改为 LCD 屏幕也只需更换执行层并调整对应的驱动库。3. 硬件搭建与焊接实操要点3.1 物料清单与工具准备在开始焊接前请准备好所有物料和工具清晰的准备是成功的一半。核心物料清单Adafruit Trinket (5V) × 1被动红外 (PIR) 传感器模块 (如 HC-SR501) × 18x8 双色 LED 点阵屏 (带 I2C 背板地址通常为 0x70) × 1半尺寸 Perfboard 或 Perma-Proto 板 × 1 用于固定所有元件小型防水项目盒 × 1 用于安装整个电路尺寸需能容纳点阵屏和电路板2.1mm 面板安装 DC 电源插座 × 1M4 螺丝及尼龙柱 × 若干 用于固定电路板5V/1A DC 电源适配器 × 1 确保电压稳定为 5V导线、排针、排母、1500欧姆电阻 × 若干必备工具电烙铁及焊锡丝万用表 用于检查通断和电压剥线钳螺丝刀套装手电钻及合适尺寸的钻头用于在项目盒上开孔热熔胶枪或螺丝用于固定 PIR 传感器3.2 电路焊接步骤详解焊接遵循“从低到高、先固定后连接”的原则确保电路整洁可靠。步骤一规划与固定核心部件将半尺寸的万用板放入项目盒确定其最佳位置。通常让 LED 点阵屏的显示区域对准盒盖的透明部分并留出电源插座和传感器线缆入口的空间。在万用板的四个角做好标记然后在项目盒底壳对应位置钻孔并使用 M4 尼龙柱和螺丝将电路板固定。注意确保螺丝高度不会顶到上层的元件或焊点。焊接排母为了便于调试和更换强烈建议为 Trinket 和 LED 点阵屏焊接排母而不是直接将元件焊死在板上。为 Trinket 焊接两排 5针的排母。为 LED 点阵屏的 4个引脚VCC, GND, SDA, SCL焊接一排 4针的排母。焊接电源总线在万用板的一侧用较粗的导线或直接利用板上的铜箔建立一条5V 电源总线和一条地线总线GND。这两条总线将为所有模块供电。步骤二连接 Trinket 与外围电路这是整个电路的核心务必对照原理图仔细操作。以下是 Trinket 引脚定义BAT: 接 5V 电源总线。GND: 接地线总线。Pin 0: 接 LED 点阵屏的 I2C 数据线 (SDA)。Pin 2: 接 LED 点阵屏的 I2C 时钟线 (SCL)。Pin 1: 这是 PIR 传感器的信号线接入点。这里需要一个上拉电阻。关键细节上拉电阻的作用PIR 模块在未触发时其信号输出引脚处于高阻态并非稳定的低电平。如果微控制器的输入引脚直接悬空或连接到这种高阻态很容易因电磁干扰读到不确定的值漂移导致误触发。加入一个 1.5kΩ - 10kΩ 的上拉电阻本例用 1.5kΩ可以将 Pin 1 通过电阻拉到 5V从而在传感器无输出时为 Trinket 提供一个稳定、明确的高电平。当 PIR 触发时其内部会输出一个强低电平足以将引脚电压拉低从而被 Trinket 识别为低电平。这个电阻是电路稳定工作的关键。焊接操作将 1500欧姆电阻的一端焊接到 5V 总线另一端焊接到一个空的焊盘上。将 Trinket 的 Pin 1 也通过导线连接到这个焊盘。这样电阻就将 Pin 1 上拉到了 5V。将 PIR 传感器的信号线通常是中间那根线也连接到这个焊盘。至此PIR 的信号线、上拉电阻和 Trinket Pin 1 就共接到同一点了。将 PIR 传感器的 VCC通常为红线和 GND通常为黑线或棕线分别连接到电源总线和地线总线。将 LED 点阵屏的 VCC 和 GND 也分别连接到电源总线和地线总线。步骤三安装外部接口在项目盒侧面规划电源插座和传感器线缆入口的位置。电源插座通常安装在侧面或背面底部。用手电钻在项目盒上钻出适合 DC 电源插座和防水电缆接头用于穿 PIR 传感器线的孔。从外部将 DC 电源插座拧紧固定在盒子上。注意焊接电源线到插座引脚时务必区分正负极。通常中心针为正极()外侧套管为负极(-)。用万用表确认后再焊接。将电源插座的正负极通过导线引入盒内并分别焊接到电路板的电源总线和地线总线上。将 PIR 传感器的三根线穿过防水电缆接头在盒内留出适当长度后拧紧接头以防水防尘。然后将线头焊接到电路板对应的接点上。3.3 装配与初步检查完成焊接后先不要急着上电进行以下检查视觉检查仔细检查所有焊点是否饱满、光滑有无虚焊、连锡特别是相邻焊盘之间。通断测试使用万用表的蜂鸣档检查电源总线与地线之间是否短路读数应为无穷大或很高阻值。检查 Trinket 的 BAT 和 GND 引脚与电源总线和地线是否连通。安装将 Trinket 和 LED 点阵屏插入对应的排母。将电路板用螺丝固定在项目盒底壳。盖上盒盖但先不要完全拧紧以便后续调试。上电测试关键步骤连接 5V 电源适配器。此时LED 点阵屏可能会亮起一些随机光点这是正常的因为控制器尚未初始化。用手在 PIR 传感器前晃动观察其红色指示灯是否会亮起大部分 PIR 模块自带一个触发指示灯。用万用表电压档测量 Trinket 的 Pin 1 对地电压静止时应为 5V 左右触发时应接近 0V。如果电压变化正常说明传感器和电路基本工作。4. 软件编程与代码深度解析4.1 开发环境搭建与库安装Trinket 基于 ATtiny85其开发环境配置与标准 Arduino 板略有不同。安装 Arduino IDE从 Arduino 官网下载并安装最新版本的 IDE。添加 Trinket 支持打开 Arduino IDE进入文件 - 首选项在“附加开发板管理器网址”中输入https://adafruit.github.io/arduino-board-index/package_adafruit_index.json。然后进入工具 - 开发板 - 开发板管理器搜索“Adafruit AVR”找到并安装“Adafruit AVR Boards”包。安装完成后你就可以在工具 - 开发板列表中找到 “Adafruit Trinket (ATtiny85 8MHz)” 选项。安装必要的库本项目需要三个库均可以通过库管理器安装。进入工具 - 管理库...。搜索 “Adafruit LED Backpack”选择并安装。这个库会自动安装它所依赖的 Adafruit GFX 库和 Adafruit BusIO 库非常方便。确保安装成功。你可以在文件 - 示例中看到Adafruit LED Backpack的示例文件夹。实操心得库版本兼容性有时新版本的库可能对旧版 IDE 或硬件支持有变化。如果编译出错可以尝试指定安装稍旧一点的稳定版本库。另外确保你为 Trinket 选择的编程器是USBtinyISP在工具 - 编程器中设置这是正确上传代码的关键。4.2 代码逐行解读与优化空间以下是完整的项目代码我将结合注释详细解释每一部分的作用和编程技巧。/*************************************************** Adafruit Trinket 会议室占用状态显示器 硬件Trinket 5V 8x8 双色LED点阵屏带I2C背板 特点代码空间极度紧凑已接近Trinket的存储上限 ****************************************************/ // 引入LED背板库该库会自动引入必需的 Wire (I2C) 库和 Adafruit_GFX 图形库 #include Adafruit_LEDBackpack.h // 宏定义与全局变量 const int PIRpin 1; // PIR传感器信号线连接的Trinket引脚Pin 1 uint8_t pirState LOW; // 用于记录PIR的上一稳定状态初始为“未触发” Adafruit_BicolorMatrix matrix Adafruit_BicolorMatrix(); // 创建双色点阵对象 void setup() { pinMode(PIRpin, INPUT); // 将PIR引脚设置为输入模式 matrix.begin(0x70); // 初始化I2C通信点阵屏的默认地址是0x70 } // 使用PROGMEM将图形数据存储在程序存储器中节省宝贵的SRAM空间 static const uint8_t PROGMEM // 红色“X”的位图数据每个字节代表一行8个像素1亮0灭 x_bmp[] { B10000001, // 第1行两端亮 B01000010, // 第2行 B00100100, // 第3行 B00011000, // 第4行中间亮 B00011000, // 第5行中间亮 B00100100, // 第6行 B01000010, // 第7行 B10000001 }, // 第8行两端亮 // 绿色方框的位图数据 box_bmp[] { B11111111, // 第1行全亮 B10000001, // 第2行两边亮 B10000001, // 第3行两边亮 B10000001, // 第4行两边亮 B10000001, // 第5行两边亮 B10000001, // 第6行两边亮 B10000001, // 第7行两边亮 B11111111 }; // 第8行全亮 void loop() { int sense digitalRead(PIRpin); // 读取PIR传感器当前的电平状态 if(sense HIGH) { // 如果读到高电平传感器未被触发注意逻辑 // 这里需要理解我们加了上拉电阻所以平时Pin 1被拉高为HIGH。 // PIR触发时会输出低电平将引脚拉低。所以HIGH表示无人。 if(pirState LOW) { // 如果之前的状态是LOW有人现在变成HIGH无人 matrix.clear(); // 清除屏幕 // 绘制绿色方框表示房间空闲。LED_GREEN是库定义的常量。 matrix.drawBitmap(0, 0, box_bmp, 8, 8, LED_GREEN); matrix.writeDisplay(); // 将缓冲区内容发送到显示屏 pirState HIGH; // 更新状态记录为“无人” } } else { // 如果读到低电平传感器被触发有人 if(pirState HIGH) { // 如果之前的状态是HIGH无人现在变成LOW有人 matrix.clear(); // 绘制红色“X”表示房间占用。 matrix.drawBitmap(0, 0, x_bmp, 8, 8, LED_RED); matrix.writeDisplay(); pirState LOW; // 更新状态记录为“有人” } } // 注意这里没有使用 delay()因为库函数和循环本身已有一定耗时 // 且PIR模块自身有延时调节所以无需软件延时避免占用额外代码空间。 }代码逻辑精析与常见陷阱电平逻辑这是最容易混淆的地方。由于使用了上拉电阻常态无人下digitalRead(PIRpin)读到的是HIGH。当 PIR 触发时它内部导通到地将引脚电平拉成LOW。所以代码中的if(sense HIGH)分支对应的是“无人”状态。务必理解这一点否则显示逻辑会完全相反。状态变量pirState这个变量用于实现“边缘检测”。它记录的是系统上一次确认并显示的状态。只有当当前读取的传感器电平与记录的系统状态不一致时才更新显示。这避免了传感器在触发阈值附近抖动导致的屏幕频繁闪烁也减少了不必要的 I2C 通信。PROGMEM关键字ATtiny85 的 SRAM 非常小仅512字节。将不变的位图数据存放在PROGMEM程序存储器中而不是默认的 RAM 中可以节省宝贵的 SRAM防止程序运行异常。代码空间警告如原项目所述使用高级库后Trinket 的 5KB 左右代码空间几乎被占满。这意味着你几乎无法再添加复杂的逻辑或字符串。delay()函数也会占用不少空间所以代码中刻意避免使用它。PIR 的持续时长通过其板载电位器调节而非软件延时。4.3 程序上传的特定步骤给 Trinket 上传代码需要一点技巧因为它没有传统 Arduino 的自动复位电路。在 Arduino IDE 中正确选择开发板工具 - 开发板 - Adafruit Trinket (ATtiny85 8MHz)。选择编程器工具 - 编程器 - USBtinyISP。点击“验证”对勾图标编译代码。确保无错误。关键上传操作用 USB 数据线将 Trinket 连接到电脑。按下 Trinket 板载的物理复位按钮。在按下复位按钮的瞬间Trinket 板载的红色 LED 会快速闪烁一下然后常亮。在红色 LED 常亮期间大约只有1秒钟立即点击 Arduino IDE 上的“上传”右箭头图标。如果时机把握正确IDE 下方会显示上传进度条。上传成功后红色 LED 会恢复慢速闪烁这是 Trinket 默认的“心跳”指示灯。注意事项上传失败排查时机不对这是最常见原因。多试几次掌握从按下复位到点击上传的节奏。驱动问题确保电脑已安装 Trinket 的 USB 驱动通常首次连接时会自动安装。电源问题如果通过项目电路板供电确保 5V 电源稳定。有时直接通过 USB 供电上传更可靠。编程器选择错误务必选择USBtinyISP。5. 系统调试、部署与优化实录5.1 PIR 传感器调试与定位技巧硬件和软件都就绪后调试的重点就落在了 PIR 传感器上。初步功能测试将组装好的系统通电用纸板暂时盖住 PIR 传感器镜头。此时 LED 屏应显示绿色方框无人状态。快速移开纸板并在传感器前挥手屏幕应切换为红色“X”并保持一段时间后恢复绿色。如果显示逻辑相反请检查代码中对sense电平的判断逻辑或者检查硬件上拉电阻是否接错。调节两个电位器灵敏度调节 (SENSITIVITY 或 Sx)逆时针旋转到底Min灵敏度最低。慢慢顺时针旋转同时测试最远探测距离。对于会议室建议调节到能稳定探测到房间内人员正常活动如起身、走动但又不会因为门外的走廊行人而误触发。技巧测试时让人在房间最远的角落轻微活动调节到能刚好触发的位置。延时调节 (TIME 或 Tx)这个电位器决定了触发后输出信号保持低电平有人状态的时间。逆时针最短约2-3秒顺时针最长可达数分钟。对于会议室建议设置一个合理的时间例如5-10分钟。这样即使会议中大家暂时静止系统也不会立即显示“空闲”避免他人误入。重要提示这个延时是传感器硬件级别的与我们的软件无关。调节它不会增加代码负担。安装位置选择避免对准热源不要将 PIR 正对着空调出风口、窗户阳光直射或发热设备这些稳定的热源变化可能引起误报。覆盖主要区域将传感器安装在会议室侧墙视角能覆盖会议桌和主要活动区域。避免安装在正对门口的位置否则门开关时门外人员可能被探测到。高度适宜安装高度建议在1.8米 - 2.2米之间略高于人体高度向下倾斜以获得最佳探测覆盖。5.2 显示单元优化与安装亮度调节部分 LED 背板库支持通过setBrightness()函数调节亮度。如果觉得屏幕太刺眼可以在setup()函数中matrix.begin(0x70);之后添加matrix.setBrightness(5);亮度范围 0-15。注意添加任何新函数调用前务必先“验证”代码确认不会超出存储空间。制作遮光罩为了让显示效果更清晰专业可以裁剪一块白色半透的亚克力板或厚硫酸纸贴在项目盒内部覆盖整个盒盖。然后在对应 LED 点阵的位置开一个精确的方形窗口。这样既能柔化LED光线使其看起来更像一个商业产品又能隐藏盒子内部杂乱的电路。安装固定在项目盒背面钻孔使用螺丝或强力双面胶将其固定在会议室门外侧的墙上高度与常人视线平齐约1.5米。确保电源线走线安全、隐蔽。5.3 常见问题排查速查表下表汇总了项目实施过程中可能遇到的典型问题及解决方法问题现象可能原因排查步骤与解决方案上电后无任何反应LED屏不亮1. 电源未接通或损坏2. 电源极性接反3. 电路存在短路电源保护1. 用万用表测量电源适配器空载输出电压是否为5V。2. 检查DC插座和电路板上的电源正负极是否接反。3. 断开电源用万用表蜂鸣档检查电源总线与地线是否短路。LED屏亮但显示乱码或部分LED常亮1. I2C通信失败2. 接线错误SDA/SCL接反3. 库未正确安装或地址错误1. 检查Trinket Pin 0, Pin 2 到显示屏SDA, SCL的连接是否牢固、正确。2. 确认代码中matrix.begin(0x70);的地址与显示屏背板一致多数为0x70。3. 重新安装 Adafruit LED Backpack 库。屏幕始终显示红色“X”挥手无变化1. PIR传感器信号线接触不良或接错2. 上拉电阻未接或虚焊3. 代码逻辑错误电平判断反了1. 用万用表测量PIR信号线对地电压静止时~5V触发时~0V。若无变化检查PIR接线。2. 检查1500Ω电阻是否一端接5V另一端接Pin 1和PIR信号线。3. 审查代码确认sense HIGH时显示绿色空闲的逻辑是否符合你的硬件上拉电阻导致常态高电平。屏幕状态变化延迟异常或频繁闪烁1. PIR延时电位器调节不当2. 传感器安装位置不佳探测到不稳定热源3. 电源不稳定导致Trinket复位1. 重新调节PIR背面的“TIME”电位器选择合适的保持时间。2. 重新选择传感器安装位置避开通风口和窗户。3. 使用万用表监测5V电源电压在PIR触发时是否有大幅跌落。建议使用输出电流充足的电源1A或以上。代码上传失败提示“编程器未响应”1. 上传时机不对2. Trinket驱动未安装3. USB线或端口问题1. 严格按照“按复位键 - 红灯常亮 - 立即点上传”的节奏操作多试几次。2. 检查设备管理器中是否有未知设备尝试重新安装Adafruit提供的驱动。3. 更换USB数据线或电脑USB端口确保其能传输数据而非仅充电。5.4 项目扩展思路这个基础项目稳定运行后你可以考虑以下扩展方向使其功能更强大增加无线通信难度中级换用像 ESP8266 或 ESP32 这类带 Wi-Fi 功能的微控制器。这样占用状态不仅可以本地显示还能通过 MQTT 协议发布到服务器在公司的内部网页或移动应用上实时查看所有会议室状态。多传感器融合难度中级除了 PIR可以增加一个声音传感器。只有同时检测到移动和一定分贝的声音时才判定为“占用”进一步降低误报率比如仅有人进去拿东西。低功耗优化难度高级如果想用电池供电需要全面改造。选用 3.3V 版本的 Trinket 或专门的低功耗芯片让微控制器大部分时间处于深度睡眠模式仅定时唤醒读取传感器状态。LED 屏也只在状态变化时点亮片刻其余时间关闭。这样可以用电池工作数月。更改显示内容利用Adafruit_GFX库的功能可以显示数字、字母或更复杂的动画。例如显示“IN USE”和“FREE”的英文缩写或者用滚动动画表示状态切换。这个基于 Trinket 和 PIR 的会议室占用显示器虽然电路和代码简单却完美诠释了物联网“感知-控制”的核心思想。它用最低的成本解决了一个实际痛点其开发过程中涉及的硬件选型、电路设计、逻辑编程和调试排错是每一位嵌入式开发者和物联网爱好者都值得亲手实践一遍的宝贵经验。当你亲手制作的设备在会议室门口稳定工作有效避免了无数次尴尬的敲门时那种成就感远非购买一个成品所能比拟。