아두이노 코딩 코드 소스 : RDA5807을 사용한 Arduino FM 라디오
오늘날 거의 모든 사람들이 음악, 뉴스, 팟캐스트 등을 듣기 위해 휴대폰을 사용합니다. 하지만 얼마 전까지만 해도 우리는 모두 최신 뉴스와 노래를 듣기 위해 지역 FM 라디오에 의존하고 있었습니다. 서서히 이 라디오들은 인기를 잃어가고 있지만, 인터넷이 다운되면, 라디오는 사용자에게 정보를 전달하는 중요한 역할을 합니다. 라디오 신호는 항상 공기 중(방송국에서 방송함)에 존재하며, 이러한 무선 신호를 포착하여 오디오 신호로 전송하는 FM 수신기 회로만 있으면 됩니다. 또한 이전 튜토리얼에서는 아래에 나열된 FM 송신기 및 수신기를 거의 제작하지 않았습니다.
라즈베리 파이 FM 송신기
Raspberry Pi FM 수신기 라디오
FM 송신기 회로
FM 송신기 회로에 인덕터가 없습니다.
본 자습서에서는 Arduino FM Receiver를 구축하여 프로젝트 무기고에 추가할 예정입니다. RDA5807 FM 수신기 IC를 Arduino와 함께 사용하고 이를 프로그래밍하여 사용자가 전위차계로 튜닝할 수 있는 FM 라디오 방송국을 재생합니다. 또한 오디오 앰프를 회로와 함께 사용하여 Arduino FM 라디오의 출력 볼륨을 제어할 것입니다. 흥미롭게 들리죠? 자, 이제 시작하겠습니다.
FM 라디오가 일반 작동 중입니다.
라디오 방송국은 전기 신호를 라디오 신호로 변환하며, 이러한 신호는 안테나를 통해 전송되기 전에 변조되어야 합니다. 신호를 변조할 수 있는 방법은 AM 및 FM 두 가지가 있습니다. 이름에서 알 수 있듯이 진폭 변조(AM)는 신호를 전송하기 전에 진폭을 변조하는 반면 주파수 변조(FM)에서는 안테나를 통해 전송하기 전에 신호 주파수가 변조됩니다. 라디오 방송국에서는 주파수 변조를 사용하여 신호를 변조한 다음 데이터를 전송합니다. 이제, 우리가 만들면 되는 것은 수신기입니다. 특정 주파수에 맞춰 조정하고, 그 신호를 수신할 수 있고, 나중에 이 전기 신호를 오디오 신호로 변환할 수 있습니다. 이 프로젝트에서는 회로를 단순화하는 RDA5807 FM 수신기 모듈을 사용할 예정입니다.
구성 요소가 필요합니다.
아두이노
RDA5807 수신기
오디오 앰프
와이어를 연결
냄비는 100K
퍼프 보드
RDA5807 수신기
RDA5807은 완전히 통합된 신디사이저를 갖춘 단일 CHIP FM 스테레오 라디오 튜너 모듈입니다. 이 모듈은 50 115 115MHz, 볼륨 컨트롤 및 음소거, 프로그래밍 가능한 디엠퍼시스(50/75us), 수신 신호 강도 표시기 및 SNR, 32.768KHz 크리스털 오실레이터, 디지털 자동 게인 제어 등의 전 세계 주파수 대역을 지원합니다. 아래 그림에는 RDA5807M 튜너의 블록 다이어그램이 나와 있습니다.
디지털 low-IF 아키텍처를 갖추고 있으며, FM 방송 대역(50~115MHz), 프로그램 가능 이득 제어(PGA), 고해상도 아날로그-디지털 변환기 및 고밀도 디지털-아날로그 컨버터(DAC)를 지원하는 저소음 증폭기(LNA)를 통합하고 있습니다. 이 제한 장치는 과부하를 방지하고 인접 채널에 의해 생성된 인터변조 제품 수를 제한합니다. PGA는 믹서 출력 신호를 증폭시킨 다음 ADC로 디지털화합니다. DSP 코어는 채널 선택, FM 복조, 스테레오 MPX 디코더 및 출력 오디오 신호를 관리합니다. IC에 대한 RDA5807 핀아웃 다이어그램은 다음과 같습니다.
이 모듈은 1.8 – 3.3V의 전원 공급 장치에서 작동합니다. 정지 상태로 전환되고 제어 인터페이스를 선택하면 모듈이 VIO 전원을 켤 때 자동으로 재설정되며 02H 주소 중 0 ~ 1의 비트1 트리거에 의한 소프트 재설정을 지원합니다. 모듈은 I2C 통신을 사용하여 MCU와 통신하고 인터페이스는 시작 조건, 명령 바이트 및 데이터 바이트로 시작합니다. RDA5807에는 각각 특정 기능을 수행하는 13개의 16비트 레지스터가 있습니다. 레지스터 주소는 칩 ID에 할당되고 0FH로 끝납니다. 13개 레지스터 모두에서 일부 비트는 R/W인 반면 일부 비트는 예약됩니다. 각 레지스터는 할당된 비트에 따라 볼륨 변경, 채널 변경 등의 작업을 수행합니다.
핀이 닫히므로 모듈을 회로에 연결할 때 모듈을 직접 사용할 수 없습니다. 그래서 저는 아래 사진에서 보듯이, 향수 판과 몇 개의 남성 핀을 사용하여 모듈의 각 핀을 각 남성 핀에 납땜했습니다.
오디오 앰프입니다.
오디오 앰프는 저전력 전자 오디오 신호를 확성기 또는 헤드폰을 구동하기에 충분한 수준으로 증폭하는 전자 장치입니다. LM386을 사용하여 간단한 오디오 앰프를 제작했습니다. 동일한 회로에 대한 회로가 아래에 표시되어 있습니다. 또한 링크를 확인하여 이 회로에 대한 자세한 내용을 확인하고 다른 오디오 앰프 회로도 점검할 수 있습니다.
Arduino FM 수신기 회로도입니다.
FM 밴드를 조정하고 오디오 앰프의 볼륨을 제어하기 위해 두 개의 전위차계를 사용했습니다. 볼륨을 변경하기 위해 LM386의 1번째 핀과 8번째 핀 사이에 연결된 포트 또는 LM386의 핀 3에 연결된 포트를 변경할 수 있습니다. 아래 사진은 Arduino FM 라디오의 전체 회로 다이어그램을 보여줍니다.
앰프를 조금 바꿨어요. 앰프에 두 개의 전위차계를 사용하는 대신, 저는 한 개만 사용했습니다. 가인(Gain)을 바꾸는 데 쓰이는 항아리를 저항기와 상호 교환했습니다. 이제 저희 프로젝트에는 두 개의 전위차계가 있습니다. 하나는 음량을 조절할 수 있고 하나는 음량을 바꿀 수 있습니다. 채널을 조정하는 데 사용되는 전위차계는 Arduino 나노와 연결됩니다. 화분 중앙 핀은 아두이노 나노의 A0 핀에 연결되며, 나머지 핀 2개는 5V에 연결되고 다른 핀은 GND에 연결되며, 다른 포트는 라디오의 볼륨을 제어하는 데 사용되며 위의 무화과와 같이 연결됩니다.
Arduino의 핀 A4 및 A5는 RDA5807M의 SDA 및 SCL 핀에 연결되어 있습니다. 수신기 모듈은 3.3V에서만 작동합니다. 따라서, 나노의 3v3 핀을 수신기 모듈의 VCC 핀에 연결합니다. 일단 연결고리가 만들어지면 이렇게 생겼어요.
Arduino FM 라디오 코드 설명입니다.
이 코드는 수신기 모듈을 초기화한 다음 채널을 사전 설정된 주파수로 설정합니다. A0 핀에서 나노가 읽은 값이 변경되면(포트 변경으로) 주파수가 변경되고 주파수가 변경되어 채널이 변경됩니다. 전체 코드는 페이지 끝에 지정됩니다.
우리는 RDA5807과의 통신에 필요한 와이어 라이브러리를 추가하는 것으로 프로그램을 시작합니다. 그런 다음 변수 "채널"에서 채널 값을 설정합니다. 라디오가 시작될 때마다 이 채널에 자동으로 튜닝됩니다.
#include <Wire.h>
uint16_t channel = 187;
그런 다음 RDA5807 IC의 각 레지스터에 바이트를 로드하여 초기 구성을 설정합니다. 이 시점에서 수신기를 재설정하고 있습니다.
uint8_t boot_config[] = {
/* register 0x02 */
0b11000001,
0b00000011,
/* register 0x03 */
0b00000000,
0b00000000,
/* register 0x04 */
0b00001010,
0b00000000,
/* register 0x05 */
0b10001000,
0b00001111,
/* register 0x06 */
0b00000000,
0b00000000,
/* register 0x07 */
0b01000010,
0b00000010,
};
장치를 재설정하면 장치를 조정할 수 있습니다. 채널을 튜닝하려면 처음 4바이트만 프로그래밍하면 됩니다. 코드의 이 부분은 채널을 원하는 주파수로 변경합니다. I2C에서는 처음에는 전송을 시작하고 데이터를 쓰거나 읽은 다음 전송을 종료합니다. 이 수신기 IC에서는 데이터시트에 I2C 인터페이스에 고정된 시작 레지스터(예: 쓰기 작업의 경우 0x02h, 읽기 작업의 경우 0x0Ah)가 있다고 명시되어 있으므로 주소를 지정할 필요가 없습니다.
uint8_t tune_config[] = {
/* register 0x02 */
0b11000000,
0b00000001,
/* register 0x03 */
(channel >> 2),
((channel & 0b11) << 6 ) | 0b00010000
};
설정에서는 부팅 구성(재설정)을 초기화한 다음 튜닝 구성 바이트를 RDA5807M에 기록하여 채널에 튜닝합니다.
void setup()
{
Serial.begin(9600);
pinMode(A0,INPUT);
/* Conect to RDA5807M FM Tuner: */
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();
}
주파수를 맞추는 데 냄비를 사용할 때, 저는 문제에 직면했습니다. A0 핀으로 읽는 값은 일정하지 않습니다. 원하는 값을 가진 노이즈 클럽이 있습니다. A0과 GND 사이에 연결된 0.1uF 세라믹 커패시터를 사용했지만 노이즈가 최소화되었으므로 원하는 수준에 미치지 못했습니다. 그래서 저는 코드를 몇 가지 수정해야 했습니다. 처음에는 소음의 영향을 받는 수치를 기록해 두었습니다. 소음의 최대값은 10이라는 것을 알게 되었습니다. 그래서 저는 새로운 값과 같은 핀의 이전 값의 차이가 10보다 큰 경우에만 새로운 값을 고려하도록 프로그램을 작성했습니다. 그리고 나서 원하는 채널로 튜닝합니다.
void loop()
{
int channel1 =187 ,avg=0, newA;
static int oldA = 0;
int result = 0;
newA = analogRead(A0);
if ((newA - oldA) > 10 || (oldA - newA) > 10){
Serial.println(newA);
if(newA!= oldA){
channel = channel1+(newA/10);
myChangeChannel(channel);
oldA=newA;
}
}
}//loop end
이 기능은 touch_config 어레이의 바이트를 설정한 다음 I2C 프로토콜을 사용하여 데이터를 RDA5807M IC로 전송하는 데 사용됩니다.
void myChangeChannel(int channel){ /* void if nothing is returned else int */
tune_config[2] = (channel >> 2);
tune_config[3] = ((channel & 0b11) << 6 ) | 0b00010000;
Wire.begin();
Wire.beginTransmission(RDA5807M_ADDRESS);
Wire.write(tune_config, TUNE_CONFIG_LEN);
Wire.endTransmission();
}
Arduino FM 라디오를 사용합니다.
모듈의 전원이 켜지면 NAT 코드는 RDA5807-M IC를 재설정하여 원하는 사용자의 채널로 설정합니다(참고: 이 주파수는 주파수가 증가할 기본 주파수로 간주됨). 전위차계(A0에 연결됨)를 변경하면 Arduino Nano에서 읽은 값이 변경됩니다. 새 값과 이전 값의 차이가 10보다 클 경우, 우리 코드는 이 새 값을 고려합니다. 채널은 이전 값에서 새 값이 변경됨에 따라 변경됩니다. 볼륨 증가 또는 감소는 핀 3과 GND 사이에 연결된 전위차계에 따라 달라집니다.
시공 및 코딩이 끝나면 FM 라디오를 직접 사용할 수 있습니다. FM 라디오의 전체 작동은 이 페이지 하단에 연결된 비디오에서 확인할 수 있습니다. 당신이 그 프로젝트를 즐기고 유용한 것을 배웠기를 바랍니다. 이 프로젝트를 진행하기 위해 질문이 있는 경우, 코멘트 섹션에 남겨두거나 포럼을 사용하여 다른 기술 지원을 받을 수 있습니다.
Code
#include <Wire.h>
/* Select the frequency we want to tune to by way
* of selecting the channel for the desired frequency
*/
uint16_t channel = 187;
/*
* assuming band starts at 87.0MHz (per settings below)
* and channel spacing of 100kHz (0.1MHz) (per settings below)
* then channel can be derived as follows:
*
* channel = (<desired freq in MHz> - 87.0) / 0.1
*
* which is the same as:
* <10 x desired freq in MHz> - 870
*/
#define RDA5807M_ADDRESS 0b0010000 // 0x10
#define BOOT_CONFIG_LEN 12
#define TUNE_CONFIG_LEN 4
/*
* These bytes set our initial configuration
* We don't bother to tune to a channel at this stage.
* But instead initiate a reset.
*/
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 bass boost
* 0 = disabled
*
* RCLK NON-CALIBRATE MODE
* 0 = RCLK is always supplied
*
* RCLK DIRECT INPUT MODE
* 0 = ??? not certain what this does
*
* SEEKUP
* 0 = seek in down direction
*
* SEEK
* 0 = disable / stop seek (i.e. don't seek)
*/
0b00000011,
/*
* SKMODE seek mode:
* 0 = wrap at upper or lower band limit and contiue seeking
*
* CLK_MODE clock mode
* 000 = 32.768kHZ clock rate (match the watch cystal on the module)
*
* RDS_EN radio data system enable
* 0 = disable radio data system
*
* NEW_METHOD use new demodulate method for improved sensitivity
* 0 = presumably disabled
*
* SOFT_RESET
* 1 = perform a reset
*
* ENABLE power up enable:
* 1 = enabled
*/
/* register 0x03 */
/* Don't bother to tune to a channel at this stage*/
0b00000000,
/*
* CHAN channel select 8 most significant bits of 10 in total
* 0000 0000 = don't boher to program a channel at this time
*/
0b00000000,
/*
* CHAN two least significant bits of 10 in total
* 00 = don't bother to program a channel at this time
*
* DIRECT MODE used only when test
* 0 = presumably disabled
*
* TUNE commence tune operation
* 0 = disable (i.e. don't tune to selected channel)
*
* BAND band select
* 00 = select the 87-108MHz band
*
* SPACE channel spacing
* 00 = select spacing of 100kHz between channels
*/
/* register 0x04 */
0b00001010,
/*
* RESERVED 15
* 0
*
* PRESUMABLY RESERVED 14
* 0
*
* RESERVED 13:12
* 00
*
* DE de-emphasis:
* 1 = 50us de-emphasis as used in Australia
*
* RESERVED
* 0
*
* SOFTMUTE_EN
* 1 = soft mute enabled
*
* AFCD AFC disable
* 0 = AFC enabled
*/
0b00000000,
/*
* Bits 7-0 are not specified, so assume all 0's
* 0000 0000
*/
/* register 0x05 */
0b10001000,
/*
* INT_MODE
* 1 = interrupt last until read reg 0x0C
*
* RESERVED 14:12
* 000
*
* SEEKTH seek signal to noise ratio threshold
* 1000 = suggested default
*/
0b00001111,
/*
* PRESUMABLY RESERVED 7:6
* 00
*
* RESERVED 5:4
* 00
*
* VOLUME
* 1111 = loudest volume
*/
/* register 0x06 */
0b00000000,
/*
* RESERVED 15
* 0
*
* OPEN_MODE open reserved registers mode
* 00 = suggested default
*
* Bits 12:8 are not specified, so assume all 0's
* 00000
*/
0b00000000,
/*
* Bits 7:0 are not specified, so assume all 0's
* 00000000
*/
/* register 0x07 */
0b01000010,
/*
* RESERVED 15
* 0
*
* TH_SOFRBLEND threshhold for noise soft blend setting
* 10000 = using default value
*
* 65M_50M MODE
* 1 = only applies to BAND setting of 0b11, so could probably use 0 here too
*
* RESERVED 8
* 0
*/
0b00000010,
/*
* SEEK_TH_OLD seek threshold for old seek mode
* 000000
*
* SOFTBLEND_EN soft blend enable
* 1 = using default value
*
* FREQ_MODE
* 0 = using defualt value
*/
};
/* After reset, we can tune the device
* We only need program the first 4 bytes in order to do this
*/
uint8_t tune_config[] = {
/* register 0x02 */
0b11000000,
/*
* DHIZ audio output high-z disable
* 1 = normal operation
*
* DMUTE mute disable
* 1 = normal operation
*
* MONO mono select
* 0 = mono
*
* BASS bass boost
* 0 = disabled
*
* RCLK NON-CALIBRATE MODE
* 0 = RCLK is always supplied
*
* RCLK DIRECT INPUT MODE
* 0 = ??? not certain what this does
*
* SEEKUP
* 0 = seek in down direction
*
* SEEK
* 0 = disable / stop seek (i.e. don't seek)
*/
0b00000001,
/*
* SKMODE seek mode:
* 0 = wrap at upper or lower band limit and contiue seeking
*
* CLK_MODE clock mode
* 000 = 32.768kHZ clock rate (match the watch cystal on the module)
*
* RDS_EN radio data system enable
* 0 = disable radio data system
*
* NEW_METHOD use new demodulate method for improved sensitivity
* 0 = presumably disabled
*
* SOFT_RESET
* 0 = don't reset this time around
*
* ENABLE power up enable:
* 1 = enabled
*/
/* register 0x03 */
/* Here's where we set the frequency we want to tune to */
(channel >> 2),
/* CHAN channel select 8 most significant bits of 10 in total */
((channel & 0b11) << 6 ) | 0b00010000
/*
* CHAN two least significant bits of 10 in total
*
* DIRECT MODE used only when test
* 0 = presumably disabled
*
* TUNE commence tune operation
* 1 = enable (i.e. tune to selected channel)
*
* BAND band select
* 00 = select the 87-108MHz band
*
* SPACE channel spacing
* 00 = select spacing of 100kHz between channels
*/
};
void setup()
{
Serial.begin(9600);
pinMode(A0,INPUT);
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();
}//setup end
void loop()
{
int channel1 =90,newA;
static int oldA = 0; // set the oldA as HIGH
int result = 0;
newA = analogRead(A0);
if ((newA - oldA) > 10 || (oldA - newA) > 10){
Serial.println(newA);
if(newA!= oldA){
channel = channel1+(newA/10);
myChangeChannel(channel);
oldA=newA;
}
}
uint16_t frequency = channel+870;
uint16_t num1 = (frequency / 1000) % 10;
uint16_t num2 = (frequency / 100) % 10;
uint16_t num3 = (frequency / 10) % 10;
uint16_t num4 = frequency % 10;
Serial.print(num1);
Serial.print(num2);
Serial.print(num3);
Serial.print(num4);
Serial.print("--");
Serial.println(channel+870);
}//loop end
/*
* Function to change channel on radio RDA5807
* Example: channel = 191
*/
void myChangeChannel(int channel){ /* void if nothing is returned else int */
/*
* first write new channel to tune_config massive
*/
tune_config[2] = (channel >> 2);
tune_config[3] = ((channel & 0b11) << 6 ) | 0b00010000;
Wire.begin();
Wire.beginTransmission(RDA5807M_ADDRESS);
Wire.write(tune_config, TUNE_CONFIG_LEN);
Wire.endTransmission();
}
댓글