前两年趁着亚马逊促销买了索尼 ICF-C1PJ 投影收音机闹钟,投影基本没啥用,时钟显示在晚上看时间还是挺方便的。这货自带了5种自然声,大海波浪、森林小溪之类的,睡前当白噪声还不错;也可以闹钟当铃声,但对于睡得比较死的我来说,自然声当闹钟铃声是基本没有用的,根本叫不醒。所以就用 FM/AM 电台来做闹钟铃声,但是早上的电台节目实在是太无聊,再加上电台的众多傻逼广告,也是没法忍了。除了电台傻逼(这也不关索尼的事啊),这货作为闹钟本身还是挺好的,那能不能让它播放我指定的声音呢?这就考虑两点问题:1. 如何让播放设备根据闹钟时间定时开启和关机;2. 播放设备的输出如何作为闹钟的输入?

一开始是想要把整个模块整合进机器内部,拆开机器看了下内部空间挺大的应该够。首页模块装进内部,在内部如何供电?闹钟本身有个对外 USB 接口可以给手机充电,因此模块可以从 USB 口取 5V 供电。播放设备首先想到的就是廉价的不带屏幕的插卡MP3,一通电就开始随机播放TF卡里的 mp3,淘宝上十块钱就能买到,拆开去掉电池,整体尺寸不会太大。但是这样把 MP3 装进机器后,想要换歌就有点麻烦了,可以再加一个 TF卡 延长线接出来。其次方案就蓝牙音频接收器,体积也不大,比较灵活,直接在外部播放音乐,但这多了外部设备也定时启动播放。播放设备要能跟闹钟一起启动,这就需要到感知闹钟内部的状态。设置闹钟后,屏幕上会常亮闹钟的设置信息(时间、工作日/周日、FM/AM/自然声),闹钟响起时这些信息就会闪烁起来。所以,初步想法是通过读取显示屏的输入来确定闹钟是否开启,但搞清楚输入信号跟闹钟启动的关系感觉有点费力,而且闪烁判断涉及到时序,复杂了起来。闹钟响了之后,还需要劫持原本的音频输出,改为 mp3 或 蓝牙接收器的音频输出。内部电路板还是稍微有点复杂的,看着晕,改造风险也比较大。如果直接在扬声器的输入上做劫持就会简单很多,但是音频输出信号又不足以驱动扬声器,真是麻烦呢。

为了尽可能不影响原本的功能,还需要对 5 个频道预设按钮之一做劫持,仅当切换到某个预设频道时模块才生效。这时候突然想到既然 AM 模式用不到,何不利用一下呢,可以大大简化上面说的判断方式。只要切换到了 AM 模式,即屏幕上的 AM 模式亮起,就可以马上启动新增模块,这样就不需要去检测闹钟闪烁了。作为 MP3,应该要有控制按键,AM 模式下 5 个频道预设按钮劫持一下正好可以映射到播放/暂停、前进、后退,计划通。

这么计划着计划着,好像变得越来越复杂了,我怂了,还是换个没有侵入性的方案吧。


没有侵入性,那就直接用收音机的 FM 接收功能呗,所以方案二:定时启动播放音频 & FM信号发射 的装置。FM信号发射装置很好找,有很多现成的产品和半成品。现成的产品一般都是插上电就开始工作的,而我希望能控制一下,只在闹钟响的时候才发射信号,所以就买半成品的FM发射模块来自己搞咯。我买的这个 FM 模块支持串口来控制,再加一个三极管来控制电源开关就行了。

同样,播放设备也需要受控:定时播放、可选的播放列表、播放控制... 还要能有多组闹钟设置,考虑下来还是直接在树莓派上用软件实现简单一点,GPIO口和串口编程都挺容易。为了减小体积,我选择了树莓派 zero wifi版本,zero没有 3.5mm 的音频口,需要从 PWM 口输出音频,参考这篇文章做了滤波电路来过滤PWM信号,再把线都连起来,硬件部分就完成了。因为只需要近距离传输,就不专门买天线了,拿根普通的线当天线就够用了。

软件部分,需要实现 FM 开关以及串口通讯的功能。引入 rpi-gpioserialport 库就能方便地处理这俩逻辑了,串口通讯加上锁来独占。

再加上定时播放功能,我结合 cron 时间表达式和时长来确定闹钟启停时间点,方便闹钟配置;封装play-sound 成为列表播放器,可以读取列表文件来决定播放哪些音频文件。