14.FM Radio Receiver Module

Arduino กับ FM Radio Receiver Module (RDA5807SS)

อุปกรณ์

บอร์ด Arduino

FM Radio Receiver Module RDA5807SS

LCD

เครื่องมือ

Arduino-1.0.3

ความสามารถ

    1. Arduino ทำหน้าที่เป็น ตัวควบคุม ให้ภาครับ FM ทำงาน

    2. แสดงค่าความดังและสถานีได้ทาง LCD

วงจร

คู่มือของ FM Module ดูได้จาก เอกสารแนบ

ตัวอย่างโปรแกรมแก้ไขมาจาก http://pastebin.com/KEyfK0dd

โปรแกรมนี้ยังไม่ต้องต่อ LCD แต่ใช้การสั่งงานผ่านทาง Serial Monitor

เมื่อรันโปรแกรมที่ Serial Monitor จะเป็นดังนี้

คำสั่งสำหรับสั่งงานดูได้จาก หน้าต่าง Serial Monitor

เช่น + หรือ - เป็นการปรับคลื่น และ เครื่องหมาย > หรือ < ปรับความดังเสียง

โปรแกรม

// i2c fm parallax part 27984

// bs2 and spin code available

// device has 2 I2C address, ending in 0, no addresses required Ahhhh

// write configregs 5x2 read status 2x2

// have to enable tune to set channel

#include <Wire.h>

#include <stdint.h>

#include <string.h>

// SDA pin is Analog4 module pin 1 internal pullup ok

// SCL pin is Analog5 module pin 2

// grnd to pin 10 v3.3-5v to pin 9

// device ID

#define SLAVE_ID 0x20 >> 1

#define CONFIG_WORDS 5

#define STATUS_WORDS 4

static uint16_t Config0[CONFIG_WORDS] = {0xD001, 0, 0x0400, 0x86D3, 0x4000};

static uint16_t Config[CONFIG_WORDS], Status[STATUS_WORDS];

// config 0 register 02

#define DHIZ 15

#define DMUTE 14

#define MONO 13

#define BASS 12

#define CLK32_INPUT_ENB 10

#define SEEK 8

#define CLK_MODE 4

#define SOFT_RESET 1

#define ENABLE 0

#define CLK_MODE_MASK (7 << CLK_MODE)

#define SEEK_MASK (3 << SEEK)

#define SEEK_UP (3 << SEEK)

#define SEEK_DOWN (1 << SEEK)

// config 1 register 03

#define CHAN 6

#define TUNE 4

#define BAND 2

#define SPACE 0

#define CHAN_MASK (0xff << CHAN)

#define BAND_MASK ( 3 << BAND)

#define SPACE_MASK ( 3 << SPACE)

// config 2 register 04

#define STCEIN 14

#define DE 11

#define I2S_ENABLED 6

#define GPIO3 4

#define GPIO2 2

#define GPIO1 0

#define GPIO3_MASK ( 3 << GPIO3)

#define GPIO2_MASK ( 3 << GPIO2)

#define GPIO1_MASK ( 3 << GPIO1)

// config 3 register 05

#define INT_MODE 15

#define SEEKTH 8

#define LNA_PORT_SEL 6

#define LNA_ICSEL_BIT 4

#define VOLUME 0

#define SEEKTH_MASK (0x7f << SEEKTH)

#define LNA_PORT_MASK (2 << LNA_PORT_SEL)

#define LNA_ICSEL_MASK (2 << LNA_ICSEL_BIT)

#define VOLUME_MASK (0x0f << VOLUME)


// status regs

// status 0 register 0a

#define STC 14

#define SF 13

#define ST 10

#define READCHAN 0

#define READCHAN_MASK (0xff << READCHAN)

// status 1 register 0b

#define RSS 9

#define FM_TRUE 8

#define FM_READY 7

#define RSS_MASK (0x7f << RSS)

// assume band 0 760 for other spacing .1 MHz

#define MAX_PRESETS 10

#define MAX_FREQ 1080

#define MIN_FREQ 870

#define MAX_SST 127

#define MAX_VOL 15

uint16_t fm_vol=1, fm_chan = 975; // channel spacing 100KHz

uint16_t fm_rss, fm_readchan,fm_sst=6,fm_st,fm_true,fm_ready,fm_stc,fm_sf;

uint16_t fm_seek, fm_presets[MAX_PRESETS] = {919,975}, fm_presetnext=2;;

bool seeking;

void setup()

{

int channel;

Wire.begin(); // connect I2C

Serial.begin(9600);

delay(5);

Serial.println("FM Demo");

fm_reset();

printConfig();

printPresets();

delay(100);

getStatus();

printStatus();

}

void loop()

