自动化剧集与动漫放送日期通知系统 - Arduino Nano 33 IoT + 树莓派
组件与材料
| JLCPCB 定制 PCB | ×1 |
| Arduino Nano 33 IoT | ×1 |
| Raspberry Pi 3 Model B (或 Pi 4) | ×1 |
| Raspberry Pi 4 Model B (或 Pi 3) | ×1 |
| SparkFun Nokia 5110 屏幕 | ×1 |
| Serial MP3 Player (OPEN-SMART) | ×1 |
| RGB 共阳极 LED | ×1 |
| MicroSD 卡 | ×2 |
| 220Ω 电阻 | ×12 |
| 6×6×5 轻触开关 | ×4 |
| DC 电源插座 2.1mm | ×1 |
所需工具
- 电烙铁 (通用)
- 热熔胶枪 (通用)
软件与在线服务
- Arduino IDE
- KiCad (PCB 设计)
- Notepad++ (代码编辑)
项目概述
虽有大量 Web/移动 App 追踪剧集放送日期,但我想从零构建硬件+软件一体的专用通知设备,具备多种特色功能。
系统架构
- Web 应用 (PHP):部署在树莓派 LAMP (MariaDB) 服务器,利用 TVMAZE REST API 按日期精准获取剧集信息。也提供免费在线版 (TheAmplituhedron) 供无树莓派用户使用。
- Arduino Nano 33 IoT:通过 WiFi 定时轮询 Web 应用,解析返回数据,在 Nokia 5110 屏幕显示剧集信息,并播放对应片头曲。
- 串口 MP3 模块:通过 UART 控制播放片头曲,增加 MP3 播放器模式,化身桌面摆件。
最终设计了一块复古电话造型的 PCB (TV Series / Anime Release Date Notifier),感谢 JLCPCB 赞助。

步骤 1:PCB 设计与焊接
使用 KiCad 设计,Gerber 文件见附件,可直接在 JLCPCB 下单。焊接排针、按键、电阻、电源插座、RGB LED 等元件。




步骤 2:树莓派搭建 LAMP + MariaDB 服务器
新手可参考 树莓派官方教程。
sudo apt-get install apache2 -y安装 Apache- 浏览器访问
https://localhost或hostname -I获取的 IP 测试 sudo apt-get update && sudo apt-get install php -y安装 PHPsudo apt-get install mariadb-server php-mysql -y安装 MariaDBsudo mysql_secure_installation安全初始化:设 root 密码为 bot,移除匿名用户、禁止远程 root 登录、删除测试库- 创建数据库
tvseries并授权 sudo apt-get install php-curl支持file_get_contents()调用 APIsudo service apache2 restart重启生效
步骤 3:利用 TVMAZE API 获取剧集信息
TVMAZE 提供免费 REST API,使用 Episode by Date 接口:
GET https://api.tvmaze.com/shows/{tv_id}/episodesbydate?date=YYYY-MM-DD
需在 TVMAZE 搜索剧集获取 TV ID。示例列表:
- One Piece - TV ID: 1505
- My Hero Academia - TV ID: 13615
- Westworld - TV ID: 1371
- The Simpsons - TV ID: 83
- The Late Late Show - TV ID: 2831 (每日播放,适合测试)
步骤 4:开发 Web 应用 (TV Series / Anime Release Date Tracker)
PHP 应用含两文件:index.php (建表) 和 query.php (查询 API 并返回 Arduino 可解析格式)。
部署方法
- 下载
TV-Series-Anime-Episode-Tracker.zip解压 sudo mv ~/Downloads/TV-Series-Anime-Episode-Tracker/ /var/www/html/- 访问
https://localhost/TV-Series-Anime-Episode-Tracker/自动建表 - 向
series表插入数据:INSERT INTO series (series_name, tv_id, status) VALUES ('One Piece', '1505', 'Pending'); - 访问
query.php返回格式:%Series_Name%Season%Episode_Number%Episode_Name%(以 % 为分隔符)
无树莓派用户:使用在线版
访问 在线管理界面,提供图形化数据库操作,需订阅 TheAmplituhedron。
步骤 5:配置 Arduino Nano 33 IoT
- 安装 Arduino SAMD 核心支持
- 安装
WiFiNINA库 (WiFi 连接) - 安装
LCD5110_Basic库 (Nokia 5110 驱动) - 使用第二串口
Serial1(RX0/TX1) 与 MP3 模块通信
步骤 6:串口 MP3 模块 (OPEN-SMART) 控制命令
MicroSD 卡格式化为 FAT16/32,建立 01 文件夹,歌曲命名为 001xxx.mp3、002xxx.mp3...。
核心 UART 命令 (均以 7E 开头,EF 结尾):
选择 TF 卡: 7E 03 35 01 EF
播放第1首: 7E 04 41 00 01 EF
播放第2首: 7E 04 41 00 02 EF
... 以此类推
播放: 7E 02 01 EF
暂停: 7E 02 02 EF
下一首: 7E 02 03 EF
上一首: 7E 02 04 EF
Arduino 端封装 send_command_to_MP3_player() 函数通过 Serial1 发送字节数组。
步骤 7:Arduino 固件编程要点
- 包含库、配置 WiFi SSID/密码、树莓派 IP 与应用路径
- 初始化 Nokia 5110、定义图标图像、MP3 命令数组
- 菜单系统:
Init Tracker/MP3 Player/Sleep三模式,左右键切换,OK 键确认 Init Tracker模式:HTTP GET 请求query.php,解析 % 分隔符字段,显示剧集信息、播放对应片头曲、RGB LED 显示剧集专属颜色MP3 Player模式:按键控制上一首/下一首/暂停Sleep模式:10 秒倒计时进入睡眠,RGB 呼吸灯作夜灯,退出键唤醒







