Talking to a Philips FM1216 tuner module

Hi there,

I am new to all this stuff and as my first real Arduino application i would like to use the FM part of a Philips FM1216 tuner module as a standalone FM radio receiver.

But Murphy's laws kind of prevent me from succeeding. I just can't get that damn thing to work...

First question: Why does my sketch only output 3 Bytes of data? (I can see 3 bursts on the SCL-Line with my DSO)
Here's a screenshot. http://gallery.kabelbrand.at/2012-07/i2cduorsch.jpg

Second question: Do I really need external pullup-resistors? I don't wanna read anything from the bus and the Arduino already pulls them to +5V.

Here's my sketch:

#include <Wire.h>

byte address = 0xC2;
byte address_IF = 0x86;
byte altvvals[] = {address, 0xC0, 0x1F, 0xE2, 0x86, 0x44, 0xA0};
byte fmmode[] = {address_IF, 0x00, 0x4E, 0xD0, 0x77};
byte tune[] = {address, 0x07, 0xC2, 0x88, 0x59, 0xB0};

void setup()
{
Wire.begin();
//avoiding locked tuning voltage
Wire.beginTransmission(altvvals[0]);
for(int i = 1; i < 7; i++)
{
Wire.write(altvvals*);*
}
Wire.endTransmission();

//setting FM mode, high sensitivity
Wire.beginTransmission(fmmode[0]);
for(int j = 1; j < 5; j++)
{

  • Wire.write(fmmode[j]);*
    }
    Wire.endTransmission();

//setting it to 88,6 MHz
Wire.beginTransmission(tune[0]);
for(int k = 1; k < 6; k++)
{

  • Wire.write(tune[k]);*
    }
    Wire.endTransmission();
    }
    void loop()
    {

}
[/quote]
Thanks in advance!

Link to the philips data sheet?
Likely stops because slave is not sending back acknowledge bit.
Can you post the SDA line?

This is the Datasheet: http://pvr.sourceforge.net/FM1216.pdf

And this is what the SDA-Line looks like: http://gallery.kabelbrand.at/2012-07/fm1216-sda.jpg

I left pin 6 floating, so the tuner should have the address 0xC2.

Well this is weird...

I just tried the I2C-Scanner sketch from here and it showed me some different adresses. After changing the base address to 0xC3 it now seems that there is some communicating going on. Although i don't hear any audio... But that's a different story :slight_smile:

This scetch works fine with FM1216:

#include <Wire.h>

byte i2c_adr_zf = 0x43; // I2C-Adresse Zwischenfrequenz
byte i2c_adr_fb = 0x60; // I2C-Adresse Frequenzband
byte stereo = 0x19;
byte mono = 0x59;
byte freq_high = 0x08; // see station list below
byte freq_low = 0x1e; // see station list below

// some radio-stations in germany - northrhinewestfalia

// WDR_1 = (105,5 + 10,7)*20 = 2324 = hex914 => high = 0x09 | low = 0x14
// WDR_2 = ( 93,2 + 10,7)*20 = 2078 = hex81E => high = 0x08 | low = 0x1E
// WDR_3 = ( 97,0 + 10,7)*20 = 2157 = hex86D => high = 0x08 | low = 0x6D
// WDR_4 = (100,5 + 10,7)*20 = 2224 = hex8B0 => high = 0x08 | low = 0xB0
// WDR_5 = ( 90,6 + 10,7)*20 = 2026 = hex7EA => high = 0x07 | low = 0xEA

void setup()
{

Wire.beginTransmission(i2c_adr_fb);

Wire.write(0xC0);
Wire.write(0x1F);
Wire.write(0xE2);
Wire.write(0x86);
Wire.write(0x44);
Wire.write(0xA0);
Wire.endTransmission();
delay(200);

// FM-mode
Wire.beginTransmission(i2c_adr_zf);
Wire.write(0x00);
Wire.write(0x4E); // 0x0E mute
Wire.write(0xD0);
Wire.write(0x77);
Wire.endTransmission();
delay(200);

Wire.beginTransmission(i2c_adr_fb);
Wire.write(freq_high); //
Wire.write(freq_low);
Wire.write(0x88);
Wire.write(mono);
Wire.write(0xB0);
Wire.endTransmission();
delay(200);
}