{

uint8_t c;

bool update;

Serial.println();

Serial.println("Freq +/- Vol >/< Seek u/d Preset 0-9 AddPreset A Reset R SST x/y");

Serial.println(" Enter command character:");

while(!Serial.available()) delay(1);

c = Serial.read();

Serial.println((char)c);

update = false;

switch(c) {

case '+':

update = chan_update(fm_chan+1);

break;

case '-':

update = chan_update(fm_chan-1);

break;

case '>':

update = vol_update(fm_vol+1);

break;

case '<':

update = vol_update(fm_vol-1);

break;

case 'u':

Config[0] &= ~SEEK_MASK;

Config[0] |= SEEK_UP;

seeking = update = true;

break;

case 'd':

Config[0] &= ~SEEK_MASK;

Config[0] |= SEEK_DOWN;

seeking = update = true;

break;

case 'x':

update = sst_update(fm_sst+1);

break;

case 'y':

update = sst_update(fm_sst-1);

break;

case '0':

case '1':

case '2':

case '3':

case '4':

case '5':

case '6':

case '7':

case '8':

case '9':

chan_update(fm_presets[c - '0']);

update = true;

break;

case 'A':

add_preset();

break;

case 'R':

fm_reset();

update = true;

break;

case '?':

getStatus();

printConfig();

printStatus();

printPresets();

break;

default:

break;

}

if (update || seeking) {

setConfig();

delay(800); // let seek complete ... spin on flags?

getStatus();

if (seeking && fm_stc) {

seek_disable();

chan_update(fm_seek + MIN_FREQ);

setConfig();

}

tune_disable();

printConfig();

printStatus();

}

}

// config updates

void fm_reset() {

seeking = false;

fm_vol = 1;

fm_chan = 975;

fm_sst = 6;

memcpy(Config,Config0,CONFIG_WORDS * sizeof(uint16_t));

Config[1] &= ~CHAN_MASK;

Config[1] |= (fm_chan - MIN_FREQ) << CHAN;

Config[3] &= ~VOLUME_MASK;

Config[3] |= fm_vol << VOLUME;

tune_enable();

setConfig();

tune_disable();

}

void tune_enable() {

Config[1] |= (1 << TUNE);

}

void tune_disable() {

Config[1] &= ~(1 << TUNE);

}

void seek_disable() {

seeking = false;

Config[0] &= ~SEEK_MASK; // turn off seek

}

bool vol_update(int val) {

if (val < 0 || val > MAX_VOL) return false;

fm_vol = val;

Config[3] &= ~VOLUME_MASK;

Config[3] |= fm_vol << VOLUME;

return true;

}

bool chan_update(int val) {

if (val < MIN_FREQ || val > MAX_FREQ) return false;

fm_chan = val;

Config[1] &= ~CHAN_MASK;

Config[1] |= (fm_chan - MIN_FREQ) << CHAN;

tune_enable();

return true;

}

bool sst_update(int val) {

if (val < 0 || val > MAX_SST) return false;

fm_sst = val;

Config[3] &= ~SEEKTH_MASK;

Config[3] |= fm_sst << SEEKTH;

return true;

}

void add_preset() {

if (fm_presetnext >= MAX_PRESETS) return;

fm_presets[fm_presetnext++] = fm_chan;

printPresets();

}

// Set configuration register

void setConfig()

{

int i;

Wire.beginTransmission(SLAVE_ID);

for(i=0; i< CONFIG_WORDS;i++) {

Wire.write((int)Config[i]>>8);

Wire.write((int)(Config[i] & 0xff));

}

Wire.endTransmission();

}

void getStatus()

{

int i;

Wire.requestFrom(SLAVE_ID, STATUS_WORDS*2);

for(i=0; i< STATUS_WORDS;i++) {

Status[i] = Wire.read();

Status[i] = Status[i]<<8 | Wire.read();

}

fm_seek = Status[0] & READCHAN_MASK;

fm_stc = Status[0] >> STC & 1;

fm_sf = Status[0] >> SF & 1;

fm_st = Status[0] >> ST & 1;

fm_rss = (Status[1] & RSS_MASK) >> RSS;

fm_true = Status[1] >> FM_TRUE & 1;

fm_ready = Status[1] >> FM_READY & 1;

}

void printConfig() {

int chan;

char str[128];

sprintf(str,"config %04x %04x %04x %04x",Config[0],Config[1],Config[2],Config[3]);

Serial.println(str);

chan = ((Config[1] & CHAN_MASK) >> CHAN ) + MIN_FREQ;

sprintf(str," fm channel %d.%d volume %d ss %d sst %d",

chan/10,chan%10,fm_vol,fm_rss,fm_sst);

Serial.println(str);

}

void printStatus() {

int chan;

char str[128];

sprintf(str,"status %04x %04x",Status[0],Status[1]);

Serial.println(str);

chan = fm_seek + MIN_FREQ;

if(seeking) Serial.print("seeking ... ");

sprintf(str," seek channel %d.%d ss %d stereo %d complete %d fail %d %d %d",

chan/10,chan%10,fm_rss,fm_st,fm_stc,fm_sf,fm_true,fm_ready);

Serial.println(str);

}

void printPresets() {

int chan,i;

char str[128];

Serial.print("Presets: ");

for (i=0;i<fm_presetnext;i++) {

chan = fm_presets[i];

sprintf(str,"%d.%d ",chan/10,chan%10);

Serial.print(str);

}

Serial.println();

}

#define SID (0x22 >> 1)

void i2cdump(uint8_t addr, int n)

{

int i;

uint16_t buff[8];

char str[128];

Serial.print(addr,HEX); Serial.println(" dump");

Wire.beginTransmission(SID);

Wire.write(addr); // start addr

Wire.endTransmission();

Wire.requestFrom(SID, n*2);

for(i=0; i< n;i++) {

buff[i] = Wire.read();

buff[i] = buff[i]<<8 | Wire.read();

sprintf(str,"%04x ",buff[i]);

Serial.print(str);

}

Serial.println();

}

แบบที่ 2 แสดงค่าความถี่ออกทาง LCD

อ้างอิง

  1. https://sites.google.com/site/eplearn/microcontroller/fm_tunner

    1. http://pastebin.com/KEyfK0dd