今天幾乎每個人都用手機聽音樂、新聞、播客等。但不久前,我們都依靠當地的 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 引導配置 [] = { /* 寄存器 0x??02 */ 0b11000001, 0b00000011, /* 寄存器 0x??03 */ 0b00000000, 0b00000000, /* 寄存器 0x??04 */ 0b00001010, 0b00000000, /* 寄存器 0x??05 */ 0b10001000, 0b00001111, /* 寄存器 0x??06 */ 0b00000000, 0b00000000, /* 寄存器 0x??07 */ 0b01000010, 0b00000010, };
?
重置設備后,我們可以調整設備。為了調諧通道,我們只需要編程前 4 個字節。這部分代碼會將頻道更改為所需的頻率。在 I2C 中,我們首先開始傳輸,寫入或讀取數據,然后結束傳輸。在這個接收器IC中,我們不必指定地址,因為數據表清楚地說明了I2C接口有一個固定的起始寄存器,即0x02h用于寫操作,0x0Ah用于讀操作。
?
uint8_t tune_config[] = { /* 寄存器 0x??02 */ 0b11000000, 0b00000001, /* 寄存器 0x??03 */ (頻道 >> 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 = 啟用
? ? ?*/??
? /* 寄存器 0x??03 */?
? ? /* 在此階段不要費心調諧到頻道*/?
? 0b00000000 ,??
? ? /*??
? ? ?* CHAN 通道選擇總共 10 的 8 個最高有效位
? ? ?* 0000 0000 = 此時不要對通道進行編程
? ? ?*/?
? 0b00000000,?
? ? /*??
? ? ?* CHAN 總共 10 的兩個最低有效位?
? ? ?* 00 = don '此時無需費心對頻道進行編程
? ? ?*?
? ? ?* DIRECT MODE 僅在測試時使用
? ? ?* 0 = 可能禁用
? ? ?*?
? ? ?* TUNE 開始調諧操作?
? ? ?* 0 = 禁用(即不調諧到所選頻道)
? ? ?*?
? ? ?* BAND 波段選擇
? ? ?* 00 = 選擇 87-108MHz 波段
? ? ?*?
? ? ?* SPACE 頻道間隔
? ? ?* 00 = 選擇間隔通道之間 100kHz?
? ? ?*/? ? ?
? /* 寄存器 0x??04 */?
? 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?
? ? ?*/? ?
? /* 寄存器 0x??05 */?
? 0b10001000,??
? ? /*??
? ? ?* INT_MODE?
? ? ?* 1 = 中斷最后直到讀取 reg 0x0C?
? ? ?*?
? ? ?* 保留 14:12??
? ? ?* 000?
? ? ?*?
? ? ?* SEEKTH 尋道信噪比閾值
? ? ?* 1000 = 建議的默認值
? ? ?*/? ??
? 0b00001111,??
? ? /*??
? ? ?* 大概保留 7:6?
? ? ?* 00?
? ? ?*?
? ? ?* 保留 5:4?
? ? ?* 00?
? ? ?*?
? ? ?* 音量
? ? ?* 1111 = 最大音量
? ? ?*/??
? /* 寄存器 0x??06 */?
? 0b00000000,??
? ? /*??
? ? ?* 保留 15?
? ? ?* 0?
? ? ?*?
? ? ?* OPEN_MODE 打開保留寄存器模式
? ? ?* 00 = 建議的默認值
? ? ?*?
? ? ?* 未指定位 12:8,因此假設全為 0?
? ? ?* 00000?
? ? ?*/? ??
? 0b00000000,??
? ? /*?
? ? ?* 位 7:0 未指定,因此假設全為 0?
? ? ?* 00000000?
? ? ?*/? ? ?
? /* 寄存器 0x??07 */?
? 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 = 啟用
? ? ?*/??
? ?/* 寄存器 0x??03 */?
? ?/* 這是我們設置要調諧到的頻率的位置 */?
? ?(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();?
? }
評論
查看更多