SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By keithpoplar
#82083
Dear all, I am having some troubles to get data output from HMC5843. I have work with this problem for really a long time but still can't figure out why. Can anybody give me some help? Thanks a lot.

I am using dsPIC33FJ32GP302 MCU from microchip and HMC5843 evaluation board in single power supply mode. The code for I2C part is tested OK as I can read /write data from/to external EEPROM using I2C interface. So I believe the way I config/read HMC5843 is wrong.

Here is the code for initialize the device:

The problem for this part is that I always receive NAK from HMC. Obviously, HMC does not recognize what I send.
Code: Select all
int8u init_hmc(){
	int8u err;
	init_i2c();
	i2c_idle();
	i2c_start();
	i2c_write(HMC_WADDR);//write addr of HMC5843
	i2c_idle();
	
	err=ACKStatus();
	
	i2c_write(0x02);
	i2c_idle();
	i2c_write(0x00);
	i2c_idle();
	
	err=ACKStatus();
	i2c_stop();
	//set register pointer to data output register
	return err;
}
After the above code, reading function is immediately called. But what I get from device is all 0xff.
Code: Select all
void get_hmc_data(int16u *x,int16u *y,int16u *z){
	int8u xhb,xlb,yhb,ylb,zhb,zlb,err;
	i2c_idle();
	i2c_write(HMC_RADDR);	//read address
	i2c_idle();

		xhb=i2c_read();
		i2c_ack();
		xlb=i2c_read();
		i2c_ack();
		yhb=i2c_read();
		i2c_ack();
		ylb=i2c_read();
		i2c_ack();
		zhb=i2c_read();
		i2c_ack();
		zlb=i2c_read();
		i2c_ack();			
		*x=xhb*0x100+xlb;
		*y=yhb*0x100+ylb;
		*z=zhb*0x100+zlb;
	i2c_stop();
}
Last edited by keithpoplar on Thu Oct 08, 2009 3:01 am, edited 1 time in total.
By busonerd
#82185
I don't know if this applies to the HMC5843, but on their other compass chips, the compass will clock-stretch. Try adding a delay between the command and readback, if you're not sure if your i2c implementation is handling clock-stretching.

--David Carne
By Laurent D.
#82439
Hello,

I'm also trying to connect an HMC5843 to a pic 18F14K50 and have some difficulties with I2C protocol.
I use the 18F14k50 at 48MHz, 100kHz for I2C.
Here is my code:
To set up the config (call only one time at start):
Code: Select all
	IdleI2C();
	StartI2C();
	while ( SSPCON2bits.SEN );    // attente start condition is over 
	WriteI2C(0x3C);	// sélection capteur mode écriture
	IdleI2C();
	WriteI2C(0);	// adresse registre A
	IdleI2C();
	WriteI2C(24);	// registre A => frequence 50 Hz
	IdleI2C();
	WriteI2C(32);	// registre B => gain 1300
	IdleI2C();
	WriteI2C(0);	// registre mode => mode continu
	IdleI2C();
  	StopI2C();                      // send STOP condition
  	while ( SSPCON2bits.PEN );      // wait until stop condition is over 
Then the call to read datas:
Code: Select all
	IdleI2C();
	StartI2C();
	while ( SSPCON2bits.SEN );    // attente start condition is over (I2CCONbits.SEN ); 
	WriteI2C(0x3C);	// sélection capteur mode ecriture
	IdleI2C();    
	WriteI2C(0x03);	// sélection registre 3
	IdleI2C();
	StopI2C();
 	while ( SSPCON2bits.PEN );      // wait until stop condition is over 
	IdleI2C();
	StartI2C();
	while ( SSPCON2bits.SEN );    // attente start condition is over (I2CCONbits.SEN ); 
	WriteI2C(0x3D);	// sélection capteur mode lecture
	IdleI2C();   
	lowX=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle	
	highX=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	lowY=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	highY=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	lowZ=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	highZ=ReadI2C();
	NotAckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until NOACK sequence is over 
  	StopI2C();                      // send STOP condition
 	while ( SSPCON2bits.PEN );      // wait until stop condition is over 
I have some eratic data with the read operations.
And it seems the sensor does'nt take into account the config setup, although it gave good 'ack' response after writing operations.

Did you succeed with your code ? Can you post it, in order to have a good example of what is working.

Regards,
By keithpoplar
#82584
I can't even get a positive ACK from HMC5843. I have worked with this for a very long time, but still haven't figure out the reason.
Laurent D. wrote:Hello,

I'm also trying to connect an HMC5843 to a pic 18F14K50 and have some difficulties with I2C protocol.
I use the 18F14k50 at 48MHz, 100kHz for I2C.
Here is my code:
To set up the config (call only one time at start):
Code: Select all
	IdleI2C();
	StartI2C();
	while ( SSPCON2bits.SEN );    // attente start condition is over 
	WriteI2C(0x3C);	// sélection capteur mode écriture
	IdleI2C();
	WriteI2C(0);	// adresse registre A
	IdleI2C();
	WriteI2C(24);	// registre A => frequence 50 Hz
	IdleI2C();
	WriteI2C(32);	// registre B => gain 1300
	IdleI2C();
	WriteI2C(0);	// registre mode => mode continu
	IdleI2C();
  	StopI2C();                      // send STOP condition
  	while ( SSPCON2bits.PEN );      // wait until stop condition is over 
