DIY 吃豆人 LED 像素面板万圣节服装:全家 8-bit 发光套装制作指南
项目背景与灵感
全家装扮主题选定为《吃豆人》:吃豆人、吃豆小姐、红鬼 Blinky、粉鬼 Pinky。核心需求:
- 还原街机原版 8-bit 精灵动画 (嘴巴开合、鬼眼睛转动、脚部摆动)
- 全家统一像素尺寸,适配最小成员 (儿子) 肩宽
- 轻量化、可穿戴、电池续航 ≥ 3 小时
- 带声音效果 (吃豆人音效/背景音乐)
像素规格与面板尺寸设计
| 角色 | 精灵分辨率 | 像素尺寸 | 面板物理尺寸 | LED 总数 |
|---|---|---|---|---|
| 鬼 (Blinky/Pinky) | 14 × 14 | 1.57 英寸/像素 | 22″ × 22″ (56 × 56 cm) | 170 |
| 吃豆人 | 13 × 13 | 1.57 英寸/像素 | 20.4″ × 20.4″ | 137 |
| 吃豆小姐 | 14 × 14 | 1.57 英寸/像素 | 22″ × 22″ | 151 |
像素间距 1.57″ (40mm) 由最小成员肩宽反推。LED 串灯珠间距 3″ (75mm),布局时需相邻像素对应串灯相邻灯珠,避免剪线重焊。
材料清单 (BOM)
| 材料 | 规格/数量 | 备注 |
|---|---|---|
| 底板 | 3mm 瓦楞纸板 / 3mm 胶合板 | 激光切割或手工刀切割 |
| 像素格栅 (竖/横条) | 同材质,厚度匹配 | 榫卯结构插接,免胶定位 |
| 漫射面板 | 描图纸 / Vellum / Mylar 卷材 | 宽度覆盖整面板,白乳胶粘顶边 |
| WS2811 12mm 单线可编程 LED 串 | 50 颗/串,鬼需 4 串 (200 颗留余量) | DC 5V,单线控制,全彩 |
| Arduino Uno R3 | 1 块/套装 | 每套装独立控制器 |
| 移动电源 (Power Bank) | 5V 2A+,2200mAh 约 4h / 7800mAh 约 12h | USB 转 DC 5.5×2.1mm 公头线 |
| 魔术贴、织带背带、胶带、热熔胶 | 若干 | 固定电路板、背负系统 |
| 蓝牙音箱 + 手机 | 1 套 | 播放吃豆人音效/BGM |
面板结构设计与激光切割
参数化建模 (Rhino / Fusion 360)
- 基板:正方形,边长 22″,四周留 1″ 边距
- 竖向格栅:14 根,宽 3/16″ (4.8mm),间距 1.57″,中部开十字槽与横向咬合
- 横向格栅:14 根,同规格,与竖向插接形成 14×14 网格
- 每个网格中心开 12mm 圆孔 (LED 灯珠座)
- 基板对应位置开十字缺口,格栅插入后热熔胶加固角落
- 基板分两半拼接 (激光切割床面 32″×18″ 限制),胶带临时固定,格栅插入后自锁
教训:背部未封箱导致行走时 LED 被身体挤入格栅内,建议加 2.5″ 高围板全封闭背部。
切割文件下载
- 鬼面板 DWG:ghostlaser-1_8th_v5.dwg (32″×18″ 床面)
- 吃豆人/吃豆小姐 DWG:pacman-mspacman-laser.dwg
- 无激光切割条件:打印 PDF 1:1 贴纸板手工切割,或按尺寸手绘锯切
LED 布局与接线
Excel 像素编号映射
按蛇形/扫描线顺序给 170 个像素编号 0~169,确保物理相邻像素在串口序列中也相邻,减少导线跨越。起始点 (0号) 置于靠近 Arduino 安装位置的角落。
接线拓扑
移动电源 (5V USB) → USB转DC母头 → LED串第1颗红/白线 (VCC/GND)
↓
LED串第1颗绿线 (DATA) → Arduino D3
↓
级联连接后续 LED 串 (VCC/GND/DATA 并联)
↓
最后一颗悬空
Arduino D3 → 470Ω 电阻 → LED串 DATA (推荐加电阻保护)
Arduino GND ↔ 电源 GND 共地
关键:确认你手中 LED 串线序 (红=VCC, 绿=DATA, 白=GND) 或用万用表实测,接反会烧灯珠。
动画代码设计模式 (FastLED 库)
核心思想:全屏填充主色 → 逐帧修改特定像素索引为特征色/关灯,而非逐像素绘制。每帧调用 FastLED.show() 推送缓冲区。
鬼角色动画逻辑 (Blinky/Pinky)
#include
#define NUM_LEDS 170
#define DATA_PIN 3
CRGB leds[NUM_LEDS];
// 预计算特征像素索引数组 (从 Excel 导出)
int eyes_pixels_l[] = {17,20,21,24,37,38,39,40,41,47,48,49,94,102,103,106,119,120,121,122,123,129,130,131};
int pupils_pixels_l[] = {15,16,22,23,92,93,104,105};
int eyes_pixels_r[] = {38,39,40,46,47,48,49,50,63,66,67,75,120,121,122,128,129,130,131,132,145,148,149,152};
int pupils_pixels_r[] = {64,65,76,77,146,147,153,154};
int void_pixels_1[] = {8,29,30,31,83,84,85,86,138,139,140,161}; // 脚部遮挡帧1
int void_pixels_2[] = {7,31,55,56,57,112,113,114,138,162}; // 脚部遮挡帧2
int sad_ghost[] = {11,26,35,48,49,53,60,64,65,80,89,104,105,109,116,120,121,134,143,158}; // 被吃表情
const int feet_delay = 120; // 脚部动画帧间隔 ms
const int eye_loop = 16; // 左右看循环次数 (2秒/120ms)
const int reg_ghost_loop = 5; // 正常循环 5 次 (10秒)
const int sad_ghost_loop = 50; // 被吃循环
void setup() {
delay(2000);
FastLED.addLeds(leds, NUM_LEDS);
FastLED.setBrightness(40); // 0-255, 省电护眼
FastLED.clear();
}
void loop() {
// 正常巡逻:红身 + 白眼 + 蓝瞳 + 脚部交替
for (int cycle = 0; cycle < reg_ghost_loop; cycle++) {
// 看左
for (int i = 0; i < eye_loop; i++) {
render_frame(CRGB::Red, eyes_pixels_l, pupils_pixels_l, void_pixels_1);
delay(feet_delay);
render_frame(CRGB::Red, eyes_pixels_l, pupils_pixels_l, void_pixels_2);
delay(feet_delay);
}
// 看右
for (int i = 0; i < eye_loop; i++) {
render_frame(CRGB::Red, eyes_pixels_r, pupils_pixels_r, void_pixels_1);
delay(feet_delay);
render_frame(CRGB::Red, eyes_pixels_r, pupils_pixels_r, void_pixels_2);
delay(feet_delay);
}
}
// 被吃动画:蓝身 + 黄眼 + 眨眼
for (int i = 0; i < sad_ghost_loop; i++) {
render_frame(CRGB::Blue, sad_ghost, NULL, void_pixels_1); delay(feet_delay);
render_frame(CRGB::Blue, sad_ghost, NULL, void_pixels_2); delay(feet_delay);
}
// 眨眼闪白
for (int i = 0; i < 10; i++) {
render_frame(CRGB::Yellow, sad_ghost, NULL, void_pixels_1); delay(feet_delay);
render_frame(CRGB::Blue, sad_ghost, NULL, void_pixels_2); delay(feet_delay);
}
}
// 通用渲染函数
void render_frame(CRGB body_color, int* feature_pixels, int* pupil_pixels, int* void_pixels) {
fill_solid(leds, NUM_LEDS, body_color);
if (feature_pixels) for (int i=0; i<24; i++) leds[feature_pixels[i]] = CRGB::White;
if (pupil_pixels) for (int i=0; i<8; i++) leds[pupil_pixels[i]] = CRGB::DarkBlue;
if (void_pixels) for (int i=0; i< (void_pixels==void_pixels_1?12:10); i++) leds[void_pixels[i]] = CRGB::Black;
FastLED.show();
}
吃豆人/吃豆小姐:嘴巴开合动画
// 吃豆人 137 LED
int void_pixels_opened[] = {19,20,21,22,23,24,25,26,27,28,29,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,94,95,96,97,98,99,100,101,102,103,104,105,121,122,123,124,125,126};
int void_pixels_mid[] = {46,47,48,49,50,51,52,53,54,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,98,99,100};
// 吃豆小姐 151 LED (含红蝴蝶结/蓝眼/黑轮廓像素索引数组略)
void loop() {
// 张嘴
fill_solid(leds, NUM_LEDS, CRGB::Yellow);
for (int i : void_pixels_opened) leds[i] = CRGB::Black;
set_feature_colors(); // 设置红/蓝/黑特征像素
FastLED.show(); delay(100);
// 半张
fill_solid(leds, NUM_LEDS, CRGB::Yellow);
for (int i : void_pixels_mid) leds[i] = CRGB::Black;
set_feature_colors();
FastLED.show(); delay(100);
// 闭嘴
fill_solid(leds, NUM_LEDS, CRGB::Yellow);
set_feature_colors();
FastLED.show(); delay(100);
// 半张
fill_solid(leds, NUM_LEDS, CRGB::Yellow);
for (int i : void_pixels_mid) leds[i] = CRGB::Black;
set_feature_colors();
FastLED.show(); delay(100);
}
穿戴系统集成
- 电子模块固定:Arduino + 移动电源用魔术贴贴在面板背部 (若有背箱则内置)
- 线缆管理:数据/电源线沿格栅走线,胶带固定,预留松弛量
- 背带系统:织带背带 (可调节长度) 通过基板预留槽穿过,双肩背负,重心在胸前
- 声音系统:手机蓝牙连音箱,音箱塞入口袋或粘背带上,循环播放 吃豆人音效包
实测续航数据
| 移动电源容量 | 实测亮灯时长 | 亮度设置 |
|---|---|---|
| 2200 mAh (唇膏充) | 3 小时 40 分钟 | Brightness 40/255 |
| 7800 mAh | 12 小时 43 分钟 | Brightness 40/255 |
| 10000 mAh (推荐) | > 16 小时 | Brightness 40/255 |
⚠️ 切勿用 8×AA 电池盒 (12V) 直供 5V LED,虽能亮但会过压损坏灯珠且续航极短 (仅 2h)。
进阶优化建议
- 改用 ESP32 + Web 端控制:手机网页切换动画模式、亮度、颜色,无需重刷代码
- 加装 MPU6050:检测行走步频,同步脚部动画频率;倾斜触发「被吃」动画
- 红外同步:多套装之间 IR 同步,鬼追吃豆人时自动切换追逐/逃跑动画
- 声控触发:麦克风模块检测「Waka Waka」声触发吃豆人张嘴
- 升级为 APA102 (SPI) 或 SK9822:更高刷新率、无时序敏感、支持全局亮度寄存器
完整代码文件下载
- 鬼动画:LED_Ghost_Animation.ino
- 吃豆人:Pacman.ino
- 吃豆小姐:MsPacman.ino
原理图与切割文件
- 接线示意图:schematic_wiring.jpg
- 鬼面板切割 DWG:ghostlaser-1_8th_v5.dwg
- 吃豆人/吃豆小姐切割 DWG:pacman-mspacman-laser.dwg
这个项目完美融合了机械设计、电子电路、嵌入式编程、可穿戴工程与家庭娱乐。从 Excel 像素映射到 FastLED 帧渲染,从激光切割榫卯结构到移动电源续航实测,每个环节都充满实战干货。万圣节、漫展、家庭派对,这套 8-bit 发光全家装绝对是全场焦点!
制造工艺
- 发光二极管:从诞生到百年寿命
- Arduino Nano飞行模拟2020控制面板——LCD与CDI显示
- Arduino 飞行模拟器 2020 实体开关面板
- Arduino复刻“棺材舞”旋律:蜂鸣器+三色LED灯光秀完整教程
- DIY 云朵发光服装 — LED 灯带 + Arduino Nano + SparkFun 元件
- 用 Arduino Mega 制作惊艳的 5×5×5 LED 光立方
- Arduino + HC-05 蓝牙控制 LED:MIT App Inventor 手机 App 开发全攻略
- 声控 8 路 LED 灯光秀:Arduino 入门项目
- 从零构建智能 Arduino 四足机器人:完整指南
- Pixel Chaser:Arduino Nano 单键 NeoPixel 追逐小游戏
- Arduino RGB LED调色器:三电位器混色入门项目
- DIY 节日影子剧场:Arduino 与可寻址 LED 灯条打造光影秀