TEA5767 radio module on teensy?

Status
Not open for further replies.
Heya!

I just learned about these cool looking small FM radio modules: http://playground.arduino.cc/Main/TEA5767Radio

I was wondering whether that code library would work on a Teensy?

I've ordered some anyway (I can always just use an arduino), so I'm happy to test if no one has done so already. I'd like to make a USB MIDI controlled radio station sequencer, so if I can surmount the first obstacle of controlling the radio with a teensy then I'll post my progress here.

cheers,

yann
 
radio station sequencer -
does what?

I'm thinking about assigning each midi note value a radio frequency. that way I can program drum patterns in Max/MSP or Ableton or something and output them through USB MIDI to the Teensy/TEA5767, creating constantly shifting sequences that change along with the radio stations.

I could also just 'play' the stations using a midi keyboard, which would be fun!

So yeah, I'd like to use a Teensy for this, because it's so easy to turn it into a USB MIDI device.
 
T3 shop clock/radio

The TEA5767 works just fine with the Teensy3.x. Here is the complete program for a shop clock/radio that I developed using a Teensy 3.0. It uses a Nokia 5110 display and a mechanical encoder from SparkFun https://www.sparkfun.com/products/9117. The program is a patchwork of sloppy code stitched together with good intentions. It includes temperature compensation for the Teensy RTC and a tweaked patch of code for the encoder. Again, the code is a bit sloppy and disorganized but it is reliable and works very well. I have not put everything in an enclosure yet so it is laced together on a small section of my bench and has worked great for over a year now.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


#include <SPI.h>
#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <Time.h>

// These Adafruit(#338 blue board) Nokia 5110
// displays use SPI to communicate, 4 or 5 pins
// are required to interface.
// MCU pins -- Nokia pins
// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 3 - LCD chip select (CS)
// pin 4 - LCD reset (RST)
// init display
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 3, 4);

/*****************************************************************************************************/

boolean toggle = false;
int SDIO = A4;
int SCLK = A5;
int channel;
int volume;
int myhour;
int mutePin = 1;
char tempString[10];
float fchannel;

const int encoderPin21 = 21; // encoder pin 1
const int encoderPin22 = 22; // encoder pin 2

#define INT_Pin21 21 // interrupt on #21
#define INT_Pin22 22 // interrupt on #22

//Volatile variables are needed if used within interrupts
volatile int lastEncoded = 0;
volatile long encoderValue = 0;

volatile int goodEncoderValue;
volatile boolean updateStation = false;

const boolean UP = true;
const boolean DOWN = false;
volatile boolean stationDirection;

/*****************************************************************************************************/
byte frequencyH = 0;
byte frequencyL = 0;
unsigned int frequencyB;
double frequency = 0;
/*****************************************************************************************************/


/*****************************************************************************************************/
void setup()
{
//setTime(hr,min,sec,day,mnth,yr)
//use 24 hour time in the above
//format with midnight being 0 hours

//PROCEDURE: un-comment the two lines below and
// upload the program. Then re-comment
// the same lines and upload the program again.

//setTime(14,58,0,23,9,14);
//Teensy3Clock.set(now());

hourFormat12();

// set the Time library to use Teensy 3.0's RTC to keep time
setSyncProvider(getTeensy3Time);

display.begin();
analogWrite(9,25); // turn on and modulate display backlight
display.setContrast(60); // set contrast
display.clearDisplay(); // clears the screen and buffer


Wire.begin();

read_channel_from_EEPROM();
if(channel <= 875 || channel >= 1081)
{ channel = 981;}
setFrequency();

update_display();

analogReadRes(12);
analogReadAveraging(8);

pinMode(mutePin,INPUT_PULLUP); // to read encoder momentary push switch

// both pins on the rotary encoder are inputs and pulled high
pinMode(encoderPin21, INPUT_PULLUP);
pinMode(encoderPin22, INPUT_PULLUP);

//call updateEncoder() when any high/low changed seen
//on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(INT_Pin21, updateEncoder, CHANGE);
attachInterrupt(INT_Pin22, updateEncoder, CHANGE);

updateEncoder();
}
/*****************************************************************************************************/

