Wednesday, 30 July 2014

TEA5767 FM Radio Receiver with Arduino and LM386 Amplifier Part 2


I spent the week playing around with how the radio was working, I wasn't horribly impressed with how it was working after my last post. I think I've pretty much nailed it for what I want to do, I even fixed a few kinks. I do strongly recommend you check out the post behind this one to see links to where software and design material came from. I also mentioned that the way I mounted the TEA5767 was similar to what another individual did, and here is a link to his blog: http://www.doctormonk.com/2012/03/tea5767-fm-radio-breakout-board-for.html

I've also noticed that this posting has been receiving a lot of attention, and I decided it may not provide enough information for someone trying to replicate it, so I made a quick and dirty paintbrush schematic:
For both pots I used a single turn 10K potentiometer.  You should also tie up the SDA and SCL lines up to 5V with a 4.7K resistor - this module seems to work just fine without it.
I understand the schematic isn't great and should be a CAD drawing, but it's simple enough. I'd urge you to dig up the data sheet for the LM386 to look at the different configurations. Hopefully this schematic will make this post more useful! This is a component of a larger project I'm working on, so hopefully at some point I will have it drawn properly in its entirety.

Because of how mine is done, this will be a daughter board soldered onto a main perf. board.

I'll make a programming note here:
You can see in the picture that I soldered onto the middle pin on the right side of the chip, which is suppose to be LEFT CHANNEL. If you decide you want to mute the RIGHT CHANNEL by adjusting the 3rd byte, they are backwards - you will end up muting the wrong one!! I'm not sure if  the issue is that you're turning off the wrong channel, or if the pins are flipped - if you're running stereo, this could mean you have LEFT AND RIGHT backwards. If you're running mono, like I am here, it won't matter - but I feel this is a fairly large ooops in a data sheet.

One thing I really didn't like about how my first attempt worked was that tuning with a 270 degree potentiometer was horrible. It just doesn't have enough resolution - if you actually tuned the channel you wanted, it would weave in and out of it, making it pretty intolerable. The solution I came up with (and this is really because I wanted to keep the number of knobs and buttons to a minimum) was to use the ADC to use different areas of the knob to achieve different results.

To the left you can see the scheme I used to control the tuning. It was a little weird at first, but I seem to have gotten the hang of it. If the knob is pointed up, nothing happens. Turn it a little to the left and it decreases by 100KHz, Turn it further, it decreases by 1MHz. It's buffered by a 300ms delay, which you could tweak to your tastes. I'm not in love with it, but it seems to work well for using the materials I have and getting it to tune in a satisfactory way. I will likely use the same method for setting the time on the clock portion of this project.

Here is what some of  you may have been skimming for, the code:

#include <Wire.h>

unsigned char frequencyH;
unsigned char frequencyL;

unsigned int frequencyB;
double frequency;
double tunerFrequency;

void setup()
{
  Wire.begin();
  frequency = 95.9; //A fancier approach would be to store this in EEPROM and retrieve last channel ;)
  Serial.begin(9600);
  setFrequency();
}

void loop()
{
  int reading = analogRead(0);
  //Serial.println(reading); //Shows the adc position - setting it to 512 will point "up" so you can attach a knob
  if (reading <= 410 || reading >= 614) checkTuner(); //only check tuning if tuning knob leaves rest area
}

void checkTuner()
{
  int currentReading = analogRead(0);
  if (currentReading <= 205) frequency = frequency--; //Tune back by 1MHz
  else if (currentReading >= 206 && currentReading <= 410) frequency = frequency - 0.1; //Tune back decimal
  else if (currentReading >= 614 && currentReading <= 819) frequency = frequency + 0.1; //Tune forward decimal
  else if (currentReading >= 820) frequency = frequency ++; //Tune forward by 1MHz
  else frequency = frequency; //If something unexpected happens, this will buffer it out
  if (frequency < 88.0) frequency = 88.0; //make sure it doesn't tune too low *Band limits can be adjusted
  if (frequency > 108.0) frequency = 108.0; //make sure it doesn't tune too high
  delay(300);// this delay will only occur if the main loop makes it into this function
  Serial.println(frequency);//only prints frequency while being tuned
  setFrequency();
}

void setFrequency()
{
  tunerFrequency = ((int)(frequency * 10)) / 10.0; //fun use of a cast!
  frequencyB = 4 * (tunerFrequency * 1000000 + 225000) / 32768;
  frequencyH = frequencyB >> 8;
  frequencyL = frequencyB;
  Wire.beginTransmission(0x60);
  Wire.write(frequencyH);
  Wire.write(frequencyL);
  Wire.write(0x1A);//0001 1010 -highside injection, forced mono, "right channel" muted, *PINOUT AND 3RD BYTE HAVE CHANNELS SWAPPED
  Wire.write(0x10);//Set for US and Europe band
  Wire.write(0x00);
  Wire.endTransmission();
}


I won't take credit for this in its entirety, between the link I posted above and a blog mentioned in the previous post, is where some of the work came from. You will want to open the serial monitor window in your Arduino IDE to see the frequency. I implemented my tuning method in the checkTuner function. I also tweeked out the setFrequency function, it seems to have fixed an issue I was having with the tuning drifting by 0.1MHz (I don't know why). I also changed that it only sends a message out to the I2C bus only after a change is requested by the checkTuner function - I was getting a ticking sound from it constantly communicating ~200ms. So I have it tuning better and less clicking. I also adjusted some of the data bytes to better reflect my needs. I found a detailed data sheet here:
http://www.voti.nl/docs/TEA5767.pdf 

The one last issue I had was trying to get it to scan for channels. I never got it to work properly, if you have it sorted out, let me know! 

So yeah, check out the video for the demonstration, and stay tuned to see where this project ends up. I hope this helped if you were looking for guidance!

If you want to see this project with a real time clockadded to it, check out a more recent blog which uses the DS3231 RTC combined with the project you just read about here: Arduino + DS3231 Real Time Clock

No comments:

Post a Comment