Then the call to read datas:
Code: Select all
	IdleI2C();
	StartI2C();
	while ( SSPCON2bits.SEN );    // attente start condition is over (I2CCONbits.SEN ); 
	WriteI2C(0x3C);	// sélection capteur mode ecriture
	IdleI2C();    
	WriteI2C(0x03);	// sélection registre 3
	IdleI2C();
	StopI2C();
 	while ( SSPCON2bits.PEN );      // wait until stop condition is over 
	IdleI2C();
	StartI2C();
	while ( SSPCON2bits.SEN );    // attente start condition is over (I2CCONbits.SEN ); 
	WriteI2C(0x3D);	// sélection capteur mode lecture
	IdleI2C();   
	lowX=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle	
	highX=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	lowY=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	highY=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	lowZ=ReadI2C();
	AckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until ACK sequence is over 
	IdleI2C();      // ensure module is idle
	highZ=ReadI2C();
	NotAckI2C();
	while ( SSPCON2bits.ACKEN );    // wait until NOACK sequence is over 
  	StopI2C();                      // send STOP condition
 	while ( SSPCON2bits.PEN );      // wait until stop condition is over 
I have some eratic data with the read operations.
And it seems the sensor does'nt take into account the config setup, although it gave good 'ack' response after writing operations.

Did you succeed with your code ? Can you post it, in order to have a good example of what is working.

Regards,
By Laurent D.
#82587
Hi,

I have found yesterday evening my problem !
It is simply due to the capacitor value of C1. The datasheet specify a minimum of 4.7 uF, I used first a 10uF.
It appears that during measurment of magnetic force, there is a high current need by the sensor, and this value of capacitor wasn't sufficient: there was a very short drop (2 us) in sensor supply voltage, producing a reset of the logic stage of the sensor.
With a 100uF, the problem disapear and now all is working perfectly !
Check this on your side...
By keithpoplar
#82592
This is definitely an important finding. Thanks for your clue. I hope this also works for me :)
Laurent D. wrote:Hi,

I have found yesterday evening my problem !
It is simply due to the capacitor value of C1. The datasheet specify a minimum of 4.7 uF, I used first a 10uF.
It appears that during measurment of magnetic force, there is a high current need by the sensor, and this value of capacitor wasn't sufficient: there was a very short drop (2 us) in sensor supply voltage, producing a reset of the logic stage of the sensor.
With a 100uF, the problem disapear and now all is working perfectly !
Check this on your side...
By UhClem
#82624
Laurent D. wrote:Hi,
I have found yesterday evening my problem !
It is simply due to the capacitor value of C1. The datasheet specify a minimum of 4.7 uF, I used first a 10uF.
The problem is more likely that the capacitor you used has too high of an ESR. While the data sheet warns you to use a low ESR capacitor, it fails to quantify what it means by low. It also fails to say what the resistance of the set/reset strap is so that you could calculate the maximum ESR.


But the root cause is the decision to connect the digital supply in single supply mode to C1 which has its charge current limited.
By MichaelN
#82625
I agree with David about ESR being the problem.

For this reason, as well as the fact that electrolytics tend to dry out over time, I almost never use them in my projects these days (for values less than 10's of uF anyway).
By Laurent D.
#82673
You'r right with the ESR, but as said, no value was proposed.
My first try was with a 10uF ceramic=>doesn't work
Second test ok with 100uF electrolitic
By MichaelN
#82674
That's curious - a 10uF ceramic cap should have a MUCH lower ESR than a 100uF electrolytic...
By keithpoplar
#82675
After replacing C1 with larger capacitor. I encounter different problem. Previously I can't receive ACK from HMC5843. Now I can.

But I can't receive data from the compass for more than once. I am testing this by reading internal ID register A. Only the first read returns me the correct ID 0x48. All subsequent reading can't receive any data.

However, if I reset the device (turn of power and turn on again), I can read it again (only the first read is OK).

What a weird problem!
By Laurent D.
#82842
Theorically, you should send a NotAck after the last reading, before the stop condition. This is theory of I2C, don't know if it is really usefull in this case but you can try.
By lehmanna
#82843
AFAICT from my own experience with the HMC6343, _that_ thing is very sensitive with respect to the final NACK.
By keithpoplar
#82924
Hi, what do I expect to receive after I send the writing/reading address to HMC5843?
ACK or NACK?
Sometimes, I always get NACK reply from HMC5843. In this case, I always read 0xFF from compass IC.
By lehmanna
#82938
You'll want to receive an SLA_ACK upon sending the HMC's I2C address.

Or do you mean the address of one of the HMC's registers?