void loop()
{
}

I used source code from: Philips FM1216ME/I H-3 tuner example code - EmbDev.net

#include <Wire.h>

//0xC2 is default I2C addr when AS pin is NC
#define FM1216ME_I2C_ADDR		0xC3
#define TDA9887_I2C_ADDR		0x63

//divider bytes DB1&2:
#define FM1216ME_DIV_HIGH(f_in_10kHz)	(((f_in_10kHz)/5+214)>>8)
#define FM1216ME_DIV_LOW(f_in_10kHz)	(((f_in_10kHz)/5+214)&0xFF)

//control byte CB
#define FM1216ME_CHARGE_PUMP		0x40
#define FM1216ME_TUNE_50KHZ		0x00
#define FM1216ME_TUNE_31_25KHZ		0x02
#define FM1216ME_TUNE_166_7KHZ		0x04
#define FM1216ME_TUNE_62_5KHZ		0x06
#define FM1216ME_PLL_TUNING		0x01
#define FM1216ME_CB_BITS		0x88	//default, normal operation

//band switching byte BB:
#define FM1216ME_LOW_BAND		0x01
#define FM1216ME_MID_BAND		0x02
#define FM1216ME_HIGH_BAND		0x04
#define FM1216ME_FM_STEREO_BAND		0x19
#define FM1216ME_FM_MONO_BAND		0x59

//auxilliary byte AB:
#define FM1216ME_AGC_115dBuV		0x10
#define FM1216ME_AGC_112dBuV		0x20
#define FM1216ME_AGC_109dBuV		0x30
#define FM1216ME_AGC_106dBuV		0x40
#define FM1216ME_AGC_103dBuV		0x50
#define FM1216ME_AGC_EXT		0x60
#define FM1216ME_AGC_OFF		0x70
#define FM1216ME_ATC			0x80

//TDA9887 settings:
#define TDA9887_SAD			0x00	//standard slave register address
#define TDA9887_FM_MONO_B		0x0A
#define TDA9887_FM_MONO_C		0x30
#define TDA9887_FM_STEREO_C		0x90
#define TDA9887_FM_B			0x0A
#define TDA9887_AUDIO_MUTE_B		0x20
#define TDA9887_FM_HIGH_SENSITIVITY_B	0x40
#define TDA9887_FM_E			0x20

void fm1216me_radio_init(){
	Wire.begin();
        //Wire.beginTransmission(FM1216ME_I2C_ADDR);

	//FM1216ME bug? see datasheet page 20
	//set to high band, 150MHz before using FM radio!
	//i2c_start();
	Wire.write(FM1216ME_I2C_ADDR);
	Wire.write(FM1216ME_DIV_HIGH(15000));
	Wire.write(FM1216ME_DIV_LOW(15000));
	Wire.write(FM1216ME_CB_BITS);
	Wire.write(FM1216ME_HIGH_BAND);
	Wire.write(FM1216ME_AGC_109dBuV);
	Wire.endTransmission();

	Wire.begin();
	Wire.write(FM1216ME_I2C_ADDR);
	Wire.write(FM1216ME_DIV_HIGH(10080)); //100.80 MHz, WDR2 :-)
	Wire.write(FM1216ME_DIV_LOW(10080));
	Wire.write(FM1216ME_CB_BITS);
	Wire.write(FM1216ME_FM_STEREO_BAND);
	Wire.write(FM1216ME_AGC_103dBuV);
	Wire.endTransmission();

	Wire.begin();
	Wire.write(TDA9887_I2C_ADDR);
	Wire.write(TDA9887_SAD);
	Wire.write(TDA9887_FM_B);
	Wire.write(TDA9887_FM_STEREO_C | TDA9887_FM_HIGH_SENSITIVITY_B);
//	i2c_write(TDA9887_FM_STEREO_C);
	Wire.write(TDA9887_FM_E);
	Wire.endTransmission();
}

