Arduino与树莓派物联网项目实战:构建漫画周更追踪器
1. 项目概述:一个漫画迷的硬核桌面玩具
作为一个每周都要跑漫画店、生怕错过任何一本新刊的资深漫画收藏者,我太懂那种每周三(北美漫画上新日)刷手机查列表的仪式感了。市面上App很多,但总觉得少了点“宅”味儿。于是,一个念头冒了出来:能不能做个实体的、放在书架上、一按按钮就能“吐”出本周新刊列表的小玩意儿?它最好还得有点个性,比如……能放段蜘蛛侠的主题曲?
这个想法催生了“漫威DC漫画周更追踪器”。它的核心很简单:一个能联网、能显示、还能跟你互动的小盒子。我选择了Arduino Nano 33 IoT作为前端的“大脑”和“手脚”,负责控制屏幕、按钮、灯光和音乐;用Raspberry Pi在后台充当一个小型服务器,运行一个用PHP写的Web应用,专门去ShortBoxed漫画API抓取数据。两者一结合,一个独立的、脱离手机和电脑的漫画信息终端就诞生了。这不仅仅是一个工具,更是给爱好者的一个“玩具”,一个能融入你收藏环境的科技摆件。无论你是想复现一个放在桌边,还是想学习如何将微控制器、单板计算机和网络API串联起来,这个项目都能提供一条清晰的路径。
2. 核心思路与架构设计:为什么是Arduino + Raspberry Pi?
很多物联网项目会面临一个选择:是用一个性能强大的主控(如树莓派)包办一切,还是用多个分工明确的微控制器?这里我选择了后者,并且有充分的理由。
2.1 硬件选型背后的考量
Arduino Nano 33 IoT 是这个项目的交互核心。我选择它,主要看中三点:
- 内置Wi-Fi与低功耗:这是实现联网查询的基础。相比给普通Arduino外接Wi-Fi模块,集成方案更稳定,电路也更简洁。
- 丰富的GPIO与PWM引脚:我需要驱动诺基亚5110屏幕(需要SPI接口和几个控制引脚)、多个按钮、RGB LED、蜂鸣器和振动电机。Nano 33 IoT的引脚数量和功能刚好够用,且其PWM引脚能完美控制LED亮度和蜂鸣器音调。
- 实时性与响应速度:对于按钮检测、屏幕刷新、播放简单旋律这类任务,Arduino的实时性和确定性远超运行完整操作系统的树莓派。你不会希望按个按钮要等半秒才有反应。
Raspberry Pi (3B+或4) 在这里扮演了“家庭服务器”和“数据网关”的角色。它的任务是:
- 运行稳定的Web服务:我需要一个7x24小时运行、能响应HTTP请求的服务器。用树莓派搭建一个LAMP(Linux, Apache, MySQL, PHP)环境是成熟且低功耗的方案。
- 处理复杂的网络请求与数据解析:调用第三方API(ShortBoxed)、处理JSON数据、进行简单的数据过滤(只取漫威和DC的漫画),这些任务在PHP中编写和调试,远比在Arduino上用C++处理HTTP客户端和JSON解析要简单、健壮得多。树莓派强大的处理能力可以轻松应对。
- 职责分离:这种架构将“数据获取与处理”和“用户交互与控制”解耦。如果未来API有变动,或者我想增加新的数据源(比如其他出版社),我只需要在树莓派的PHP代码中修改,无需重新烧录Arduino固件。系统的可维护性和可扩展性大大增强。
其他关键组件解析:
- Nokia 5110屏幕:这是一块经典的84x48像素单色LCD屏。选择它是因为其极高的性价比、极低的功耗,以及那种独特的“复古像素风”,非常契合漫画和极客项目的审美。其驱动库成熟,在Arduino上使用非常简单。
- ShortBoxed API:这是一个专注于漫画发行信息的免费API,数据相对准确及时。它提供了按周查询的接口,正好符合我们的“周更”需求。相比爬取漫画新闻网站,使用API是更规范、更稳定的数据获取方式。
注意:这种“微控制器(MCU)+ 单板计算机(SBC)”的架构是物联网中非常经典的“边缘计算”雏形。树莓派处理云端交互和复杂逻辑,Arduino负责具体的传感器和执行器控制,两者通过简单的HTTP协议通信,各司其职,效率最高。
2.2 系统工作流程全景图
整个设备的工作流程可以清晰地分为云端、网关和终端三层:
- 数据层(云端):ShortBoxed API服务器。它存储并提供了结构化的漫画发行数据。
- 网关/处理层(树莓派):
- 树莓派上运行着Apache服务器和我们的PHP应用。
- PHP应用定时或按需(当Arduino请求时)向ShortBoxed API发送HTTP GET请求。
- 获取到JSON格式的完整周更列表后,PHP脚本进行解析,过滤出“Marvel Comics”和“DC Comics”的条目,并格式化为一行行纯文本。
- 当Arduino通过局域网访问特定的URL(如
http://[树莓派IP]/New_Comics_Releases/?q=this)时,PHP脚本就将处理好的纯文本列表返回。
- 交互层(Arduino设备):
- Arduino上电后,首先连接预设的Wi-Fi网络。
- 连接成功后,在诺基亚5110屏幕上显示主菜单(本周、下周、上周、图形)。
- 用户通过五个按钮(上、下、左、右、确认)进行导航和选择。
- 当用户选择“本周”等选项后,Arduino会向树莓派的PHP应用地址发送HTTP请求,获取对应的文本数据。
- 接收到数据后,Arduino将其在屏幕上分页显示,用户可以使用左/右按钮翻页浏览。
- 在整个交互过程中,RGB LED、振动电机和蜂鸣器提供额外的视觉、触觉和听觉反馈,增强用户体验。
这个流程确保了数据从互联网到最终显示在小小屏幕上的完整通路是畅通且高效的。
3. 硬件制作详解:从电路图到蜘蛛侠主题PCB
硬件部分是整个项目的物理基础,也是乐趣所在。我强烈建议先使用面包板进行原型验证,再转向定制PCB,这样可以避免很多设计错误。
3.1 原型验证与电路连接
在将一切焊接到精美的PCB之前,必须在面包板上完成所有连接和功能测试。这是硬件开发的黄金法则。
核心连接清单(基于Arduino Nano 33 IoT):
| 组件 | 连接到Arduino引脚 | 说明与注意事项 |
|---|---|---|
| Nokia 5110 LCD | 通信协议:SPI | |
| SCK (时钟) | D2 | |
| MOSI (数据输入) | D3 | |
| DC (数据/命令) | D4 | |
| RST (复位) | D5 | |
| CS (片选) | D6 | |
| 旋转电位器 | 信号线 (S) | A0 |
| 按钮 (右) | 信号线 | A1 |
| 按钮 (左) | 信号线 | A2 |
| 按钮 (确认) | 信号线 | A3 |
| 按钮 (上) | 信号线 | A6 |
| 按钮 (下) | 信号线 | A7 |
| RGB LED (共阴极) | 红色 (R) | D12 |
| 绿色 (G) | D11 | |
| 蓝色 (B) | D10 | |
| 蜂鸣器 (有源) | 正极 (+) | D8 |
| 振动电机 | 正极 (+) | D9 |
实操心得:驱动振动电机:这是新手常踩的坑。振动电机工作电流可能超过100mA,远超Arduino单个GPIO引脚(通常20-40mA)的驱动能力。务必使用一个N沟道MOSFET(如IRLZ34N)或一个三极管(如2N2222)来驱动。将电机的正极接电源(VIN或5V),负极接MOSFET的漏极(D),MOSFET的源极(S)接GND,栅极(G)通过一个220Ω电阻接Arduino的D9引脚。这样,D9输出高电平时,MOSFET导通,电机通电振动。
3.2 定制PCB设计与焊接要点
当面包板上的原型稳定运行后,就可以着手设计定制PCB了。我使用KiCad进行设计,并将灵感来源于蜘蛛侠网纹和漫画对话框的元素融入PCB丝印层,让它成为一件真正的“主题藏品”。
PCB设计关键点:
- 布局规划:将Arduino Nano 33 IoT的接口放在板子中央,方便布线。屏幕接口、按钮、电位器、LED等外围元件围绕其布置,并考虑最终外壳的安装位置。
- 电源设计:板子上有一个DC电源插座,用于输入7-12V的直流电压。我使用了一个低压差稳压器(如AMS1117-5.0)将其稳压到5V,为整个系统供电。务必在电源输入处加入一个极性保护二极管和至少100μF的电解电容进行滤波,防止接反电源或电压波动损坏器件。
- 信号完整性:为每个按钮的上拉电阻(1KΩ)预留了位置。对于连接到模拟引脚(A0-A3, A6, A7)的按钮和电位器,走线应尽量短,并远离数字高速信号线(如连接蜂鸣器的D8),以减少噪声干扰。
- 丝印与美学:在PCB的空白处,我添加了蜘蛛侠logo的轮廓和“Comics Tracker”的艺术字。这不仅是为了好看,清晰的丝印也能极大方便焊接和调试。
焊接顺序建议:
- 先矮后高:先焊接电阻、二极管、IC插座等低矮元件。
- 再焊接口:焊接所有的排母(用于插接Arduino和屏幕),确保它们与PCB垂直。
- 最后焊外设:焊接电位器、按钮、蜂鸣器、电机、LED和DC插座。这些元件通常较高或需要承受机械力。
- 焊接检查:焊接完成后,务必用放大镜检查是否有虚焊、短路(特别是引脚密集的芯片附近)。使用万用表的通断档,检查所有VCC和GND网络是否短路,以及关键信号线是否连通。
4. 软件环境搭建:树莓派LAMP服务器与PHP应用
树莓派端的任务是搭建一个可靠的数据中转站。我们选择LAMP栈,因为它轻量、成熟,且非常适合运行PHP脚本。
4.1 树莓派系统准备与Apache安装
首先,确保你的树莓派已经安装了Raspberry Pi OS(原Raspbian)并连接了网络。
安装完成后,在树莓派或其他同一局域网的设备的浏览器中,输入树莓派的IP地址(用 hostname -I 命令查看),你应该能看到Apache的默认测试页面。这表明Web服务器已经成功运行。
4.2 PHP与必要扩展的安装
我们的PHP脚本需要用到curl扩展来调用ShortBoxed API。
为了测试PHP是否安装成功,可以创建一个测试文件:
在里面写入 <?php phpinfo(); ?>,保存退出。然后在浏览器访问 http://[树莓派IP]/test.php,如果能看到详细的PHP配置信息页面,说明PHP环境配置成功。测试完毕后,请务必删除这个test.php文件,因为它会暴露系统信息。
4.3 PHP Web应用部署与解析
将项目提供的 New_Comics_Releases.zip 解压后,其核心是一个 index.php 文件。这个文件的结构清晰:
- 定义Comics类:这是一个简单的PHP类,封装了从API获取数据的方法。
- 三个核心方法:
get_this_week_releases(): 向https://api.shortboxed.com/comics/v1/new发送请求,获取本周漫画。get_next_week_releases(): 向https://api.shortboxed.com/comics/v1/future发送请求,获取下周漫画。get_previous_week_releases(): 向https://api.shortboxed.com/comics/v1/previous发送请求,获取上周漫画。
- 数据过滤与格式化:每个方法在拿到JSON数据后,会解码成PHP数组,然后遍历数组,只输出出版商(
publisher)为“Marvel Comics”或“DC Comics”的条目。输出格式被精简为%出版商, 标题 ****...%日期%,以节省传输数据量并方便Arduino端解析。 - 请求路由:脚本通过检查
$_GET[‘q’]参数来决定调用哪个方法。例如,?q=this触发本周列表。
部署步骤:
现在,你可以通过浏览器访问 http://[树莓派IP]/New_Comics_Releases/?q=this 来测试。如果一切正常,你会看到纯文本格式的漫画列表。这个URL就是Arduino之后要访问的地址。
注意事项:API限制与缓存:ShortBoxed API是免费的,但可能有调用频率限制。我们的设备是手动触发查询,问题不大。但在实际部署中,可以考虑在PHP端加入简单的缓存机制,比如将API返回的JSON数据以文件形式保存1小时,这样即使API暂时不可用或Arduino频繁刷新,也能提供旧数据,提升设备稳定性。这可以通过检查缓存文件是否存在且未过期来实现。
5. Arduino端编程:连接、交互与显示
Arduino端的代码是项目的灵魂,它负责将所有硬件和网络服务整合成一个流畅的用户体验。
5.1 开发环境与库配置
首先,确保你的Arduino IDE已安装对Arduino Nano 33 IoT的支持。
- 打开Arduino IDE,进入 文件 > 首选项,在“附加开发板管理器网址”中添加:
https://www.arduino.cc/download_handler.php?f=/packages/arduino/package_index.json - 进入 工具 > 开发板 > 开发板管理器,搜索“Arduino SAMD Boards”,安装它。
- 安装完成后,在 工具 > 开发板 中选择“Arduino Nano 33 IoT”。
- 安装必要的库:通过 项目 > 加载库 > 管理库,搜索并安装:
WiFiNINA:用于Nano 33 IoT的Wi-Fi连接。Adafruit PCD8544 Nokia 5110 LCD Library:用于驱动屏幕。安装时可能还会提示安装依赖的Adafruit GFX Library,一并安装。
5.2 网络连接与HTTP请求
稳定的Wi-Fi连接是项目的前提。代码中需要硬编码你的Wi-Fi SSID和密码(对于开源项目,务必提醒用户在部署前修改)。
连接Wi-Fi的函数通常放在 setup() 中,并加入重试逻辑:
发起HTTP GET请求的核心函数如下:
在实际调用时,serverName 是你的树莓派IP地址,query 是 /New_Comics_Releases/?q=this 这样的路径。
5.3 用户界面(UI)与状态机设计
在有限的84x48像素屏幕上设计一个友好的界面需要精打细算。我采用了一个简单的**状态机(State Machine)**模型来管理设备的不同模式,这是嵌入式系统UI设计的常用模式。
定义状态枚举:
主循环 (loop()) 逻辑:
在 handleMenu() 函数中,通过读取上/下按钮来高亮不同的菜单项,并改变RGB LED的颜色和触发短振动作为反馈。当按下“确认”按钮时,根据当前高亮的菜单项,将 currentState 切换到对应的状态,并触发相应的动作(如播放音乐、获取数据)。
5.4 蜂鸣器音乐与旋律编程
播放蜘蛛侠主题曲是项目的点睛之笔,增加了设备的趣味性和主题沉浸感。Arduino使用 tone(pin, frequency, duration) 函数来产生指定频率(音高)和时长(音长)的声音。
原理:歌曲的旋律是由一系列音符序列及其对应的时值组成的。我们需要定义两个数组:
int melody[]: 存储每个音符的频率(单位:赫兹)。int noteDurations[]: 存储每个音符的时值(单位:毫秒,或用一个代表音符类型的整数,如4分音符)。
项目中使用了一个额外的 pitches.h 头文件,它定义了像 NOTE_C4、NOTE_G4 这样的常量,其值就是对应音符的频率,这比直接写数字更直观。
播放函数示例:
实操心得:旋律来源与转换:网上找到的乐谱通常是简谱或五线谱,需要手动或借助工具转换成频率和时值。一个技巧是:先确定歌曲的调性和节奏(如C大调,4/4拍),然后用
tone()函数一个音一个音地调试,直到听起来像为止。这个过程虽然繁琐,但完成后成就感十足。也可以搜索“Arduino [歌曲名] melody”看看有没有现成的代码。
6. 功能集成与调试:让设备“活”起来
当硬件焊接完毕,树莓派和Arduino的代码都准备就绪后,就到了最激动人心的集成与调试阶段。
6.1 首次上电与基础测试
- 供电检查:使用万用表测量PCB上5V和3.3V电源网络是否正常。确保没有短路。
- Arduino程序烧录:将完整的Sketch代码(包含Wi-Fi信息)编译并上传到Nano 33 IoT。打开串口监视器(波特率115200),观察启动日志。你应该能看到Wi-Fi连接的过程,以及连接成功后的IP地址。
- 屏幕与按钮测试:在
setup()函数中初始化屏幕,并显示一个简单的测试图案(如“Hello Comics!”)。同时,编写一个简单的循环,打印每个按钮引脚的状态,确保每个按钮按下时都能正确触发。 - 网络连通性测试:在Arduino代码中,添加一个测试函数,尝试向树莓派的PHP应用发送一个简单的请求(如请求“this”),并将返回的原始数据打印到串口监视器。确保你能看到漫画列表的文本。
6.2 交互逻辑联调
这是将各个独立模块串联起来的过程。
- 菜单导航:确保上/下按钮可以循环高亮四个菜单项,并且RGB LED的颜色能随之正确变化(紫色-本周,青色-下周,黄色-上周,绿色-图形)。振动电机的短促震动反馈也应同步。
- 数据获取与显示:选择“本周”菜单并按下确认。设备应播放蜘蛛侠主题曲(确保蜂鸣器接线正确),然后屏幕显示“Fetching...”,接着向树莓派发起请求。成功后,列表应显示在屏幕上。这里的关键是文本解析与分页。由于诺基亚5110屏幕一行只能显示约14个英文字符,而漫画标题可能很长,需要设计一个滚动或分页显示的逻辑。我通常将获取到的长字符串按换行符(
\n)分割成多个条目,然后每屏显示3-4条,用左/右按钮翻页。 - 图形模式:在图形模式下,旋转电位器,屏幕应在预置的几张单色位图(比如蜘蛛侠头像、漫威Logo、DC Logo等)之间切换。这需要先将图片通过工具(如LCD Assistant)转换成字节数组存到Arduino的闪存中,然后根据电位器ADC读取的值(映射到0-9)来选择显示哪一张。
6.3 常见问题与排查实录
在调试过程中,你几乎一定会遇到下面这些问题。这里是我的排查笔记:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 屏幕白屏或乱码 | 1. 电源电压不对(诺基亚5110是3.3V设备)。 2. SPI引脚接错。 3. 复位或DC引脚时序问题。 |
1. 检查屏幕VCC是否接3.3V,背光LED限流电阻是否合适。 2. 核对SCK、MOSI引脚是否与代码中定义一致。 3. 在 setup() 中初始化屏幕后,增加一个长延时(2秒),并确保 reset() 和 setContrast() 函数被正确调用。 |
| Wi-Fi无法连接 | 1. SSID/密码错误。 2. 网络加密方式不兼容(如WPA3)。 3. Nano 33 IoT的Wi-Fi模块固件过旧。 |
1. 再三检查代码中的SSID和密码,注意大小写和特殊字符。 2. 尝试将路由器加密方式暂时改为WPA2-PSK。 3. 在Arduino IDE中,通过 工具 > WiFi101 / WiFiNINA Firmware Updater 更新Wi-Fi模块的固件。 |
| HTTP请求失败,返回空数据 | 1. 树莓派IP地址错误或已变更。 2. Apache/PHP服务未运行。 3. Arduino客户端未正确解析HTTP响应头。 |
1. 在树莓派上执行 hostname -I 确认当前IP,并更新Arduino代码。2. 在树莓派上运行 sudo systemctl status apache2 检查服务状态。用浏览器直接访问PHP链接测试。3. 在Arduino的 httpGETRequest 函数中,将读取到的原始HTTP响应(包括头信息)全部打印到串口,检查是否收到了正确的数据,并调整解析正文的逻辑(查找“\r\n\r\n”作为头结束标志更可靠)。 |
| 按钮反应不灵或连击 | 1. 硬件抖动。 2. 代码中防抖逻辑不完善。 |
1. 确保按钮引脚配置为 INPUT_PULLUP,并使用外部上拉电阻是更稳定的做法(尽管MCU内部有上拉)。2. 实现软件防抖。记录按钮按下时的时间戳,只有当前状态与上次检测状态不同,且距离上次变化时间超过50毫秒,才认为是一次有效的按键事件。 |
| 电位器控制图形切换跳跃/不灵敏 | 1. ADC读取值有噪声。 2. 映射区间划分不合理。 |
1. 对ADC值进行软件滤波,例如连续读取5次取平均值。 2. 将0-1023的ADC值映射到0-9时,确保每个区间宽度大致相等(约102个单位)。可以在切换时加入一个小的“迟滞”区间,防止在边界值附近频繁跳动。 |
| 振动电机不工作或Arduino发热 | 电机直接连接到了GPIO引脚! | 立即断电! 这是最危险的错误。必须按前文所述,改用MOSFET或三极管驱动电路。检查你的电路图。 |
7. 项目优化与扩展思路
当基础功能全部跑通后,你可以考虑以下优化和扩展,让这个项目更加强大和个性化。
7.1 性能与稳定性优化
- 加入看门狗(Watchdog):Arduino Nano 33 IoT支持硬件看门狗。启用它可以在程序意外卡死时自动重启设备,这对于需要长期运行的物联网设备至关重要。CPP#include <avr/wdt.h> // 对于基于AVR的Arduino// 对于SAMD架构的Nano 33 IoT,可能使用不同的库void setup() {wdt_enable(WDTO_8S); // 启用看门狗,超时时间8秒}void loop() {wdt_reset(); // 在主循环中定期“喂狗”// ... 你的主循环代码}
- 实现OTA(空中升级):利用Wi-FiNINA库,可以为设备添加OTA更新功能。这样,未来修复bug或增加新功能时,无需再用USB线连接电脑,直接通过网络就能更新固件。
- 数据缓存:在Arduino端,可以将每次获取的漫画列表保存在EEPROM(电可擦写存储器)中。这样,当网络断开或树莓派关机时,设备至少能显示上一次成功获取的数据,并提示“数据可能不是最新的”。
7.2 功能扩展
- 增加更多出版社:修改树莓派上的PHP脚本,将“Image Comics”、“Dark Horse”等其他你感兴趣的出版社也加入过滤列表。
- 添加收藏提醒:在PHP端维护一个你正在追的系列列表(如“The Amazing Spider-Man”, “Batman”)。当获取到列表后,进行关键词匹配。如果发现新刊,可以让Arduino通过RGB LED闪烁特定颜色(比如红色),或让振动电机长震,实现一个简单的“上新提醒”功能。
- 改用电子墨水屏:如果你追求极致的显示效果和低功耗(像真正的电子书一样),可以考虑将诺基亚5110屏幕换成一块小尺寸的电子墨水屏(E-Ink)。这样,只有在刷新内容时才耗电,显示内容时零功耗,非常适合作为常驻桌面的信息牌。驱动库可以使用
GxEPD2。 - 集成语音合成:加入一个简单的语音合成模块(如SYN6288),让设备在切换模式或找到特定漫画时,用语音播报出来,科技感瞬间拉满。
完成所有步骤后,将这个充满心血的设备放在你的漫画书架或工作台上。每次按下按钮,听到熟悉的旋律,看到最新的漫画列表在复古的像素屏幕上滚动,那种将数字信息与实体硬件、个人爱好完美融合的满足感,是单纯使用手机App无法比拟的。这个项目不仅是一个追踪器,更是一个宣告你极客身份和热爱的个性宣言。希望你在制作和使用的过程中,也能感受到同样的乐趣。如果在复现过程中遇到任何问题,随时可以回顾第六部分的排查指南,或者带着具体的现象去相关的开发者社区交流,那里有很多热心的朋友。