Si4730과 아두이노 나노로 만드는 전대역 라디오 - LW, MW, SW, FM
부품 및 소모품
| Arduino Nano R3 |
1 |
| Si4730 라디오 모듈 |
1 |
| Adafruit 16x2 LCD (백색/파랑) |
1 |
| 로터리 인코더 (푸시버튼 포함) |
1 |
| 클래스 D 오디오 앰프 모듈 (PAM8403) |
1 |
| 스피커 (0.25W, 8옴) |
1 |
| 페라이트 로드 안테나 (구형 MW 라디오에서 추출) |
1 |
| 슬라이드 스위치 |
1 |
필요 도구
앱 및 온라인 서비스
프로젝트 개요
아두이노 라디오라 하면 보통 FM 라디오(유럽 기준 88-108 MHz)를 떠올립니다. 하지만 LW(장파), MW(중파), SW(단파) 대역은 0.2~30 MHz를 커버합니다. 특히 SW는 전리층 반사로 대륙 간 장거리 통신이 가능해 매력적입니다.
이 프로젝트는 위 모든 대역을 수신하는 라디오를 만듭니다. 핵심은 Silicon Labs의 Si4730 IC로, 알리익스프레스에서 몇 달러에 소형 개발 보드 형태로 구매 가능합니다.
하드웨어 구성
- Si4730 보드는 I2C로 아두이노 제어
- 코드는 Julio C. Rosa 작성, Si4735-I2C-R4 라이브러리 기반
- 제조사 스펙은 AM/FM만 지원하나 실제로는 SW도 수신 가능
- 오디오 출력은 PAM8403 클래스 D 앰프 보드(2×3W) 사용, 저렴하고 성능 양호
완성된 기기는 적절한 케이스에 조립해 소형 월드밴드 라디오로 사용합니다. 지상층 밀집 지역에서 10m 롱와이어 안테나로 수신 시 상용 포켓 라디오와 비교해도 손색없는 수신 감도를 보입니다.
참고: 이 칩은 TECSUN, DEGEN, SANGEAN 등 유명 휴대용 라디오 브랜드에서도 널리 사용됩니다.
코드
/**************************************************************************************************
JCR Si4730/5 수신기 LW/MW/SW/FM - 공유 버전. 배선은 회로도 참조.
Written by Julio C. Rosa - The CesarSound - May/2019
주요 명령어:
radio.volumeUp(); radio.volumeDown(); radio.seekDown(); radio.seekUp();
radio.mute(); radio.unmute(); radio.setMode(FM); radio.tuneFrequency(9490);
radio.getStatus(); radio.getVolume(); radio.getMode(); radio.getMute();
radio.toggleMute(); RSQMetrics rsq; radio.getRSQ(&rsq);
*****************************************************************************************************/
#include <Si4735.h>
#include <LiquidCrystal.h>
#include <rotary.h>
#include "Wire.h"
// I/O 설정
Rotary r = Rotary(2, 3);
LiquidCrystal lcd(12, 13, 7, 6, 5, 4);
const byte band = A0;
// 변수 설정
unsigned int freq = 880;
unsigned int freqmax = 10800;
unsigned int freqmin = 50;
unsigned int fstep = 10;
unsigned int freqold;
unsigned int buttonstate;
unsigned int count = 15;
Si4735 radio;
void setup() {
lcd.begin(16, 2);
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
pinMode(band, INPUT_PULLUP);
radio.begin();
radio.setMode(AM);
command_am();
radio.tuneFrequency(freq);
lcd.setCursor(0, 2);
lcd.print("JCR Multiband Rx");
lcd.setCursor(0, 0);
lcd.print("F>>");
lcd.setCursor(3, 0);
lcd.print(":");
lcd.setCursor(13, 0);
lcd.print("kHz");
}
// 인코더 인터럽트
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (result) {
if (result == DIR_CW) {
freq = freq + fstep;
if (freq >= freqmax) freq = freqmax;
} else {
freq = freq - fstep;
if (freq <= freqmin) freq = freqmin;
}
}
}
void loop() {
if (freqold != freq) { tune(); }
freqold = freq;
lcd.setCursor(5, 0);
lcd.print(freq);
lcd.print(" ");
buttonstate = digitalRead(band);
if (buttonstate == LOW) {
inc_preset();
while (digitalRead(band) == 0);
}
// S-미터 (dBu) 및 SNR (dB) 표시
RSQMetrics rsq;
radio.getRSQ(&rsq);
lcd.setCursor(0, 2);
lcd.print("dBu: ");
lcd.print(rsq.RSSI);
lcd.setCursor(9, 2);
lcd.print("dB: ");
lcd.print(rsq.SNR);
}
void inc_preset() {
count++;
if (count > 15) count = 1;
bandpresets();
delay(100);
}
void bandpresets() {
lcd.setCursor(0, 0);
switch (count) {
case 1: freq = 370; radio.setMode(LW); radio.tuneFrequency(freq); command_am(); fstep = 5; lcd.print("LW1"); break;
case 2: freq = 620; radio.setMode(AM); radio.tuneFrequency(freq); fstep = 5; lcd.print("MW1"); break;
case 3: freq = 840; radio.setMode(AM); radio.tuneFrequency(freq); fstep = 5; lcd.print("MW2"); break;
case 4: freq = 3700; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW0"); break;
case 5: freq = 4985; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW1"); break;
case 6: freq = 6010; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 1; lcd.print("SW2"); break;
case 7: freq = 7200; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 1; lcd.print("SW3"); break;
case 8: freq = 10000; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW4"); break;
case 9: freq = 11940; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW5"); break;
case 10: freq = 13710; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW6"); break;
case 11: freq = 15400; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW7"); break;
case 12: freq = 17560; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW8"); break;
case 13: freq = 21505; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("SW9"); break;
case 14: freq = 27015; radio.setMode(SW); radio.tuneFrequency(freq); fstep = 5; lcd.print("CB1"); break;
case 15: freq = 9700; radio.setMode(FM); radio.tuneFrequency(freq); fstep = 10; lcd.print("FM1"); break;
}
}
void tune() { radio.tuneFrequency(freq); }
void command_am() {
radio.setProperty(PROP_AM_SOFT_MUTE_MAX_ATTENUATION, 0);
radio.setProperty(PROP_AM_AUTOMATIC_VOLUME_CONTROL_MAX_GAIN, 0x3A98);
}
라이브러리
Si4735, rotary 라이브러리 필요 (다운로드 필요)
회로도
회로도 파일 별도 제공