Project 17 - A Digital FM Radio

<< Click to Display Table of Contents >>

Navigation:  Projects >

Project 17 - A Digital FM Radio

This project demonstrates an FM radio using the radio component - RDA5807M and Speaker.

 

 

Component(s)

 

This project uses the following component(s) -

 

RDA5807M

56mm, 80hm 0.5W(RMS) / 1W(Peak) Internal CleO speaker

 

 

Wiring Diagram

 

 

Project 17-FM Radio

 

 

Code

 

The Setup() routine loads the speaker bitmap. It initializes the radio and sets the initial channel as well as volume.  Here is the sample code snippet -

 

void setup() {

 Serial.begin(115200);

 

/* Initialize CleO */

 CleO.begin();

 spk1 = CleO.LoadIcon("@Icons/m48.ftico", ICON_VOLUME_UP);

 CleO.DisplayRotate(2, 0);

 

// Initialize the Radio

 if (radio.init() == false)

   hardwarePresent = false;

 

// Enable information to the Serial port

 radio.debugEnable();

 

 volume = 5;

 channel = 897;

 

 if (hardwarePresent == true) {

// Set all radio setting to the fixed values.

   radio.setBandFrequency(FIX_BAND, channel * 10);

   radio.setVolume(volume);

   radio.setMono(false);

   radio.setMute(false);

 }

 inform("ready");

}

 

The loop() routine controls the flow by displaying all the drawing elements using the displayRadio() routine and then calling the control() command to handle the touch events. Here is the code snippet -

 

void loop() {

 displayRadio();

 control();

}

 

The display() routine first draws a set of strings to indicate frequency values and then a set of frequency lines in the for loop using the  Line()command. It uses the Needle() command to show the currently used frequencies. It uses tags to handle the touch events on volume line, next and previous strings.  Here is the sample code snippet that shows the usage of  the display() routine:

 

void displayRadio() {

 /* Start drawing the screen shot */

 CleO.Start();

 

 CleO.LineWidth(1);

 for (int f = 880; f < 1080; f += 20) {

   char buf[4];

   sprintf(buf, "%d", f / 10);

   CleO.StringExt(FONT_SANS_2, dial(f), 120, LIGHT_GREEN, MM, 0, 0, buf);

 }

 CleO.Tag(1);

 CleO.LineColor(DARK_GREEN);

 for (int f = 880; f < 1080; f += 2) {

   int major = (f % 10) == 0;

   CleO.LineWidth(major ? 1.2 : 0.8);

   CleO.Line(dial(f), 60, dial(f), 90 + 10 * major);

 }

 

 CleO.NeedleColor(DARK_RED);

 CleO.NeedleWidth(10);

 CleO.NeedleXY(dial(channel), 20, 60, 0);

 

 CleO.Tag(2);

 

/* Draw dark orange volume line with 3 thickness along with circle which will be used to touch and drag */

 CleO.LineWidth(4);

 CleO.LineColor(DARK_ORANGE);

 CleO.Line(300, 280, 440, 280);

 CleO.CircleExt(rescale(volume, 0, 15, 300, 440), 280, 0, 20, DARK_ORANGE, MM, 0, 0);

 

 CleO.Tag(3);

 CleO.StringExt(FONT_MEDIUM, 10, 150, WHITE, TL, 0, 0, "Previous");

 CleO.Tag(4);

 CleO.StringExt(FONT_MEDIUM, 445, 150, WHITE, TR, 0, 0, "Next");

 

 CleO.Tag(5);

 CleO.BitmapJustification(MM);

 CleO.Bitmap(spk1, 240, 280);

 

 /* Draw channel frequency using string */

 CleO.Tag(6);

 char buf[8];

 sprintf(buf, "%d.%d", channel / 10, channel % 10);

 CleO.StringExt(FONT_SANS_6, 10, 280, WHITE, ML, 0, 0, buf);

 

 if (hardwarePresent == false)

    CleO.StringExt(FONT_SANS_2, 10, SCREEN_WIDTH - 10, RED, BL, 0, 0, "No RDA5807M Detected");

 

  /* Show the screenshot */

 CleO.Show();

}

 

The control() routines checks for the touch action and if touch is detected on the needle (tag 1), then using the rescale()command, it gets new channel value. Similar action is taken for volume line touch (tag 2). The new channel is selected based on the previous or next string press using the tag 3 and 4. Here is the sample code snippet -

 

/* set selected channel, volume, seek up and down channels based on touch input */

void control() {

 int16_t x, y, dur, tag, newval;

 CleO.TouchCoordinates(x, y, dur, tag);

 if (tag == 1) {

   newval = int(rescale(x, 10, 480 - 10, 875, 1080));

   if (channel != newval) {

     channel = newval;

     if (hardwarePresent == true)

      radio.setBandFrequency(FIX_BAND, channel * 10);

   }

 }

 else if (tag == 2) {

   newval = int(rescale(x, 300, 440, 0, 15));

   if (volume != newval) {

     volume = newval;

     if (hardwarePresent == true) {

       radio.setVolume(volume);

     }

   }

 }

  else if (tag == 3 && hardwarePresent == true) {

   radio.seekDown(false);

   RADIO_FREQ f = radio.getFrequency();

   channel = f / 10;

 //    Serial.println(f);

   }

     else if (tag == 4 && hardwarePresent == true) {

   radio.seekUp(false);

   RADIO_FREQ f = radio.getFrequency();

   channel = f / 10;

 //    Serial.println(f);

 }

}

 

Note 1: The frequency range is adjusted based on the regional band (here, in this case, it is Singapore). Hence, the frequency range needs to be changed in the code based on the user's location.

 

Note 2: If no hardware is detected, then an appropriate error message is displayed.

 

 

Output

 

 

Project 17 - A Digital FM Radio