/*****************************************************************************************************/
void loop()
{
// interrupt tells us when to update the station
if(updateStation)
{
if(stationDirection == UP) channel += 2;

else if(stationDirection == DOWN) channel -= 2;

//Catch wrap conditions
if(channel > 1079) channel = 875;
if(channel < 875) channel = 1079;

setFrequency(); //Goto the new channel
save_channel(); // save channel to EEPROM
update_display();

updateStation = false; //Clear flag
}
if(!digitalRead(mutePin))
{
delay(100);
if(!digitalRead(mutePin))
{
toggle = !toggle;
setFrequency();
update_display();
}
while(!digitalRead(mutePin));
delay(100);
}
if(millis() % 200 == 0)update_display();
}
/*****************************************************************************************************/


/*****************************************************************************************************/
void setFrequency()
{
frequency = (double)channel/10;
frequencyB = 4 * (frequency * 1000000 + 225000) / 32768;
frequencyH = frequencyB >> 8;
frequencyL = frequencyB & 0XFF;

Wire.beginTransmission(0x60);
Wire.write(frequencyH);
Wire.write(frequencyL);
Wire.write(0xB2); // bit 1 forces mono mode and mutes right channel
if(!toggle)Wire.write(0x10); // use 0x58 for mute
else Wire.write(0x58);
Wire.write((byte)0x00);
Wire.endTransmission();
}
/*****************************************************************************************************/


/*****************************************************************************************************/
void updateEncoder()
{
delayMicroseconds(500);
int MSB = digitalRead(encoderPin21); //MSB = most significant bit
int LSB = digitalRead(encoderPin22); //LSB = least significant bit

int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
{
stationDirection = DOWN; //Counter clock wise
encoderValue--;
}
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
{
stationDirection = UP; //Clock wise
encoderValue++;
}

lastEncoded = encoded; //store this value for next time

//Wait until we are more than 3 ticks from previous used value
if(abs(goodEncoderValue - encoderValue) > 3)
{
//The user can sometimes miss an indent by a count or two
//This logic tries to correct for that
//Remember, interrupts are happening in the background so encoderValue can change
//throughout this code

if(encoderValue % 4 == 0) //Then we are on a good indent
{
goodEncoderValue = encoderValue; //Remember this good setting
}
else if( abs(goodEncoderValue - encoderValue) == 3) //The encoder is one short
{
if(encoderValue < 0) goodEncoderValue = encoderValue - 1; //Remember this good setting
if(encoderValue > 0) goodEncoderValue = encoderValue + 1; //Remember this good setting
}
else if( abs(goodEncoderValue - encoderValue) == 5) //The encoder is one too long
{
if(encoderValue < 0) goodEncoderValue = encoderValue + 1; //Remember this good setting
if(encoderValue > 0) goodEncoderValue = encoderValue - 1; //Remember this good setting
}

updateStation = true;
}
}
/*****************************************************************************************************/


/*****************************************************************************************************/
time_t getTeensy3Time()
{
return Teensy3Clock.get();
}
/*****************************************************************************************************/


/*****************************************************************************************************/
void update_display(void)
{
// set up to read a LM335 temperature sensor with 12 bit resolution
// measured VCC was 3.279 volts so 1 count = .0008 volts. The LM335
// puts out 10 millivolts per deg. C. It is referenced to absolute
// zero so 0 degrees C will be 2.73 volts or 3412.5 counts. The next
// few lines convert the sensor output to degrees C.

float tmp_snsrC = analogRead(A9);
tmp_snsrC = (((tmp_snsrC - 3412.5) / 12.5) - 2.7);

//int tempcomp = abs((25.0 - (int)tmp_snsrC) / 2);
int tempcomp = abs(25.0 - (int)tmp_snsrC);

//Serial.println(tempcomp);

if(tempcomp >= 1) Teensy3Clock.compensate(tempcomp * -1);

// with Teensy3Clock.compensate(int), a positive number speeds the clock up
// and a negative number slows the clock down

fchannel = (float)channel/10;
sprintf(tempString, "%.1f", fchannel);
display.clearDisplay(); // clears the screen and buffer

display.setTextSize(2);
display.setTextColor(BLACK);
display.setCursor(0,1);

if(hour() <= 12 && hour() != 0) myhour = hour();
if(hour() >= 13) myhour = (hour() - 12);
if(hour() == 0) myhour = (hour() + 12);

if(myhour < 10)
{
display.print(" ");
display.print(myhour);
}

else display.print(myhour);
doDigits(minute());

if(isPM())display.print("PM");
else display.print("AM");

display.setTextSize(1);
display.print("--------------");
display.print(" RADIO CHANNEL");
//display.println(tmp_snsrC,1);

display.setTextSize(2);
display.setTextColor(BLACK);

if(toggle)
{
display.print(" MUTE");
display.display(); // sends buffer to display
}

else
{
if(channel < 1000) display.print(" ");
else display.print(" ");
display.println(tempString);
display.display(); // sends buffer to display
}
}
/*****************************************************************************************************/


