今天几乎每个人都用手机听音乐、新闻、播客等。但不久前,我们都依靠当地的 FM 收音机来获取最新的新闻和歌曲,慢慢地这些收音机正在失去人气,但在互联网的紧急情况下停电后,收音机在向用户传输信息方面发挥了重要作用。无线电信号始终存在于空中(由电台广播),我们所需要的只是一个FM 接收器电路来捕获这些无线电信号并将它们转换为音频信号。
在本教程中,我们将构建一个Arduino FM 接收器,并将其添加到我们的项目库中。我们将使用带有 Arduino 的 RDA5807 FM 接收器 IC并对其进行编程,播放任何可由用户使用电位计调谐的 FM 广播电台。我们还将使用音频放大器和电路来控制我们的Arduino FM 收音机的输出音量,听起来很有趣吧?那么,让我们开始吧。
调频收音机一般工作
无线电台将电信号转换为无线电信号,这些信号在通过天线传输之前必须进行调制。有两种方法可以调制信号,即 AM 和 FM。顾名思义,幅度调制 (AM)在发送信号之前调制幅度,而在频率调制 (FM)中,在通过天线发送之前调制信号的频率。在无线电台,他们使用频率调制来调制信号,然后传输数据。现在,我们只需要构建一个可以调谐到特定频率并接收这些信号的接收器,然后将这些电信号转换为音频信号。我们将使用本项目中的RDA5807 FM 接收模块,简化了我们的电路。
所需组件
Arduino纳米
RDA5807接收器
音频放大器
连接线
底池 – 100K
性能板
RDA5807 接收器
RDA5807是一款单芯片FM 立体声收音机调谐器模块,具有完全集成的合成器。模块支持全球50-115MHz频段、音量控制和静音、可编程去加重(50/75us)、接收信号强度指示和信噪比、32.768KHz晶振、数字自动增益控制等。下图为RDA5807M 调谐器的框图。
它具有数字低中频架构,并集成了支持 FM 广播频段(50 至 115 MHz)的低噪声放大器 (LNA)、可编程增益控制 (PGA)、高分辨率模数转换器和高保真数模转换器 (DAC)。限幅器可防止过载并限制相邻信道产生的互调产物的数量。PGA 放大混频器输出信号,然后使用 ADC 进行数字化。DSP 内核管理频道选择、FM 解调、立体声 MPX 解码器和输出音频信号。该IC 的RDA5807 引脚图如下所示。
该模块工作在1.8 – 3.3V 的电源上。当进入休眠状态并选择控制接口时,VIO 上电时模块会自行复位,也支持通过 02H 地址的 0 到 1 的 bit1 触发软复位。模块使用I2C 通信与 MCU 通信,接口以启动条件、命令字节和数据字节开始。RDA5807 有 13 个 16 位寄存器,每个寄存器执行一个特定的功能。寄存器地址以 00H 开始,分配给芯片 ID,以 0FH 结束。在所有 13 个寄存器中,一些位被保留,而一些位是 R/W。每个寄存器根据分配给它们的位执行诸如改变音量、改变通道等任务。
将模块连接到电路时,我们不能直接使用模块,因为引脚是封闭的。所以,我使用了一个穿孔板和一些公插针,并将模块的每个插针焊接到每个公插针上,如下图所示。
音频放大器
音频放大器是一种电子设备,可将低功率电子音频信号放大到足以驱动扬声器或耳机的水平。我们使用 LM386 构建了一个简单的音频放大器,相同的电路如下所示,您也可以查看链接以了解有关此电路的更多信息,也可以查看其他音频放大器电路。
Arduino FM接收器电路图
我们使用了两个电位器来调整 FM 波段和控制音频放大器的音量。要改变音量,您可以改变连接在 LM386 的第 1 和第 8 引脚之间的电位器或连接在 LM386 的引脚 3 之间的电位器。下图显示了Arduino FM Radio 的完整电路图。
我对放大器做了一些改动。我没有在放大器中使用两个电位器,而是只使用了一个。我把用来改变增益的电位器换成了一个电阻。所以现在我们的项目有两个电位器,一个用来调节,一个用来改变音量。用于调谐通道的电位器与 Arduino nano 相连。锅的中心引脚连接到Arduino nano的A0引脚,其余两个引脚中的一个连接到5V,另一个连接到GND。另一个电位器用于控制收音机的音量,连接方式如上图所示。
Arduino 的引脚 A4 和 A5 连接到 RDA5807M 的 SDA 和 SCL 引脚。请记住,接收器模块仅适用于 3.3V。因此,将 Nano 的 3v3 引脚连接到接收器模块的 VCC 引脚。建立连接后,我的设置看起来像这样
Arduino FM收音机代码说明
该代码将初始化接收器模块,然后将频道设置为预设频率。当 nano 在 A0 引脚上读取的值发生变化(通过改变电位器)时,频率会发生变化,从而改变通道。完整的代码在页面末尾给出。
我们通过添加与 RDA5807 通信所需的线库来开始我们的程序。然后,在变量“通道”中,我们设置通道的值。每当收音机启动时,它都会自动调到该频道。
#includeuint16_t 通道 = 187;
接下来,我们将向 RDA5807 IC 上的每个寄存器加载字节以设置我们的初始配置。此时,我们正在重置接收器。
uint8_t 引导配置 [] = { /* 寄存器 0x02 */ 0b11000001, 0b00000011, /* 寄存器 0x03 */ 0b00000000, 0b00000000, /* 寄存器 0x04 */ 0b00001010, 0b00000000, /* 寄存器 0x05 */ 0b10001000, 0b00001111, /* 寄存器 0x06 */ 0b00000000, 0b00000000, /* 寄存器 0x07 */ 0b01000010, 0b00000010, };
重置设备后,我们可以调整设备。为了调谐通道,我们只需要编程前 4 个字节。这部分代码会将频道更改为所需的频率。在 I2C 中,我们首先开始传输,写入或读取数据,然后结束传输。在这个接收器IC中,我们不必指定地址,因为数据表清楚地说明了I2C接口有一个固定的起始寄存器,即0x02h用于写 *** 作,0x0Ah用于读 *** 作。
uint8_t tune_config[] = { /* 寄存器 0x02 */ 0b11000000, 0b00000001, /* 寄存器 0x03 */ (频道 >> 2), ((频道 & 0b11) << 6 ) | 0b00010000 };
在设置中,我们初始化引导配置(重置),然后通过将调谐配置字节写入 RDA5807M 来调谐到一个通道。
无效设置() { 序列号.开始(9600); pinMode(A0,输入); /* 连接到 RDA5807M FM 调谐器:*/ Wire.begin(); Wire.beginTransmission(RDA5807M_ADDRESS); Wire.write(boot_config, BOOT_CONFIG_LEN); Wire.endTransmission(); Wire.beginTransmission(RDA5807M_ADDRESS); Wire.write(tune_config, TUNE_CONFIG_LEN); Wire.endTransmission(); }
当使用pot调整频率时,我遇到了一个问题。A0 引脚读取的值不是恒定的。有一个噪声与所需的值结合在一起。我在 A0 和 GND 之间使用了一个 0.1uF 的陶瓷电容器,虽然噪声已经降到最低,但它并没有达到预期的水平。因此,我不得不对代码进行一些更改。起初,我记下了受噪音影响的读数。我发现噪声的最大值是10。所以我编写了这样的程序,如果同一引脚的新值与旧值之间的差异大于10,它只会考虑新值然后调到想要的频道。
无效循环() { int channel1 =187 ,avg=0, newA; 静态int oldA = 0; 整数结果 = 0; newA = 模拟读取(A0); 如果 ((newA - oldA) > 10 || (oldA - newA) > 10){ 序列号.println(newA); 如果(新A!=旧A){ 通道 = 通道 1+(newA/10); 我的改变频道(频道); 旧A=新A; } } }//循环结束
该函数用于设置tune_config数组的字节,然后使用 I2C 协议将数据传输到 RDA5807M IC。
void myChangeChannel(int channel){ /* 如果没有返回则为 void else int */ tune_config[2] = (频道 >> 2); tune_config[3] = ((频道 & 0b11) << 6) | 0b00010000; Wire.begin(); Wire.beginTransmission(RDA5807M_ADDRESS); Wire.write(tune_config, TUNE_CONFIG_LEN); Wire.endTransmission(); }
Arduino FM 收音机的工作原理
当模块上电时,我们的代码重置 RDA5807-M IC 并将其设置为用户所需的通道(注意:此频率被视为频率将增加的基本频率)。通过更改电位器(连接到 A0),Arduino Nano 读取的值会发生变化。如果新旧值之差大于 10,我们的代码会考虑这个新值。通道根据新值与旧值的变化而变化。增加或减少音量取决于电位器,它连接在引脚 3 和 GND 之间。
#include
/* 选择我们想要调谐到的频率*
选择所需频率的频道
*/
uint16_t channel = 187;
/*
* 假设频段从 87.0MHz 开始(根据以下设置)
* 通道间隔为 100kHz(0.1MHz)(根据以下设置)
* 然后可以按如下方式得出通道:
*
* 通道 =(<以 MHz 为单位的所需频率> - 87.0) / 0.1
*
* 等同于:
* <10 x 所需频率 (MHz)> - 870
*/
#define RDA5807M_ADDRESS 0b0010000 // 0x10
#define BOOT_CONFIG_LEN 12
#define TUNE_CONFIG_LEN 4
/*
* 这些字节设置了我们的初始配置
* 在这个阶段我们不会费心去调到一个频道。
* 但改为启动重置。
*/
uint8_t boot_config[] = {
/* register 0x02 */
0b11000001,
/*
* DHIZ audio output high-z disable
* 1 = normal operaTIon
*
* DMUTE mute disable
* 1 = normal operaTIon
*
* MONO mono select
* 0 = stereo
*
* BASS 低音增强
* 0 = 禁用
*
* RCLK 非校准模式
* 0 = 始终提供 RCLK
*
* RCLK 直接输入模式
* 0 = ??? 不确定这是做什么的
*
* SEEKUP
* 0 = 向下搜索
*
* SEEK
* 0 = 禁用/停止搜索(即不搜索)
*/
0b00000011,
/*
* SKMODE 搜索模式:
* 0 = 向上换行或下限和继续搜索
*
* CLK_MODE 时钟模式
* 000 = 32.768kHZ 时钟速率(匹配模块上的手表晶体)
*
* RDS_EN 无线电数据系统启用
* 0 = 禁用无线电数据系统
*
* NEW_METHOD 使用新的解调方法进行改进灵敏度
* 0 = 可能已禁用
*
* SOFT_RESET
* 1 = 执行重置
*
* ENABLE 上电启用:
* 1 = 启用
*/
/* 寄存器 0x03 */
/* 在此阶段不要费心调谐到频道*/
0b00000000 ,
/*
* CHAN 通道选择总共 10 的 8 个最高有效位
* 0000 0000 = 此时不要对通道进行编程
*/
0b00000000,
/*
* CHAN 总共 10 的两个最低有效位
* 00 = don '此时无需费心对频道进行编程
*
* DIRECT MODE 仅在测试时使用
* 0 = 可能禁用
*
* TUNE 开始调谐 *** 作
* 0 = 禁用(即不调谐到所选频道)
*
* BAND 波段选择
* 00 = 选择 87-108MHz 波段
*
* SPACE 频道间隔
* 00 = 选择间隔通道之间 100kHz
*/
/* 寄存器 0x04 */
0b00001010,
/*
* 保留 15
* 0
*
* 大概保留 14
* 0
*
* 保留 13:12
* 00
*
* DE 去加重:
* 1 = 澳大利亚使用的 50us 去加重
*
* 保留
* 0
*
* SOFTMUTE_EN
* 1 = 启用软静音
*
* AFCD AFC 禁用
* 0 = AFC 启用
*/
0b00000000,
/*
* 位 7-0 未指定,所以假设所有的 0
* 0000 0000
*/
/* 寄存器 0x05 */
0b10001000,
/*
* INT_MODE
* 1 = 中断最后直到读取 reg 0x0C
*
* 保留 14:12
* 000
*
* SEEKTH 寻道信噪比阈值
* 1000 = 建议的默认值
*/
0b00001111,
/*
* 大概保留 7:6
* 00
*
* 保留 5:4
* 00
*
* 音量
* 1111 = 最大音量
*/
/* 寄存器 0x06 */
0b00000000,
/*
* 保留 15
* 0
*
* OPEN_MODE 打开保留寄存器模式
* 00 = 建议的默认值
*
* 未指定位 12:8,因此假设全为 0
* 00000
*/
0b00000000,
/*
* 位 7:0 未指定,因此假设全为 0
* 00000000
*/
/* 寄存器 0x07 */
0b01000010,
/*
* 保留 15
* 0
*
* TH_SOFRBLEND 噪声软混合设置阈值
* 10000 = 使用默认值
*
* 65M_50M MODE
* 1 = 仅适用于 0b11 的 BAND 设置,因此这里也可以使用 0
*
* RESERVED 8
* 0
*/
0b00000010,
/*
* SEEK_TH_OLD 旧搜索模式的搜索阈值
* 000000
*
* SOFTBLEND_EN 软混合启用
* 1 = 使用默认值
*
* FREQ_MODE
* 0 = 使用默认值
*/
};
/* 复位后,我们可以调整设备
* 我们只需要编程前 4 个字节就可以做到这一点
*/
uint8_t tune_config[] = {
/* register 0x02 */
0b11000000,
/*
* DHIZ audio output high-z disable
* 1 = 正常运行
*
* DMUTE 静音禁用
* 1 = 正常运行
*
* MONO 单声道选择
* 0 = 单声道
*
* BASS 低音增强
* 0 = 禁用
*
* RCLK 非校准模式
* 0 = 始终提供RCLK
*
* RCLK 直接输入模式
* 0 = ??? 不确定这是做什么的
*
* SEEKUP
* 0 = 向下搜索
*
* SEEK
* 0 = 禁用/停止搜索(即不搜索)
*/
0b00000001,
/*
* SKMODE 搜索模式:
* 0 = 向上换行或下限和继续寻求
*
* CLK_MODE 时钟模式
* 000 = 32.768kHZ 时钟速率(匹配模块上的手表晶体)
*
* RDS_EN 无线电数据系统启用
* 0 = 禁用无线电数据系统
*
* NEW_METHOD 使用新的解调方法来提高灵敏度
* 0 = 可能已禁用
*
* SOFT_RESET
* 0 = 这次不要重置
*
* 启用上电启用:
* 1 = 启用
*/
/* 寄存器 0x03 */
/* 这是我们设置要调谐到的频率的位置 */
(channel >> 2),
/* CHAN channel select 8 most Significant bits of 10 */
((channel & 0b11) << 6) | 0b00010000
/*
* CHAN 总共 10 的两个最低有效位
*
* DIRECT MODE 仅在测试时使用
* 0 = 可能禁用
*
* TUNE 开始调谐 *** 作
* 1 = 启用(即调谐到所选频道)
*
* BAND 波段选择
* 00 = 选择 87-108MHz 波段
*
* SPACE 频道间隔
* 00 = 选择通道之间的 100kHz 间隔
*/
};
无效设置()
{
序列.开始(9600);
pinMode(A0,输入);
Wire.begin();
Wire.beginTransmission(RDA5807M_ADDRESS);
Wire.write(boot_config, BOOT_CONFIG_LEN);
Wire.endTransmission();
Wire.beginTransmission(RDA5807M_ADDRESS);
Wire.write(tune_config, TUNE_CONFIG_LEN);
Wire.endTransmission();
}//设置结束
void loop()
{
int channel1 =90,newA;
静态int oldA = 0; // 将 oldA 设置为 HIGH
int result = 0;
newA = 模拟读取(A0);
if ((newA - oldA) > 10 || (oldA - newA) > 10){
Serial.println(newA);
if(newA!= oldA){
通道 = 通道 1+(newA/10);
我的改变频道(频道);
旧A=新A;
}
}
uint16_t 频率 = 频道+870;
uint16_t num1 = (频率/1000) % 10;
uint16_t num2 = (频率/100) % 10;
uint16_t num3 = (频率/10) % 10;
uint16_t num4 = 频率 % 10;
序列号.print(num1);
序列号.print(num2);
序列号.print(num3);
序列号.print(num4);
Serial.print("--");
Serial.println(通道+870);
}//loop end
/*
* 改变radio RDA5807频道的函数
* 示例:channel = 191
*/
void myChangeChannel(int channel){ /* 如果没有返回则为void else int */
/*
* 首先将新频道写入tune_config海量
*/
tune_config[2] = (频道 >> 2);
tune_config[3] = ((频道 & 0b11) << 6) | 0b00010000;
Wire.begin();
Wire.beginTransmission(RDA5807M_ADDRESS);
Wire.write(tune_config, TUNE_CONFIG_LEN);
Wire.endTransmission();
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)