📋 项目简介
本项目使用 ESP32 微控制器配合 OLED 显示屏和无源蜂鸣器,打造了一个具有*8种视觉特效*和*生日快乐歌伴奏*的酷炫显示系统。开机时会播放完整的生日快乐歌,同时配合视觉动画,非常适合用作生日礼物或创意展示项目。
🔧 硬件清单
1. ESP32 开发板
功能: 主控芯片,负责运算和控制
参数:
双核 240MHz 处理器
内置 Wi-Fi 和蓝牙
GPIO 丰富,支持 I2C/SPI 等多种通信协议
工作电压:3.3V
- ESP32开发板实物图片
2. OLED 显示屏(SSD1306)
功能: 图形显示输出
参数:
分辨率:128×64 像素
通信方式:I2C
驱动芯片:SSD1306
工作电压:3.3V-5V
屏幕尺寸:0.96英寸
- OLED显示屏实物图片
3. 无源蜂鸣器模块(高电平触发)
功能: 播放音乐旋律
参数:
类型:无源蜂鸣器(Passive Buzzer)
触发方式:高电平触发
工作电压:3.3V-5V
频率范围:100Hz - 10kHz
可播放不同音调(用于演奏旋律)
- 无源蜂鸣器实物图片
⚠️ 重要提醒:必须使用*无源蜂鸣器*!有源蜂鸣器只能发出单一"嘀嘀"声,无法播放生日快乐歌。
*识别方法*:
✅ 无源蜂鸣器:背面是绿色 PCB 电路板
❌ 有源蜂鸣器:背面是黑色圆盘贴片
4. 其他配件
杜邦线若干(母对母/公对母)
USB 数据线(Micro-USB 或 Type-C,根据 ESP32 型号)
面包板(可选,方便接线)
🔌 硬件连接
接线图
ESP32 → OLED 显示屏
GPIO6 (SDA) → SDA
GPIO7 (SCL) → SCL
3.3V → VCC
GND → GND
ESP32 → 无源蜂鸣器模块
GPIO5 → I/O (信号输入)
3.3V/5V → VCC
GND → GND
接线示意图
┌──────────────┐
│ ESP32 │
│ │
│ GPIO6 ──────┼──→ OLED SDA
│ GPIO7 ──────┼──→ OLED SCL
│ GPIO5 ──────┼──→ 蜂鸣器 I/O
│ │
│ 3.3V ──────┼──→ OLED VCC + 蜂鸣器 VCC
│ GND ──────┼──→ OLED GND + 蜂鸣器 GND
└──────────────┘
💻 软件环境配置
1. Arduino IDE 设置
1. 安装 Arduino IDE(版本 1.8.x 或 2.x)
ARDUINO IDE下载地址 https://www.arduino.cc/en/software/
2. 添加 ESP32 支持包:
- 文件 → 首选项 → 附加开发板管理器网址
- 添加:https://dl.espressif.com/dl/package_esp32_index.json
(备用地址:ESP32 Arduino 开发板管理器地址(国内镜像): https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json)
- 工具 → 开发板管理器 → 搜索"ESP32" → 安装
3. 安装依赖库:
- 工具 → 管理库 → 搜索并安装:
- `Adafruit GFX Library`
- `Adafruit SSD1306`
![Arduino IDE库管理器]
🎨 位图取模说明
本项目使用了自定义位图显示 "iEasy商城6周年快乐!",这是通过*字模提取软件*生成的点阵数据。
这个项目中我用的是第一个的图形模式尽心绘画的!!!!
AI设计并自己修改了一些
完整取模数据(C语言数组格式)
将以下数据添加到代码中,用于显示自定义文字:
// "iEasy商城6周年快乐!" 字模数据 (16x16点阵)//这个在实际中应用可能出现些许问题,但下面的那个没有任何问题!!!!!!!!
const unsigned char customText[][32] PROGMEM = {
// i (0)
{0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x70,
0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00},
// C (1)
{0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x80, 0x80,
0x80, 0x80, 0x80, 0x42, 0x44, 0x38, 0x00, 0x00},
// E (2)
{0x00, 0x00, 0x00, 0xFC, 0x42, 0x48, 0x48, 0x78,
0x48, 0x48, 0x40, 0x42, 0x42, 0xFC, 0x00, 0x00},
// a (3)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C,
0x42, 0x1E, 0x22, 0x42, 0x42, 0x3F, 0x00, 0x00},
// s (4)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E,
0x42, 0x40, 0x3C, 0x02, 0x42, 0x7C, 0x00, 0x00},
// y (5)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7,
0x42, 0x24, 0x24, 0x28, 0x18, 0x10, 0x10, 0xE0},
// 商 (6)
{0x00, 0x00, 0x00, 0x01, 0x00, 0x7F, 0xFE, 0x08,
0x10, 0x04, 0x20, 0x1F, 0xF8, 0x60, 0x06, 0x44,
0x22, 0x58, 0x1A, 0x47, 0xF2, 0x48, 0x12, 0x48,
0x12, 0x48, 0x12, 0x4F, 0xF2, 0x40, 0x1A, 0x00},
// 城 (7)
{0x00, 0x00, 0x00, 0x20, 0x20, 0x24, 0x23, 0xFC,
0x24, 0x22, 0x24, 0x20, 0x7C, 0x24, 0x27, 0xE4,
0x24, 0x54, 0x24, 0x58, 0x24, 0x58, 0x2C, 0x58,
0x34, 0x9A, 0x65, 0xAA, 0x04, 0x4A, 0x08, 0x86},
// 6 (8)
{0x00, 0x00, 0x00, 0x1C, 0x24, 0x40, 0x40, 0x58,
0x64, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00},
// 周 (9)
{0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x41, 0x04,
0x4F, 0xFC, 0x41, 0x04, 0x41, 0x04, 0x5F, 0xFC,
0x40, 0x04, 0x4F, 0xF4, 0x48, 0x14, 0x48, 0x14,
0x48, 0x14, 0x4F, 0xF4, 0x40, 0x04, 0x80, 0x3C},
// 年 (10)
{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0F, 0xFE,
0x10, 0x80, 0x20, 0x80, 0x40, 0x80, 0x0F, 0xFE,
0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x7F, 0xFE,
0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80},
// 快 (11)
{0x00, 0x00, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40,
0x5B, 0xFC, 0x58, 0x44, 0x54, 0x44, 0x94, 0x44,
0x90, 0x44, 0x97, 0xFE, 0x10, 0x60, 0x10, 0x90,
0x10, 0x90, 0x11, 0x08, 0x12, 0x04, 0x14, 0x02},
// 乐 (12)
{0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x1C, 0x00,
0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80,
0x20, 0x80, 0x1F, 0xFC, 0x08, 0x90, 0x10, 0x88,
0x10, 0x88, 0x20, 0x84, 0x40, 0x84, 0x47, 0x02},
// ! (13)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x0C, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}
};
- 上述OLED图片显示的字模!!!
// 您的位图数据 //这个是上面的那个0.96OLED(IIC)上显示的图片的字模!!!!!!
//!!!!!!
//!!!!!!!
const unsigned char bitmap[] PROGMEM = {
0x3C, 0x00, 0x03, 0xF0, 0x00, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE0, 0x00, 0x0E, 0x1E, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0xC0,
0x80, 0x00, 0xF8, 0x03, 0xC0, 0x08, 0x08, 0x10, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0xC0,
0x00, 0x03, 0x80, 0x30, 0x70, 0x08, 0x08, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xC0,
0x00, 0x1E, 0x00, 0x60, 0x11, 0x08, 0x18, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0xF0,
0x00, 0xF0, 0x00, 0xC0, 0x10, 0x08, 0x60, 0x10, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0,
0x0F, 0x80, 0x00, 0x80, 0x10, 0x09, 0x80, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
0x38, 0x00, 0xF8, 0x80, 0x10, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0xC0,
0x60, 0x01, 0x88, 0x7E, 0x10, 0x08, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x80,
0x00, 0x03, 0x08, 0x03, 0x10, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x1C, 0x01, 0xC0, 0x10, 0x00,
0x00, 0x42, 0x08, 0x01, 0x10, 0x00, 0xF8, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0xE0, 0x10, 0x00,
0x00, 0xC2, 0x18, 0x23, 0x10, 0x03, 0x88, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x10, 0x00,
0x00, 0x82, 0x71, 0x1E, 0x10, 0x1F, 0x08, 0x40, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x38, 0x30, 0x00,
0x00, 0x83, 0xC3, 0x00, 0x10, 0x71, 0x09, 0xC0, 0x02, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x21, 0x81, 0x86, 0x00, 0x13, 0xC1, 0x0F, 0xC0, 0x07, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
0x31, 0x00, 0xFC, 0x00, 0x1E, 0x41, 0xFE, 0x40, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x78, 0x43, 0xF8, 0x40, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00,
0x09, 0x81, 0x00, 0x00, 0xF0, 0x47, 0x08, 0x40, 0x00, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x0E, 0x00,
0x08, 0x83, 0x00, 0x03, 0x90, 0x7F, 0x08, 0x40, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x11, 0x00,
0x0C, 0xC6, 0x00, 0x1F, 0x10, 0xF1, 0x08, 0x40, 0x00, 0x00, 0x03, 0x00, 0x03, 0x80, 0x24, 0x80,
0x06, 0x7C, 0x00, 0x7A, 0x13, 0xC1, 0x08, 0x40, 0x00, 0x00, 0x43, 0x00, 0x01, 0x00, 0x2C, 0x80,
0x02, 0x00, 0x1F, 0xC6, 0x1E, 0x41, 0x08, 0x40, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x28, 0x80,
0x03, 0x00, 0x3C, 0x8A, 0x70, 0x41, 0x09, 0xE0, 0x10, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x80,
0x00, 0x01, 0xE1, 0x57, 0xD0, 0x41, 0x0F, 0x80, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x80,
0x00, 0x0F, 0x22, 0x25, 0x10, 0x41, 0x3C, 0x00, 0x28, 0x00, 0x03, 0x1F, 0xFF, 0x00, 0x11, 0x00,
0x00, 0xF8, 0x54, 0x3E, 0x10, 0x43, 0xE0, 0x00, 0x00, 0x00, 0x03, 0x3F, 0xFF, 0x83, 0x0A, 0x00,
0x07, 0x88, 0x88, 0xE4, 0x10, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x03, 0x70, 0x01, 0xC3, 0x04, 0x00,
0x3C, 0x15, 0x07, 0x04, 0x10, 0x5B, 0x00, 0x80, 0x00, 0x00, 0x03, 0xE0, 0x00, 0xE0, 0x0E, 0x00,
0xFA, 0x22, 0x1E, 0x04, 0x10, 0xF1, 0x80, 0x80, 0x00, 0x08, 0x03, 0xC0, 0x00, 0x70, 0x04, 0x08,
0x89, 0x40, 0xF2, 0x04, 0x17, 0xB0, 0xC1, 0x40, 0x00, 0x0C, 0x03, 0x86, 0x0C, 0x38, 0x04, 0x18,
0x08, 0x8F, 0x83, 0x04, 0x3C, 0x18, 0x60, 0x00, 0x00, 0x08, 0x03, 0x0F, 0x1E, 0x18, 0x04, 0x10,
0x08, 0x78, 0x83, 0x04, 0xE6, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x03, 0x19, 0xB3, 0x18, 0x06, 0x00,
0x0F, 0xE0, 0xC2, 0x07, 0x83, 0x06, 0x18, 0x00, 0x00, 0x00, 0x03, 0x18, 0xE3, 0x18, 0x02, 0x00,
0x0C, 0x21, 0xC3, 0x7C, 0x01, 0x83, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x18, 0x43, 0x18, 0x02, 0x00,
0x18, 0x21, 0x87, 0xC0, 0x00, 0xC1, 0x86, 0x00, 0x00, 0x00, 0x03, 0x18, 0x0B, 0x18, 0x01, 0x00,
0x10, 0x60, 0x8F, 0x80, 0x10, 0x60, 0xC3, 0x00, 0x01, 0x00, 0x03, 0x18, 0x1B, 0x18, 0x01, 0x00,
0x10, 0x60, 0xFB, 0x80, 0x10, 0x30, 0x61, 0x80, 0x01, 0x00, 0x03, 0x18, 0x13, 0x18, 0x01, 0x00,
0x50, 0x21, 0xC1, 0xC0, 0x28, 0x18, 0x30, 0xC0, 0x02, 0x80, 0x03, 0x18, 0x03, 0x18, 0x01, 0x00,
0x70, 0x3E, 0x01, 0xC0, 0x00, 0x0C, 0x18, 0x71, 0xC4, 0x40, 0x03, 0x0C, 0x06, 0x18, 0x80, 0x00,
0x70, 0xF0, 0x00, 0xE0, 0x00, 0x06, 0x0C, 0x3B, 0x98, 0x30, 0x03, 0x06, 0x0C, 0x19, 0x81, 0x00,
0x77, 0x38, 0x00, 0xF0, 0x00, 0x03, 0x06, 0x1E, 0x04, 0x40, 0x23, 0x03, 0x18, 0x18, 0x80, 0x00,
0x3C, 0x38, 0x03, 0xC0, 0x00, 0x41, 0x83, 0x78, 0x02, 0x80, 0x23, 0x81, 0xB0, 0x38, 0x01, 0x00,
0xF0, 0x1C, 0x0E, 0x00, 0x40, 0x40, 0xC1, 0xF0, 0x01, 0x00, 0x21, 0xC0, 0xE0, 0x70, 0x14, 0x60,
0x80, 0x0C, 0x7C, 0x00, 0x40, 0xA0, 0x67, 0xC0, 0x01, 0x00, 0x60, 0xE0, 0x40, 0xE0, 0x01, 0x00,
0x00, 0x0F, 0xE0, 0x00, 0xA0, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0xC0, 0x00, 0x00,
0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x88, 0x02, 0x80,
0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x0C, 0x08, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0xFE, 0x10, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80,
0x0C, 0x0F, 0x1F, 0x87, 0xE0, 0xFE, 0x18, 0x31, 0x00, 0xF0, 0x3F, 0x8F, 0xE2, 0x20, 0x03, 0x04,
0x0C, 0x1D, 0x1F, 0x8C, 0x60, 0xC6, 0x0C, 0x23, 0x81, 0x08, 0x24, 0x91, 0x02, 0x20, 0x1C, 0x04,
0x00, 0x30, 0x18, 0x08, 0x30, 0xC0, 0x04, 0x65, 0x42, 0x00, 0x2E, 0xA1, 0x02, 0xFC, 0x20, 0x04,
0x0C, 0x30, 0x18, 0x00, 0x30, 0xC0, 0x06, 0xCD, 0x62, 0x00, 0x24, 0x8F, 0xC3, 0x24, 0x22, 0x04,
0x0C, 0x60, 0x18, 0x00, 0x30, 0xFC, 0x03, 0x95, 0x52, 0x00, 0x2E, 0x89, 0x02, 0xA8, 0x22, 0x04,
0x0C, 0x60, 0x1F, 0x03, 0xF0, 0x7E, 0x01, 0x9F, 0xF2, 0xF0, 0x20, 0x89, 0x02, 0x30, 0x22, 0x04,
0x0C, 0x60, 0x1F, 0x06, 0x60, 0x06, 0x03, 0x08, 0x23, 0x08, 0x24, 0xBF, 0xE3, 0xFF, 0x1F, 0xC4,
0x0C, 0x70, 0x18, 0x0C, 0x30, 0x06, 0x06, 0x0F, 0x22, 0x08, 0x2A, 0x81, 0x0A, 0x20, 0x02, 0x00,
0x0C, 0x30, 0x18, 0x0C, 0x30, 0xC6, 0x0C, 0x09, 0x22, 0x08, 0x4A, 0x81, 0x12, 0x20, 0x0A, 0x84,
0x0C, 0x1D, 0x1F, 0x8E, 0x70, 0xFE, 0x18, 0x0D, 0x22, 0x08, 0x44, 0x81, 0x02, 0x50, 0x12, 0x40,
0x0C, 0x0F, 0x1F, 0x87, 0xEC, 0xFE, 0x30, 0x09, 0x21, 0x10, 0x80, 0x81, 0x02, 0x48, 0x22, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1F, 0xF0, 0xE1, 0x01, 0x81, 0x02, 0x87, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
- 完整Arduin代码!!!
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define BUZZER_PIN 5 // �� 改成你的蜂鸣器引脚
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ============ 音符频率定义 ============
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_D5 587
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_G5 784
// 生日快乐歌旋律
int birthdayMelody[] = {
NOTE_G4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_C5, NOTE_B4,
NOTE_G4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_D5, NOTE_C5,
NOTE_G4, NOTE_G4, NOTE_G5, NOTE_E5, NOTE_C5, NOTE_B4, NOTE_A4,
NOTE_F5, NOTE_F5, NOTE_E5, NOTE_C5, NOTE_D5, NOTE_C5
};
int birthdayDurations[] = {
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2
};
// 位图数据
const unsigned char bitmap[] PROGMEM = {
0x3C, 0x00, 0x03, 0xF0, 0x00, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE0, 0x00, 0x0E, 0x1E, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0xC0,
0x80, 0x00, 0xF8, 0x03, 0xC0, 0x08, 0x08, 0x10, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0xC0,
0x00, 0x03, 0x80, 0x30, 0x70, 0x08, 0x08, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xC0,
0x00, 0x1E, 0x00, 0x60, 0x11, 0x08, 0x18, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0xF0,
0x00, 0xF0, 0x00, 0xC0, 0x10, 0x08, 0x60, 0x10, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0,
0x0F, 0x80, 0x00, 0x80, 0x10, 0x09, 0x80, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
0x38, 0x00, 0xF8, 0x80, 0x10, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0xC0,
0x60, 0x01, 0x88, 0x7E, 0x10, 0x08, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x80,
0x00, 0x03, 0x08, 0x03, 0x10, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x1C, 0x01, 0xC0, 0x10, 0x00,
0x00, 0x42, 0x08, 0x01, 0x10, 0x00, 0xF8, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0xE0, 0x10, 0x00,
0x00, 0xC2, 0x18, 0x23, 0x10, 0x03, 0x88, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x10, 0x00,
0x00, 0x82, 0x71, 0x1E, 0x10, 0x1F, 0x08, 0x40, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x38, 0x30, 0x00,
0x00, 0x83, 0xC3, 0x00, 0x10, 0x71, 0x09, 0xC0, 0x02, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x21, 0x81, 0x86, 0x00, 0x13, 0xC1, 0x0F, 0xC0, 0x07, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
0x31, 0x00, 0xFC, 0x00, 0x1E, 0x41, 0xFE, 0x40, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x78, 0x43, 0xF8, 0x40, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00,
0x09, 0x81, 0x00, 0x00, 0xF0, 0x47, 0x08, 0x40, 0x00, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x0E, 0x00,
0x08, 0x83, 0x00, 0x03, 0x90, 0x7F, 0x08, 0x40, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x11, 0x00,
0x0C, 0xC6, 0x00, 0x1F, 0x10, 0xF1, 0x08, 0x40, 0x00, 0x00, 0x03, 0x00, 0x03, 0x80, 0x24, 0x80,
0x06, 0x7C, 0x00, 0x7A, 0x13, 0xC1, 0x08, 0x40, 0x00, 0x00, 0x43, 0x00, 0x01, 0x00, 0x2C, 0x80,
0x02, 0x00, 0x1F, 0xC6, 0x1E, 0x41, 0x08, 0x40, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x28, 0x80,
0x03, 0x00, 0x3C, 0x8A, 0x70, 0x41, 0x09, 0xE0, 0x10, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x80,
0x00, 0x01, 0xE1, 0x57, 0xD0, 0x41, 0x0F, 0x80, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x80,
0x00, 0x0F, 0x22, 0x25, 0x10, 0x41, 0x3C, 0x00, 0x28, 0x00, 0x03, 0x1F, 0xFF, 0x00, 0x11, 0x00,
0x00, 0xF8, 0x54, 0x3E, 0x10, 0x43, 0xE0, 0x00, 0x00, 0x00, 0x03, 0x3F, 0xFF, 0x83, 0x0A, 0x00,
0x07, 0x88, 0x88, 0xE4, 0x10, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x03, 0x70, 0x01, 0xC3, 0x04, 0x00,
0x3C, 0x15, 0x07, 0x04, 0x10, 0x5B, 0x00, 0x80, 0x00, 0x00, 0x03, 0xE0, 0x00, 0xE0, 0x0E, 0x00,
0xFA, 0x22, 0x1E, 0x04, 0x10, 0xF1, 0x80, 0x80, 0x00, 0x08, 0x03, 0xC0, 0x00, 0x70, 0x04, 0x08,
0x89, 0x40, 0xF2, 0x04, 0x17, 0xB0, 0xC1, 0x40, 0x00, 0x0C, 0x03, 0x86, 0x0C, 0x38, 0x04, 0x18,
0x08, 0x8F, 0x83, 0x04, 0x3C, 0x18, 0x60, 0x00, 0x00, 0x08, 0x03, 0x0F, 0x1E, 0x18, 0x04, 0x10,
0x08, 0x78, 0x83, 0x04, 0xE6, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x03, 0x19, 0xB3, 0x18, 0x06, 0x00,
0x0F, 0xE0, 0xC2, 0x07, 0x83, 0x06, 0x18, 0x00, 0x00, 0x00, 0x03, 0x18, 0xE3, 0x18, 0x02, 0x00,
0x0C, 0x21, 0xC3, 0x7C, 0x01, 0x83, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x18, 0x43, 0x18, 0x02, 0x00,
0x18, 0x21, 0x87, 0xC0, 0x00, 0xC1, 0x86, 0x00, 0x00, 0x00, 0x03, 0x18, 0x0B, 0x18, 0x01, 0x00,
0x10, 0x60, 0x8F, 0x80, 0x10, 0x60, 0xC3, 0x00, 0x01, 0x00, 0x03, 0x18, 0x1B, 0x18, 0x01, 0x00,
0x10, 0x60, 0xFB, 0x80, 0x10, 0x30, 0x61, 0x80, 0x01, 0x00, 0x03, 0x18, 0x13, 0x18, 0x01, 0x00,
0x50, 0x21, 0xC1, 0xC0, 0x28, 0x18, 0x30, 0xC0, 0x02, 0x80, 0x03, 0x18, 0x03, 0x18, 0x01, 0x00,
0x70, 0x3E, 0x01, 0xC0, 0x00, 0x0C, 0x18, 0x71, 0xC4, 0x40, 0x03, 0x0C, 0x06, 0x18, 0x80, 0x00,
0x70, 0xF0, 0x00, 0xE0, 0x00, 0x06, 0x0C, 0x3B, 0x98, 0x30, 0x03, 0x06, 0x0C, 0x19, 0x81, 0x00,
0x77, 0x38, 0x00, 0xF0, 0x00, 0x03, 0x06, 0x1E, 0x04, 0x40, 0x23, 0x03, 0x18, 0x18, 0x80, 0x00,
0x3C, 0x38, 0x03, 0xC0, 0x00, 0x41, 0x83, 0x78, 0x02, 0x80, 0x23, 0x81, 0xB0, 0x38, 0x01, 0x00,
0xF0, 0x1C, 0x0E, 0x00, 0x40, 0x40, 0xC1, 0xF0, 0x01, 0x00, 0x21, 0xC0, 0xE0, 0x70, 0x14, 0x60,
0x80, 0x0C, 0x7C, 0x00, 0x40, 0xA0, 0x67, 0xC0, 0x01, 0x00, 0x60, 0xE0, 0x40, 0xE0, 0x01, 0x00,
0x00, 0x0F, 0xE0, 0x00, 0xA0, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0xC0, 0x00, 0x00,
0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x88, 0x02, 0x80,
0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x0C, 0x08, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0xFE, 0x10, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80,
0x0C, 0x0F, 0x1F, 0x87, 0xE0, 0xFE, 0x18, 0x31, 0x00, 0xF0, 0x3F, 0x8F, 0xE2, 0x20, 0x03, 0x04,
0x0C, 0x1D, 0x1F, 0x8C, 0x60, 0xC6, 0x0C, 0x23, 0x81, 0x08, 0x24, 0x91, 0x02, 0x20, 0x1C, 0x04,
0x00, 0x30, 0x18, 0x08, 0x30, 0xC0, 0x04, 0x65, 0x42, 0x00, 0x2E, 0xA1, 0x02, 0xFC, 0x20, 0x04,
0x0C, 0x30, 0x18, 0x00, 0x30, 0xC0, 0x06, 0xCD, 0x62, 0x00, 0x24, 0x8F, 0xC3, 0x24, 0x22, 0x04,
0x0C, 0x60, 0x18, 0x00, 0x30, 0xFC, 0x03, 0x95, 0x52, 0x00, 0x2E, 0x89, 0x02, 0xA8, 0x22, 0x04,
0x0C, 0x60, 0x1F, 0x03, 0xF0, 0x7E, 0x01, 0x9F, 0xF2, 0xF0, 0x20, 0x89, 0x02, 0x30, 0x22, 0x04,
0x0C, 0x60, 0x1F, 0x06, 0x60, 0x06, 0x03, 0x08, 0x23, 0x08, 0x24, 0xBF, 0xE3, 0xFF, 0x1F, 0xC4,
0x0C, 0x70, 0x18, 0x0C, 0x30, 0x06, 0x06, 0x0F, 0x22, 0x08, 0x2A, 0x81, 0x0A, 0x20, 0x02, 0x00,
0x0C, 0x30, 0x18, 0x0C, 0x30, 0xC6, 0x0C, 0x09, 0x22, 0x08, 0x4A, 0x81, 0x12, 0x20, 0x0A, 0x84,
0x0C, 0x1D, 0x1F, 0x8E, 0x70, 0xFE, 0x18, 0x0D, 0x22, 0x08, 0x44, 0x81, 0x02, 0x50, 0x12, 0x40,
0x0C, 0x0F, 0x1F, 0x87, 0xEC, 0xFE, 0x30, 0x09, 0x21, 0x10, 0x80, 0x81, 0x02, 0x48, 0x22, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1F, 0xF0, 0xE1, 0x01, 0x81, 0x02, 0x87, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 效果名称
const char* effectNames[] = {
"TIME TUNNEL", "DNA HELIX", "STAR FIELD", "PORTAL",
"DECODE", "SHATTER", "WARP SPEED", "QUANTUM"
};
// 粒子和星星
struct Star { int x, y, z; };
struct Fragment { int x, y, tx, ty, vx, vy; };
#define MAX_STARS 30
#define MAX_FRAGS 20
Star stars[MAX_STARS];
Fragment frags[MAX_FRAGS];
unsigned long effectStartTime = 0;
int currentEffect = 0;
// ============ 音乐函数 ============
void playHappyBirthday() {
if (BUZZER_PIN < 0) return;
int numNotes = sizeof(birthdayMelody) / sizeof(birthdayMelody[0]);
for (int i = 0; i < numNotes; i++) {
int noteDuration = 1200 / birthdayDurations[i];
tone(BUZZER_PIN, birthdayMelody[i], noteDuration);
int pauseBetweenNotes = noteDuration * 1.3;
delay(pauseBetweenNotes);
noTone(BUZZER_PIN);
}
}
void playTransitionSound() {
if (BUZZER_PIN < 0) return;
int notes[] = {NOTE_C4, NOTE_E4, NOTE_G4};
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, notes[i], 80);
delay(100);
noTone(BUZZER_PIN);
}
}
void beep(int duration) {
if (BUZZER_PIN >= 0) {
tone(BUZZER_PIN, 1000, duration);
delay(duration);
noTone(BUZZER_PIN);
}
}
// ============ 启动动画 ============
void epicBootAnimation() {
// 脉冲
for (int i = 0; i < 3; i++) {
display.clearDisplay();
display.fillCircle(64, 32, 5 + i * 8, SSD1306_WHITE);
display.display();
delay(100);
}
// 标题
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(15, 10);
display.println(F("ULTIMATE"));
display.setCursor(25, 30);
display.println(F("SYSTEM"));
display.display();
delay(800);
// �� 生日祝福
display.clearDisplay();
display.setTextSize(1);
display.setCursor(10, 15);
display.println(F("Happy Birthday!"));
display.setCursor(25, 35);
display.println(F("Enjoy :)"));
// 绘制蛋糕图标
display.fillRect(52, 45, 24, 10, SSD1306_WHITE);
display.drawLine(64, 40, 64, 45, SSD1306_WHITE);
display.fillCircle(64, 39, 2, SSD1306_WHITE);
display.display();
// �� 播放生日快乐歌!
playHappyBirthday();
delay(500);
// 扫描线
for (int y = 0; y < 64; y += 2) {
display.drawFastHLine(0, y, 128, SSD1306_WHITE);
display.display();
}
delay(500);
}
// ============ 过渡动画 ============
void playTransition() {
for (int i = 0; i < 10; i++) {
display.clearDisplay();
int s = i * 13;
display.drawLine(0, 0, s, s, SSD1306_WHITE);
display.drawLine(127, 0, 127-s, s, SSD1306_WHITE);
display.drawLine(0, 63, s, 63-s, SSD1306_WHITE);
display.drawLine(127, 63, 127-s, 63-s, SSD1306_WHITE);
display.display();
delay(30);
}
}
// ============ 效果1: 时空隧道 ============
void effect1_TimeTunnel(unsigned long t) {
display.clearDisplay();
int depth = (t / 30) % 40;
for (int i = 0; i < 8; i++) {
int d = (depth + i * 5) % 40;
int r = 3 + d;
if (r < 50) {
display.drawCircle(64, 32, r, SSD1306_WHITE);
if (i % 2 == 0) display.drawCircle(64, 32, r-1, SSD1306_WHITE);
}
}
float progress = min(1.0, t / 4000.0);
int maxY = 64 * progress;
for (int y = 0; y < maxY; y++) {
for (int x = 0; x < 128; x++) {
int byteIdx = y * 16 + x / 8;
int bitIdx = 7 - (x % 8);
if (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx)) {
display.drawPixel(x, y, SSD1306_WHITE);
}
}
}
display.display();
delay(25);
}
// ============ 效果2: DNA双螺旋 ============
void effect2_DNAHelix(unsigned long t) {
display.clearDisplay();
float angle = t / 500.0;
for (int x = 0; x < 128; x += 3) {
float a = angle + x * 0.1;
int y1 = 32 + sin(a) * 15;
display.fillCircle(x, y1, 2, SSD1306_WHITE);
int y2 = 32 - sin(a) * 15;
display.fillCircle(x, y2, 2, SSD1306_WHITE);
if (abs(y1 - y2) < 5) display.drawLine(x, y1, x, y2, SSD1306_WHITE);
}
if (t > 2000) {
for (int y = 0; y < 64; y += 2) {
for (int x = 0; x < 128; x += 2) {
int byteIdx = y * 16 + x / 8;
int bitIdx = 7 - (x % 8);
if (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx)) {
display.drawPixel(x, y, SSD1306_WHITE);
}
}
}
}
display.display();
delay(30);
}
// ============ 效果3: 星域冲击 ============
void initStars() {
for (int i = 0; i < MAX_STARS; i++) {
stars[i].x = random(-64, 64);
stars[i].y = random(-32, 32);
stars[i].z = random(1, 30);
}
}
void effect3_StarField(unsigned long t) {
display.clearDisplay();
for (int i = 0; i < MAX_STARS; i++) {
stars[i].z -= 1;
if (stars[i].z <= 0) {
stars[i].x = random(-64, 64);
stars[i].y = random(-32, 32);
stars[i].z = 30;
}
int sx = 64 + (stars[i].x * 30) / stars[i].z;
int sy = 32 + (stars[i].y * 30) / stars[i].z;
if (sx >= 0 && sx < 128 && sy >= 0 && sy < 64) {
int size = (30 - stars[i].z) / 15 + 1;
int oldSx = 64 + (stars[i].x * 30) / (stars[i].z + 1);
int oldSy = 32 + (stars[i].y * 30) / (stars[i].z + 1);
display.drawLine(sx, sy, oldSx, oldSy, SSD1306_WHITE);
display.fillCircle(sx, sy, size, SSD1306_WHITE);
}
}
if (t > 3000) {
float scale = min(1.0, (t - 3000) / 2000.0);
int w = 128 * scale;
int h = 64 * scale;
int ox = (128 - w) / 2;
int oy = (64 - h) / 2;
for (int y = 0; y < h; y += 2) {
for (int x = 0; x < w; x += 2) {
int sx = x / scale;
int sy = y / scale;
int byteIdx = sy * 16 + sx / 8;
int bitIdx = 7 - (sx % 8);
if (byteIdx < 1024 && (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx))) {
display.drawPixel(ox + x, oy + y, SSD1306_WHITE);
}
}
}
}
display.display();
delay(25);
}
// ============ 效果4: 传送门 ============
void effect4_Portal(unsigned long t) {
display.clearDisplay();
int maxRadius = min(50, (int)(t / 50));
for (int r = maxRadius; r > 0; r -= 5) {
if ((r / 5) % 2 == 0) display.drawCircle(64, 32, r, SSD1306_WHITE);
}
if (t > 1000) {
float angle = t / 1000.0;
for (int y = 0; y < 64; y++) {
for (int x = 0; x < 128; x++) {
float dx = x - 64;
float dy = y - 32;
float dist = sqrt(dx*dx + dy*dy);
if (dist < maxRadius - 10) {
float a = atan2(dy, dx) + angle * (1.0 - dist / maxRadius);
int sx = 64 + cos(a) * dist;
int sy = 32 + sin(a) * dist;
if (sx >= 0 && sx < 128 && sy >= 0 && sy < 64) {
int byteIdx = sy * 16 + sx / 8;
int bitIdx = 7 - (sx % 8);
if (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx)) {
display.drawPixel(x, y, SSD1306_WHITE);
}
}
}
}
}
}
display.display();
delay(30);
}
// ============ 效果5: 矩阵解码 ============
void effect5_MatrixDecode(unsigned long t) {
display.clearDisplay();
int decodeX = (t / 30) % 140;
for (int y = 0; y < 64; y++) {
for (int x = 0; x < 128; x++) {
int byteIdx = y * 16 + x / 8;
int bitIdx = 7 - (x % 8);
bool pixel = pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx);
if (x < decodeX) {
if (pixel) display.drawPixel(x, y, SSD1306_WHITE);
} else if (x == decodeX) {
display.drawPixel(x, y, SSD1306_WHITE);
} else {
if (random(10) < 3 && pixel) display.drawPixel(x, y, SSD1306_WHITE);
}
}
}
for (int i = -3; i <= 3; i++) {
int x = decodeX + i;
if (x >= 0 && x < 128) display.drawFastVLine(x, 0, 64, SSD1306_WHITE);
}
display.display();
delay(20);
}
// ============ 效果6: 碎片重组 ============
void initShatter() {
for (int i = 0; i < MAX_FRAGS; i++) {
frags[i].tx = (i % 5) * 25;
frags[i].ty = (i / 5) * 16;
frags[i].x = random(-50, 178);
frags[i].y = random(-30, 94);
frags[i].vx = 0;
frags[i].vy = 0;
}
}
void effect6_Shatter(unsigned long t) {
display.clearDisplay();
bool gathering = t > 2000;
for (int i = 0; i < MAX_FRAGS; i++) {
if (gathering) {
frags[i].vx = (frags[i].tx - frags[i].x) / 8;
frags[i].vy = (frags[i].ty - frags[i].y) / 8;
}
frags[i].x += frags[i].vx;
frags[i].y += frags[i].vy;
int fx = frags[i].x;
int fy = frags[i].y;
for (int dy = 0; dy < 16 && fy + dy < 64; dy++) {
for (int dx = 0; dx < 25 && fx + dx < 128; dx++) {
int sy = frags[i].ty + dy;
int sx = frags[i].tx + dx;
if (sy >= 0 && sy < 64 && sx >= 0 && sx < 128) {
int byteIdx = sy * 16 + sx / 8;
int bitIdx = 7 - (sx % 8);
if (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx)) {
int py = fy + dy;
int px = fx + dx;
if (px >= 0 && px < 128 && py >= 0 && py < 64) {
display.drawPixel(px, py, SSD1306_WHITE);
}
}
}
}
}
display.drawRect(fx, fy, 25, 16, SSD1306_WHITE);
}
display.display();
delay(25);
}
// ============ 效果7: 曲速引擎 ============
void effect7_WarpSpeed(unsigned long t) {
display.clearDisplay();
for (int i = 0; i < 40; i++) {
int x = (t * 5 + i * 20) % 160 - 32;
int y = random(0, 64);
int len = random(10, 40);
if (x >= 0 && x < 128) display.drawFastHLine(x, y, min(len, 128-x), SSD1306_WHITE);
}
for (int y = 0; y < 64; y++) {
int stretch = sin(t / 300.0 + y * 0.1) * 5;
for (int x = 0; x < 128; x++) {
int sx = (x - stretch + 128) % 128;
int byteIdx = y * 16 + sx / 8;
int bitIdx = 7 - (sx % 8);
if (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx)) {
display.drawPixel(x, y, SSD1306_WHITE);
}
}
}
display.display();
delay(20);
}
// ============ 效果8: 量子叠加 ============
void effect8_Quantum(unsigned long t) {
display.clearDisplay();
int numLayers = 3;
for (int layer = 0; layer < numLayers; layer++) {
int offsetX = sin(t / 500.0 + layer * 2) * 10;
int offsetY = cos(t / 600.0 + layer * 2) * 5;
for (int y = 0; y < 64; y += (layer + 1)) {
for (int x = 0; x < 128; x += (layer + 1)) {
int sx = x - offsetX;
int sy = y - offsetY;
if (sx >= 0 && sx < 128 && sy >= 0 && sy < 64) {
int byteIdx = sy * 16 + sx / 8;
int bitIdx = 7 - (sx % 8);
if (pgm_read_byte(&bitmap[byteIdx]) & (1 << bitIdx)) {
display.drawPixel(x, y, SSD1306_WHITE);
}
}
}
}
}
if ((t / 100) % 3 == 0) {
display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
display.drawRect(2, 2, 124, 60, SSD1306_WHITE);
}
int brightness = (sin(t / 300.0) * 127.5) + 127.5;
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(brightness);
display.display();
delay(35);
}
// ============ SETUP ============
void setup() {
Serial.begin(115200);
Wire.begin(6, 7); // �� 改成你的I2C引脚
if (BUZZER_PIN >= 0) pinMode(BUZZER_PIN, OUTPUT);
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("初始化失败"));
for(;;);
}
epicBootAnimation(); // �� 播放生日快乐歌
effectStartTime = millis();
initStars();
Serial.println(F("╔═══════════════════════════════╗"));
Serial.println(F("║ 宇宙第一 终极显示系统 V1.0 ║"));
Serial.println(F("║ ULTIMATE DISPLAY SYSTEM ║"));
Serial.println(F("╚═══════════════════════════════╝"));
}
// ============ LOOP ============
void loop() {
unsigned long elapsed = millis() - effectStartTime;
if (elapsed >= 6000) {
playTransition();
currentEffect = (currentEffect + 1) % 8;
effectStartTime = millis();
elapsed = 0;
if (currentEffect == 2) initStars();
if (currentEffect == 5) initShatter();
Serial.println();
Serial.print(F(">>> 效果 #"));
Serial.print(currentEffect + 1);
Serial.print(F(": "));
Serial.println(effectNames[currentEffect]);
playTransitionSound(); // �� 音效
}
switch(currentEffect) {
case 0: effect1_TimeTunnel(elapsed); break;
case 1: effect2_DNAHelix(elapsed); break;
case 2: effect3_StarField(elapsed); break;
case 3: effect4_Portal(elapsed); break;
case 4: effect5_MatrixDecode(elapsed); break;
case 5: effect6_Shatter(elapsed); break;
case 6: effect7_WarpSpeed(elapsed); break;
case 7: effect8_Quantum(elapsed); break;
}
}
🎵 音乐系统说明
生日快乐歌旋律编码
本项目使用标准音符频率表和节奏数组来编码生日快乐歌:
```cpp
// 音符频率(单位:Hz)
NOTE_G4 = 392Hz // Sol
NOTE_A4 = 440Hz // La
NOTE_C5 = 523Hz // Do (高音)
NOTE_D5 = 587Hz // Re (高音)
// ... 等等
// 旋律数组(音符序列)
Happy Birthday to you → G G A G C B
Happy Birthday to you → G G A G D C
Happy Birthday dear... → G G G E C B A
Happy Birthday to you → F F E C D C
```
音乐播放原理
无源蜂鸣器通过 `tone()` 函数驱动:
```cpp
tone(引脚号, 频率Hz, 持续时间ms);
```
程序自动计算每个音符的时长:
四分音符 = 1200ms ÷ 4 = 300ms
二分音符 = 1200ms ÷ 2 = 600ms
音符之间自动添加 1.3倍时长的停顿,使旋律更清晰。
🎨 8种视觉特效详解
效果 1: 时空隧道 (Time Tunnel)
原理: 同心圆从中心向外扩散
实现: 使用 drawCircle()绘制多层递增半径的圆
效果: 模拟穿越时空隧道的视觉感
时长: 6秒
效果 2: DNA 双螺旋 (DNA Helix)
原理: 正弦波相位相反的双螺旋线
实现:
```cpp
y1 = 32 + sin(angle) * 15; // 上螺旋
y2 = 32 - sin(angle) * 15; // 下螺旋
效果: 生物科技感十足的 DNA 双螺旋结构
时长: 6秒
效果 3: 星域冲击 (Star Field)
原理: 3D 星空视差效果
实现: 30颗星星在 Z 轴上移动,越近越大
公式:
屏幕X = 64 + (星X * 30) / 星Z深度
屏幕Y = 32 + (星Y * 30) / 星Z深度
效果: 像《星球大战》中的超空间跳跃
时长: 6秒
效果 4: 传送门 (Portal)
原理: 同心圆旋转扭曲
实现: 图像根据距离中心的距离进行极坐标旋转
效果: 类似《传送门》游戏中的空间扭曲
时长: 6秒
效果 5: 矩阵解码 (Matrix Decode)
原理: 扫描线从左到右逐步"解码"图像
实现:
扫描线左侧:显示正常图像
扫描线位置:高亮竖线
扫描线右侧:随机噪点
效果: 《黑客帝国》风格的数据解码
时长: 6秒
效果 6: 碎片重组 (Shatter)
原理: 图像分割成 20 个碎片,先分散后聚合
实现:
每个碎片 25×16 像素
初始随机飞散
2秒后逐渐飞回原位
效果: 如同玻璃破碎后重新组合
时长: 6秒
效果 7: 曲速引擎 (Warp Speed)
原理: 水平高速运动的光条 + 波形扭曲
实现:
40条随机高度的光条高速移动
图像按正弦波扭曲
效果: 《星际迷航》曲速引擎的超光速感觉
时长: 6秒
效果 8: 量子叠加 (Quantum)
原理: 3层图像叠加,各自独立晃动
实现:
每层图像有不同的偏移量
使用正弦函数控制晃动
动态调整屏幕亮度
效果: 量子力学的叠加态视觉表现
时长: 6秒
📊 系统工作流程
```mermaid
graph TD
A[上电启动] --> B[初始化硬件]
B --> C[播放启动动画]
C --> D[显示生日祝福文字]
D --> E[播放生日快乐歌]
E --> F[进入效果循环]
F --> G[效果1: 时空隧道]
G --> H[过渡动画+音效]
H --> I[效果2: DNA双螺旋]
I --> J[...]
J --> K[效果8: 量子叠加]
K --> F
```
🎨 进阶改进建议
1. 添加更多歌曲
可以添加超级玛丽、小星星等旋律:
```cpp
void playMarioTheme() {
int melody[] = {NOTE_E5, NOTE_E5, 0, NOTE_E5, ...};
// 播放代码...
}
```
2. 触摸按钮切换效果
添加触摸传感器手动切换:
```cpp
if (touchRead(T0) < 40) {
currentEffect++;
// 切换效果
}
```
3. 联网显示
连接 Wi-Fi 显示天气、时间等:
```cpp
#include <WiFi.h>
WiFi.begin(ssid, password);
// 获取网络数据...
```
4. 彩色 OLED 升级
更换 SSD1351 彩色屏幕,获得更炫酷的视觉效果
💝 项目应用场景
🎂 生日礼物:个性化生日祝福装置
🏢 公司庆典:周年庆展示装置
🎨 创客作:技术展示项目
📚 教学演示:嵌入式系统教学
🎁 DIY 礼物:送给科技爱好者
🙏 致谢
iEasy商城 6周年庆典,祝越办越好!🎉
如果觉得本项目有帮助,请点个👍或评论留下您想听的歌曲哦!!!
Happy Making! 🎂🎵✨

