复古风 FM 收音机 DIY:TEA5767 模块与模拟仪表完美结合
项目灵感与设计理念
本项目致敬经典收音机美学,将现代 TEA5767 全集成 FM 接收芯片与模拟指针仪表、16×2 LCD 虚拟调谐刻度、D 类功放、双分频音箱融合于一体。通过旋钮编码器调谐、四键预存电台、自动/手动搜台切换、立体声/信号强度双模拟表头指示,重现“转动调谐钮、指针滑过刻度、温暖音质流淌”的仪式感。整机由两节锂电池串联经 7805 稳压供电,便携性与复古质感兼得。
核心硬件清单
| 模块 | 型号/规格 | 关键参数 | 数量 |
|---|---|---|---|
| 主控 | Arduino Nano R3 | ATmega328P, 5V/16MHz, 体积 18×45mm | 1 |
| FM 接收 | TEA5767 模块 | I2C 控制, 76-108MHz, 立体声/单声道, SNR>60dB | 1 |
| 模拟表头 | 复古仪表 (信号强度/频率) | 电流型 0-1mA, 内阻 ~500Ω, 带调零螺丝 | 2 |
| 显示屏 | 16×2 LCD (白字蓝底) | HD44780, 4-bit模式, 自定义字符刻度 | 1 |
| 音频放大 | D 类立体声功放板 (2×3W) | PAM8403 或同类, 效率 >90%, 增益固定 | 1 |
| 音量控制 | 双联对数电位器 10kΩ (B型) | 立体声同步调节, 手感阻尼适中 | 1 |
| 扬声器 | 3W 4Ω 全频 + 0.25W 8Ω 高音 | 分频电容 1μF 串联高音单元 | 各2 |
| 交互 | 旋钮编码器(带按键) + 4×轻触键 | 编码器调谐/菜单, 4键预存电台 | 1+4 |
| 指示灯 | LED ×3 (立体声/自动搜台/电源) | PWM 驱动亮度可调 | 3 |
| 电源 | 2×18650 串联 + 7805 + 470μF/100μF 滤波 | 输出 5V/1A, 续航 >8h | 1套 |
电路设计亮点
TEA5767 I2C 控制
- SDA/SCL 接 Nano A4/A5,上拉 4.7kΩ 至 3.3V(模块内部已含)。
- 音频输出 L/R 经 10μF 电容隔直流接入双联电位器,再接功放输入。
- 天线接模块 ANT 引脚,实机使用伸缩天线,长度约 75cm (λ/4 @ 100MHz)。
模拟表头驱动电路
两路 PWM (D5/D6) 经 RC 低通滤波 (10kΩ+10μF) 得到 0-5V 模拟电压,再经串联微调电位器 (10kΩ) 限流驱动表头线圈。代码中 map(freq, 88, 108, 0, 255) 与 map(signal, 0, 100, 0, 255) 分别控制频率表与信号表。表头机械惯性自然平滑指针抖动。
音频分频与功放
- 功放板输出直推两路全频单元 (3W/4Ω)。
- 高音单元 (0.25W/8Ω) 串联 1μF 无极性电容 (约 8kHz 一阶高通),并联于全频单元两端,提升高频延伸。
- 功放增益固定,音量完全由前级双联电位器控制,保证信噪比最优。
软件架构与交互逻辑
自定义 LCD 字符集
// 刻度背景字符 (5×8 像素)
byte scaleChar[8] = {0,0,0,0,0,4,21,21}; // 0b00100, 0b10101
// 指针 5 亚像素位置 (每字符 5 列)
for (int j=0; j<5; j++) {
for (int i=0; i<8; i++) needleChar[i] = scaleChar[i] | (0b10000 >> j);
lcd.createChar(j, needleChar);
}
// 立体声图标 "ST" 风格
byte stereoS[8] = {0b01111,0b11000,0b11011,0b11101,0b11110,0b11000,0b01111,0};
byte stereoT[8] = {0b11110,0b00011,0b10111,0b10111,0b10111,0b10111,0b11110,0};
编码器中断处理
#define ENC_A 3 // INT1
#define ENC_B 4
#define ENC_SW 2 // INT0
volatile byte status = 0; // bit0:AUTO, bit1:STEREO, bit2:UP, bit3:DOWN, bit4:SEARCH
void isrEncoder() { delay(50); if (digitalRead(ENC_B)) bitSet(status,2); else bitSet(status,3); }
void isrSwitch() { delay(50); bitWrite(status,0, !bitRead(status,0)); } // 切换自动/手动
主循环状态机
void loop() {
// 1. 更新自动/手动指示
lcd.setCursor(12,1); lcd.write(bitRead(status,0)?'A':'M');
digitalWrite(AUTO_LED, bitRead(status,0)?LOW:HIGH); // 低电平点亮
// 2. 读取 TEA5767 状态
unsigned char buf[5];
if (Radio.read_status(buf)) {
freq = floor(Radio.frequency_available(buf)/100000.0 + 0.5)/10;
stereo = Radio.stereo(buf);
signal = Radio.signal_level(buf)*100/15;
// 驱动模拟表头
analogWrite(SIG_METER, map(signal,0,100,0,255));
analogWrite(FREQ_METER, map(freq,88,108,0,255));
analogWrite(STEREO_LED, map(stereo,0,1,0,255));
// 更新 LCD 刻度指针
updateScale();
// 显示数值
lcd.setCursor(0,1); lcd.write(0xB7); lcd.print(signal); lcd.print('%');
lcd.setCursor(6,1); if(freq<100) lcd.print(' '); lcd.print(freq,1);
lcd.setCursor(14,1); if(stereo){lcd.write(6);lcd.write(7);} else lcd.print(" ");
}
// 3. 自动搜台处理
if (bitRead(status,4)) { // SEARCH 标志
int dir;
if (Radio.process_search(buf, dir)) bitClear(status,4);
}
// 4. 预存电台按键 (A0-A3)
for (int i=0; i<4; i++) if (digitalRead(BTN_FREQ[i])) {
float preset[] = {92.0, 94.8, 97.0, 101.2};
freq = preset[i]; Radio.set_frequency(freq); redrawScale();
}
// 5. 编码器调谐
if (bitRead(status,2)) { // UP
if (bitRead(status,0) && !bitRead(status,4)) { // 自动向上搜台
bitSet(status,4); Radio.search_up(buf); delay(50);
} else if (freq < 108) { freq += 0.1; Radio.set_frequency(freq); }
bitClear(status,2);
}
if (bitRead(status,3)) { // DOWN
if (bitRead(status,0) && !bitRead(status,4)) { bitSet(status,4); Radio.search_down(buf); delay(50); }
else if (freq > 88) { freq -= 0.1; Radio.set_frequency(freq); }
bitClear(status,3);
}
}
组装与调试全流程
- 模块测试:分别验证 TEA5767 I2C 通信、LCD 显示、功放发声、编码器中断、按键扫描、PWM 表头驱动。
- 面包板联调:全模块连接,上传固件,观察启动动画、自动搜台锁定强台、手动微调步进 0.1MHz。
- 表头校准:调节两路微调电位器,使指针在 88MHz/108MHz、信号 0%/100% 对应刻度端点。
- 音质优化:调整分频电容容值 (0.47-2.2μF) 与扬声器箱体容积,消除箱体共振峰。
- 机箱装配:3D 打印/木工制作外壳,预留 LCD 窗、表头圆孔、编码器/按键/电位器轴伸出、天线座、电源开关、USB 充电口。
- 老化测试:连续播放 24h,监测电池电压、功放温升、接触不良、按键失效情况。
已知问题与改进计划
- 频率表头步进感:指针每 1MHz 跳动一次,因库函数仅返回整 MHz 频率。计划移植 Si4703 驱动或直接操作 TEA5767 寄存器实现 50kHz 步进平滑驱动。
- 立体声/单声道切换抖动:弱信号下频繁切换。拟添加软件迟滞(信号强度 >30% 且立体声导频稳定 >2s 才切立体声)与手动强制单声道开关。
- 静噪/静音功能:增加 Squelch 电路或软件阈值,信号低于门限自动静音,消除底噪。
- RDS/RBDS 解码:TEA5767 支持 RDS,后续集成解码库显示电台名、节目类型、交通信息。
- 蓝牙音频输入:增加 CSR8635 模块,切换为蓝牙音箱模式,一机多用。
安全与法规提示
- FM 接收属免执照接收业务,但天线增益、辐射杂散需符合当地无管委规定(通常 < -57 dBm/100kHz @ 30MHz-1GHz)。
- 锂电池充电必须带保护板 (过充/过放/过流/短路),严禁裸电芯直充。
- 功放音量过大可能损伤听力,建议软件限制最大 PWM 占空比至 80%。
制造工艺
- 树莓派+Node-RED自制Nest风智能恒温器
- 树莓派构建稳健传感器 API:基于 GY‑91 多功能模块的 Flask 实现
- 树莓派低成本婴儿啼哭检测器 DIY 指南:Prota OS + Philips Hue + Volumio
- 复古 Numitron 管时钟:Arduino Nano 驱动,低温可靠省电
- Arduino Nano高速摄影控制器 – 定格水滴碰撞瞬间
- DIY VR 滑板:用 Arduino、Google Cardboard 与蓝牙打造虚拟滑雪体验
- 自制防水淋浴 FM 收音机:Arduino Nano + RDA5807 + Nokia 5110 LCD + PAM8403
- Arduino Mega 2560 接 NEO-6M GPS 模块完整教程
- Arduino DIY 电压表:Nokia 5110 屏幕显示,手把手教学
- 万圣节 PIR 人体感应惊悚音箱:声光联动恐怖道具制作
- Bluetooth Mesh设计抉择:模组还是离散器件?
- Python 模块导入实战指南:从基础到包管理