RDA5807SP FM Radio Receiver - i2C

I am so totally banging my head against the wall on this. I've learned quite a bit (I think) from the comments thus far, I think I get the jist of what is supposed to be happening here..... but its not happening that way.

For example:
I'm structuring two bytes

byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000

I send them

Wire.beginTransmission(device_address);
Wire.write(5);
Wire.write(val_hi); // hi byte 
Wire.write(val_lo); // lo byte  
Wire.endTransmission();

And when I read them back

void getVolume(){
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();

while (Wire.available() < 2);
  
byte byte1 = Wire.read();
byte byte2 = Wire.read();

// 10001000 10101111


Serial.print("The currnet volume setting is: ");
Serial.print(byte1, BIN);
Serial.print(":");
Serial.println(byte2, BIN);

I get this

The currnet volume setting is: 1110:11100000 (Leading zeroes supressed, I assume).

So WTF. I set a value, I read it, and I get something totally different back.

Complete current code for reference... Some garbage still in there of course

#include <Wire.h>

int device_address = 96;
int seekPin = 12;
int seekPinState = 0;

void setup(){
pinMode (seekPin,INPUT);  
  
Wire.begin();
Serial.begin(9600);

getVolume();
maxVolume();
getVolume();


}


void loop(){

Serial.print("Device addres is: ");
Serial.println(device_address);

seekPinState = digitalRead(seekPin);

if (seekPinState == 1) {
  Serial.println("High!");

  }

getVolume();
delay(5000);

}


void maxVolume(){
Serial.println("Setting Volume");
Wire.beginTransmission(device_address);
Wire.write(5);
byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000
Wire.write(val_hi); // hi byte 
Wire.write(val_lo); // lo byte  
Wire.endTransmission();

}

void getVolume(){
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();

while (Wire.available() < 2);
  
byte byte1 = Wire.read();
byte byte2 = Wire.read();

// 10001000 10101111


Serial.print("The currnet volume setting is: ");
Serial.print(byte1, BIN);
Serial.print(":");
Serial.println(byte2, BIN);
}

So WTF. I set a value, I read it, and I get something totally different back.

What do you get back?


Did you run the port scanner?


Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();

while (Wire.available() < 2);

That Wire.available() line is still there.


Wire.endTransmission() returns zero on a good send. If you don't get that, you may as well stop right there.

Wire.beginTransmission(device_address);
Wire.write(5);
if (Wire.endTransmission() != 0)
  {
  // error message
  return;
  }

Wire.requestFrom returns the number of bytes it got. If you don't get 2 you may as well stop. As I said before.

if (Wire.requestFrom(device_address, 2) != 2)
  {
  // error message
  return;
  }

Tell you what. You implement my earlier suggestions, like the scanner, testing for the number of bytes returned, etc. Then we can talk.

Running the scanner produces the following ( I used a similar script when I was getting started, thats how I was able to get the device address to begin with...... I have no idea why 3 devices are showing up, this is a single device).

I2C scanner. Scanning ...
Found address: 16 (0x10)
Found address: 17 (0x11)
Found address: 96 (0x60)
Done.
Found 3 device(s).

As far as the while loop goes - I haven't noticed anything 'breaking' regardless of how that was set, so I haven't really focused there yet.

As far as the values go.... I try and set this

byte val_hi = 0x88; // 10001000
byte val_lo = 0xA8; // 10101000

but I get this back

The currnet volume setting is: 1110:11100000 (Leading zeroes supressed, I assume).

So sent vs rcvd

TX - 1000100010101000
RX - 0000111011100000

Somehow I missed your error handling comments from before - I'm going to try those now, they look useful.

I also added in the error handling stuff - I'm not getting errors either way, so I believe that we're getting a return of 0 indicating success, and I also believe we're getting 2 bytes back, as we should.

Something you said earlier has me a bit confused

After staring at it for a while I think they are saying that the device address is in fact the register. So, for example, say we want to set some bits in register 2:

Yes there are multiple registers. of Primary interest to me is Register 2, 3,4,5,10, and 11. But I believe it's using a standard i2c style address (we see 3 devices in a bus scan).

OK, well see this:

http://forums.parallax.com/showthread.php?131976-FM-Receiver-Module-documentation

Try address 0x10 and failing that 0x11.

When I try 16 (0x10) I get 00000001 00111111. I get the same result after a 'set'
When I try 17 (0x11) I get 11111111 11111111. I get the same result after a 'set'.

This is what clued me in initially that I should use the third address.

So I've clearly picked an oddball piece of hardware, ehh? :slight_smile: lol

What I wish I could do is really 'see' the bitstream as I run the routine. See what crosses the bus, and see what comes back. I guess I just don't trust it until I prove it. But that's just me ranting about not believing what I'm seeing :slight_smile:

The return of all ones suggests no response to me. Are you testing the return codes?

I would be tempted to do a "read" of all possible 256 registers. After all that shouldn't hurt them, and you would find which ones seem to have reasonable data in them.

Yep I added some serial debug to tell me if things fail...Take a look, maybe my error handling has an error :slight_smile:

Current state of code:

#include <Wire.h>

int device_address = 17;
int seekPin = 12;
int seekPinState = 0;

void setup(){
pinMode (seekPin,INPUT);  
  
Wire.begin();
Serial.begin(9600);

getVolume();
maxVolume();
getVolume();


}


void loop(){

Serial.print("Device addres is: ");
Serial.println(device_address);

seekPinState = digitalRead(seekPin);

if (seekPinState == 1) {
  Serial.println("High!");

  }

getVolume();
delay(5000);

}


void maxVolume(){
Serial.println("Setting Volume");
Wire.beginTransmission(device_address);
Wire.write(5);
byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000
Wire.write(val_hi); // hi byte 
Wire.write(val_lo); // lo byte  
Wire.endTransmission();
if (Wire.endTransmission() != 0)
  {
  Serial.println("Error on TX"); // error message
  return;
  }
}

void getVolume(){
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();
if (Wire.requestFrom(device_address, 2) != 2)
  {
  Serial.println("Error in RX"); //error message
  return;
  }
  
byte byte1 = Wire.read();
byte byte2 = Wire.read();

Serial.print("The currnet volume setting is: ");
Serial.print(byte1, BIN);
Serial.print(":");
Serial.println(byte2, BIN);
}
Wire.endTransmission();
if (Wire.endTransmission() != 0)

?

No, just the one endTransmission. Get rid of the first one.

Yes it is an odd ball chip alright.
Here is a useful snippet

When reading use an address byte. When writing do not use an address byte.

This is from:- http://forums.parallax.com/showthread.php?131976-FM-Receiver-Module-documentation

Also

When in write transfer, data bytes is written out from MCU, and when in read transfer, data bytes is read out from RDA5807SS. There is no visible register address in I2C interface transfers.

For read transfer,
after command byte from MCU, RDA5807SS sends out the first register high byte, then the first register low byte, then the second register high byte, till receives NACK from MCU. MCU gives out ACK for data bytes besides last data byte. MCU gives out NACK for last data byte, and then RDA5807SS will return the bus to MCU, and MCU will give out STOP condition. The RDA5807SS supported two type I2C interface:RDA5807SS Mode and TEA5767 Mode. The different register defined in different interface Mode. Details refer to RDA5807SS Programming Guide.

From:-
http://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDYQFjAA&url=http%3A%2F%2Fwww.thebackshed.com%2Fforum%2Fuploads%2Fjman%2F2012-03-01_165913_RDA5807SS_datasheet_v1.0.pdf&ei=TwmeT9H0OsTL0QXsv_SGDw&usg=AFQjCNEqEDFHkiZATCakxMKhydZ4MHNVfA&sig2=MkxoY3MabKsvyTu_niEuTA

I see what you're referencing.... but I'm not sure I understand how to implement it. How does it know what register I'm trying to write to if I don't specify the address?

When reading use an address byte. When writing do not use an address byte.

The following snip-it works:
'========================[Write/Read data to/from FM module ]=====================
Write_ConfigRegs: ' Write Data to Configure Registers
I2COUT SDA, WrFM, [Conf2.Highbyte, Conf2.Lowbyte, Conf3.Highbyte, Conf3.Lowbyte, Conf4.Highbyte, Conf4.Lowbyte, Conf5.Highbyte, Conf5.Lowbyte, Conf6.Highbyte, Conf6.Lowbyte]
RETURN

Read_Status:
I2CIN SDA, RdFM, 0, [Status1,Status2,status3,status4]
DEBUG CRSRXY,10,1,"Status : ", HEX2 status1, " ", HEX2 status2, " ", HEX2 status3, " ", HEX2 status4, " "
RETURN
'================================================= =========================

I am not sure, it seems to imply it starts at zero and successive pairs of bytes go in the next register up.

Hello friends! I am also interested in this chip, tell me and how to record the frequency of the chip? thanks