接线对照表
Arduino Nano 33 IoT:
Nokia 5110: D2-SCK, D3-MOSI, D4-DC, D5-RST, D6-CS
RGB LED: D9-R, D10-G, D11-B
按键: A0-Left, A1-OK, A2-Right, A3-Exit
DS3231(可选): A4-SDA, A5-SCL



模式与功能详解
A. Init Tracker (追踪模式)
- 连接 WiFi 后显示
Connected to WiFi!!! - 进入菜单,选中
A.Init Tracker按 OK - 连接服务器成功显示
Connected to the server!!! - 检测到新剧集:显示剧名、季数、集数、集名;播放片头曲;RGB 亮对应色(如 One Piece→红,My Hero Academia→绿);长按 Exit 退出
- 无新剧集:显示
No Released Episode Detected :(,显示电视图标倒计时 10 秒后重新查询 - 每集仅通知一次(状态从 Pending 变 Released 防重复)
B. MP3 Player (音乐播放器)
- 显示音符图标,按键控制:Right-下一首,Left-上一首,OK-暂停,Exit-返回菜单
C. Sleep (睡眠/夜灯模式)
- 10 秒倒计时进入睡眠,LCD 关屏
- RGB 循环变色(红/绿/蓝/黄/紫,每色 500ms) 作夜灯
- Exit 键唤醒回菜单
成果展示
用热熔胶固定在书架上,运行完美!


核心代码文件
Series_Release_Date_Notifier.ino (Arduino 主程序)
// TV Series / Anime New Episode Release Date Notifier
// Arduino Nano 33 IoT - by Kutluhan Aktar
#include
#include
#include
// WiFi 配置
char ssid[] = "[_SSID_]";
char pass[] = "[_PASSWORD_]";
IPAddress server(192, 168, 1, 22); // 树莓派 IP
String application = "/TV-Series-Anime-Episode-Tracker/query.php";
// 使用在线版时替换为:
// char server[] = "www.theamplituhedron.com";
// String HEDRON = "[_HEDRON_]";
// String application = "/dashboard/TV-Series-Anime-Episode-Tracker/" + HEDRON;
WiFiClient client; // 或 WiFiSSLClient (HTTPS)
LCD5110 myGLCD(2,3,4,5,6);
extern uint8_t SmallFont[], MediumNumbers[], tv[], music[];
// MP3 命令数组 (同上)
static int8_t select_SD_card[] = {0x7e, 0x03, 0X35, 0x01, 0xef};
static int8_t play_song_1[] = {0x7e, 0x04, 0x41, 0x00, 0x01, 0xef};
// ... play_song_2 到 play_song_5, play, pause, next_song, previous_song
volatile boolean TV = false, Music = false, Sleep = false, Activated = false;
#define B_Exit A3; #define B_Right A2; #define B_OK A1; #define B_Left A0
#define redPin 9; #define greenPin 10; #define bluePin 11
void setup() {
// 引脚初始化、RGB熄灭、LCD初始化、Serial1(9600)启动MP3、选TF卡
// WiFi连接循环,LCD显示连接状态
}
void loop() {
read_buttons(); change_menu_options(); interface();
if(TV) { /* 连接服务器、解析响应、显示播放、倒计时重查 */ }
if(Music) { /* 绘制音符图标、按键控制MP3 */ }
if(Sleep) { /* 10秒倒计时、进入睡眠、RGB呼吸灯、Exit唤醒 */ }
}
// 关键函数:按键读取、菜单切换、界面绘制、MP3发送、RGB调色
// 解析响应示例:
if(response.endsWith("%")) {
int d1=response.indexOf("%"), d2=response.indexOf("%",d1+1);
int d3=response.indexOf("%",d2+1), d4=response.indexOf("%",d3+1);
String Series_Name = response.substring(d1+1, d2);
String Season = response.substring(d2+1, d3);
String Episode = response.substring(d3+1, d4);
String Episode_Name = response.substring(d4+1, response.indexOf("%",d4+1));
// 显示并根据 Series_Name 播放对应歌曲、设置RGB颜色
}
index.php (建表)
<?php
$conn = mysqli_connect("localhost", "root", "bot", "tvseries");
function checkDatabase($table, $conn) {
return mysqli_num_rows(mysqli_query($conn, "SHOW TABLES FROM `tvseries` LIKE '$table'")) > 0;
}
function createTable($table, $conn) {
if(!checkDatabase($table, $conn)) {
$sql = "CREATE TABLE `$table`( id int(11) AUTO_INCREMENT PRIMARY KEY NOT NULL, series_name varchar(255) NOT NULL, tv_id varchar(255) NOT NULL, status varchar(255) NOT NULL );";
echo mysqli_query($conn, $sql) ? "Database Table Created!" : "Error!";
} else echo "Database Table Found!";
}
createTable("series", $conn);
?>
query.php (查询 API 并返回数据)
<?php
error_reporting(0);
class query {
const ROOT = "https://api.tvmaze.com/shows/";
const PATH = "/episodesbydate?date=";
public $conn, $table_name;
public function define_user($conn, $table) { $this->conn=$conn; $this->table_name=$table; }
private function check_ep_release_date($API_ID, $series_name, $status) {
$date = date("Y-m-d");
$URL = self::ROOT.$API_ID.self::PATH.$date;
if($get_content = json_decode(file_get_contents((String)$URL))) {
if($status != "Released") {
echo "%".$series_name."%".$get_content[0]->season."%".$get_content[0]->number."%".$get_content[0]->name."%";
mysqli_query($this->conn, "UPDATE `$this->table_name` SET `status`='Released' WHERE series_name='$series_name'");
}
} else {
if($status != "Pending") mysqli_query($this->conn, "UPDATE `$this->table_name` SET `status`='Pending' WHERE series_name='$series_name'");
}
}
public function track_db_entries() {
$sql = "SELECT * FROM `$this->table_name` ORDER BY `id` DESC";
if($result = mysqli_query($this->conn, $sql)) {
if(mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) $this->check_ep_release_date($row['tv_id'], $row['series_name'], $row['status']);
} else echo "No Entry Found!";
} else echo "No Database Found!";
}
}
$conn = mysqli_connect("localhost", "root", "bot", "tvseries");
$q = new query(); $q->define_user($conn, "series"); $q->track_db_entries();
?>
附件资源
- Gerber 文件:
gerber_ycEfXzZq6h.zip - Web 应用源码:
tv-series-anime-episode-tracker_gCfN0nFiA8.zip - 片头曲打包:
opening_songs_y2LCEw79tg.zip - 图标数据:
tv_Iz2isO8nGI.c,music_SA2xR86cZw.c
原理图




制造工艺
- 树莓派 LIRC 通用红外遥控器专业构建指南
- 树莓派射频转直流:包络检波器构建与故障排查
- Cycle Chaser:树莓派让自行车变身夜间光影秀
- 树莓派防窃报警器 DIY:压力触发播放警报声
- 树莓派 + MCP9808 + InfluxDB + Grafana:家庭温度监测系统
- 树莓派打造家庭自动化系统:手机远程控制灯风扇大门
- 树莓派 3 B+ – 更新特性、规格与选购指南
- DIY仿Wall-E树莓派CD盒机器人
- RasPiRobot Board V2:将树莓派扩展为强大机器人控制器
- 树莓派 2 运行 Windows IoT Core 打造 Rover 机器人:从入门到进阶指南
- Eclipse Hono发布基于MongoDB的设备注册表:可扩展、生产就绪
- Schaffner 推出集成 IEC C14 电源入口模块的 FN 9262/9266 射频干扰滤波器,面向医疗与消费应用