void fm1216me_radio_tune(int freq_in_10kHz){
	Wire.begin();
	Wire.write(FM1216ME_I2C_ADDR);
	Wire.write(FM1216ME_DIV_HIGH(freq_in_10kHz));
	Wire.write(FM1216ME_DIV_LOW(freq_in_10kHz));
	Wire.endTransmission();
}

unsigned char fm1216me_radio_status(){
	Wire.begin();
	Wire.write(FM1216ME_I2C_ADDR|0x1);
	Wire.read();
	Wire.endTransmission();
	Wire.begin();
	Wire.write(TDA9887_I2C_ADDR|0x1);
	Wire.read();
	Wire.endTransmission();
}


void setup()
{
 fm1216me_radio_init();
 fm1216me_radio_tune(9710);
 Serial.begin(9600);
}


void loop()
{ 
  
  Serial.println(fm1216me_radio_status());
  delay(10000);
}

In the I2C scanner sketch I see three adressess: 0x43, 0x61,0xC3 (is connected FM1216/I H-3 only).

I do not hear any sound(or noise). :frowning: :frowning: Can somebody help me please?

Lukas

I think there is a Problem with the I2C when you usw the Hardware I2C, so I used a Soft I2C. With it, it worked.
You could try my Library for FM1216:

Hope it helps you.

I just tried shpank's sketch with an address 0X60 (obtained with i2c scan) .communication succeeded.

But still there is too much unknown thing.

I can see tuning voltage raised up to 38 V at pin 11 and FM tuner hiss noise ended.

But i think you already pass these points and set your tuner as you want.

If you don't leave it please share your knowledge about it.

Also after a lot of attempts, i did not manage to control the FM1216 with using hard I2C. Compared to this, library offered by DH9JHB did work without problems.
Nevertheless i also wanted to make my own version ( also using soft IC ) where intension also was, covering the total tuner range from 40-868 Mhz:

// using library: GitHub - todbot/SoftI2CMaster: Software I2C / TWI library for Arduino allows any two pins to be SDA & SCL

// --------------------------------------
// SoftI2C_Library By Shervin Emami (http://shervinemami.info/)

#include "SoftI2CMaster.h"

const int sdaPin = A4;
const int sclPin = A5;
SoftI2CMaster i2c = SoftI2CMaster( sclPin, sdaPin, 0 );

// select receiving frequency 48.0-868.0 MHz ( 100 KHz spacing )
//float Frx = 864.5; // wireless headphone
//float Frx = 87.7; // regional FM station
float Frx = 98.7; // regional FM station

float factor = (Frx+10.7)*20;
int factor2 = factor;
byte hi = highByte(factor2);
byte lo = lowByte(factor2);
byte mode;

///////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
Serial.print("Frx: ");
Serial.print(Frx);
Serial.println(" MHz");

if(Frx<87.5) {mode=0x41; } // Low-Band
else
if(Frx>87.4&&Frx<108) {mode=0x19;} // FM-Stereo
//if(Frx>87.4&&Frx<108) {mode=0x59;} // FM-Mono
else
if(Frx>107.9&&Frx<160) {mode=0x41;} // Low-Band
else
if(Frx>160&&Frx<440) {mode=0x42;} // Mid-Band
else
if(Frx>440&&Frx<870) {mode=0x44;} // High-Band

//HiBand-Start
i2c.beginTransmission(0x60);
i2c.write(0x1F);
i2c.write(0xE2);
i2c.write(0x86);
i2c.write(0x44);
i2c.write(0xA0);
i2c.endTransmission(); // I2C-Stop
delay(200);

// FM-mode
i2c.beginTransmission(0x43);
i2c.write(0x00);
i2c.write(0x4E); // 0x0E mute
i2c.write(0xD0);
i2c.write(0x77);
i2c.endTransmission(); // I2C-Stop
delay(200);

// Frequency, Band aso.
i2c.beginTransmission(0x60);
i2c.write(hi); //
i2c.write(lo); //
i2c.write(0x88);
i2c.write(mode); //
i2c.write(0xA0);
i2c.endTransmission(); // I2C-Stop
delay(200);
}

/////////////////////////////////////////////////////////////////////////
void loop()
{
}

Additional remark regarding my previous posting and concerning I2C address:
Pin 6 of my FM1216 is grounded