/*****************************************************************************************************/
void save_channel()
{
int msb = channel >> 8; // move channel over 8 spots to grab MSB
int lsb = channel & 0x00FF; // clear the MSB, leaving only the LSB
EEPROM.write(1, msb); // write each byte to a single 8-bit position
EEPROM.write(2, lsb);
}
/*****************************************************************************************************/


/*****************************************************************************************************/
void read_channel_from_EEPROM()
{
int msb = EEPROM.read(1); // load the msb into one 8-bit register
int lsb = EEPROM.read(2); // load the lsb into one 8-bit register
msb = msb << 8; // shift the msb over 8 bits
channel = msb|lsb; // concatenate the lsb and msb
}
/*****************************************************************************************************/


/*****************************************************************************************************/
// utility function for digital clock display: prints preceding colon and leading 0
void doDigits(int digits)
{
display.print(":");
if(digits < 10)display.print('0');
display.print(digits);
}
/*****************************************************************************************************/
 
Last edited:
Thanks so much for the info and the code pxgator! I'm happy that it will work with my teensys. With any luck I'll start experimenting next week, I'll post any developments here.

Cheers!
 
Glad you find the info useful amazingrolo. I'm anxious to hear about your progress. I forgot to mention that I did build one of these for my father and put it in an enclosure. It uses the exact program above and it has also worked just fine for over a year now. He mounted it in his shop outside which has open doors and it survives a temperature variation of -20F TO +90F depending on the time of year.
 
I've finally gotten started on this project. I'm afraid I haven't yet managed to get a TEA5767 working with my Teensy 3.0.

I've tried to find the simplest code possible as a starting point, here's what I'm using:
#include <Wire.h>

unsigned char frequencyH = 0;
unsigned char frequencyL = 0;

unsigned int frequencyB;
double frequency = 0;
const int analogInPin = A0;
void setup()
{
Wire.begin();
frequency = 83.0; //starting frequency
setFrequency();
Serial.begin(9600);
}

void loop()
{
int reading = analogRead(analogInPin);
//frequency = map((float)reading, 0.0, 1024.0, 87.5, 108.0);

frequency = ((double)reading * (108.0 - 87.5)) / 1024.0 + 87.5;
frequency = ((int)(frequency * 10)) / 10.0;

setFrequency();
Serial.println(frequency);
}

void setFrequency()
{
frequencyB = 4 * (frequency * 1000000 + 225000) / 32768;
frequencyH = frequencyB >> 8;
frequencyL = frequencyB & 0XFF;
delay(100);
Wire.beginTransmission(0x60);
Wire.write(frequencyH);
Wire.write(frequencyL);
Wire.write(0xB0);
Wire.write(0x10);
Wire.write((byte)0x00);
Wire.endTransmission();
delay(100);
}


It works perfectly with an Arduino Uno, but with my Teensy 3.0 all I get is hiss. I'm pretty certain I'm wiring it correctly, using Analog5 as my SCL and Analog4 as my SDA. I also don't think it's a powering issue, because it works fine using the 3.3v power from the Arduino.

Anyone have ideas for what the problem could be?
 
Are you using pull up resistors on SCL and SDA ? I'm using 4.7K pull ups on my T3/TEA5767 setups.
 
Last edited:
Are you using pull up resistors on SCL and SDA ? I'm using 4.7K resistors on my T3/TEA5767 setup.



Hey, that seems to have done the trick!
I just put in a 10k ohm resistor between A4 and 3.3V and A5 and 3.3V and it started working right away.

Thanks a bunch for the help!
 
Status
Not open for further replies.
Back
Top