View previous topic :: View next topic |
Author |
Message |
cenar
Joined: 31 Jan 2012 Posts: 7
|
[solved] sensor broken, or i2c error? |
Posted: Tue Jan 29, 2013 10:19 am |
|
|
Hello,
I am using HMC5883L magnetometer sensor as slave, 16F876a as master.
I can read device registers OK, which means no problem on hardware. but when i try to read sensor data, it is always 255 (always 1). no reaction for data line. Do you think my sensor is broken?
Thanks in advance!
Code: | i2c_start();
i2c_write(0x3C);
i2c_write(0x02);
i2c_start();
i2c_write(0x3D);
data=i2c_read();
i2c_stop();
if(data=3) output_high(pin_b0); // b0 LED lights
.
.
.
i2c_start();
i2c_write(0x3C);
i2c_write(0x03);
i2c_start();
i2c_write(0x3D);
//data_x = i2c_read()<<8; //msb
//data_x |= i2c_read();
data_x1 = i2c_read();
data_x2 = i2c_read(); // x1 and x2 is 255
|
Last edited by cenar on Tue Jan 29, 2013 3:53 pm; edited 1 time in total |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Jan 29, 2013 10:37 am |
|
|
Read the datasheet for the HMC5883L carefully. Note on page 18 it says that you must read all six result registers before they will update. Also, you must use the DRDY (data ready) to tell you when to read the data.
Double check the set-up of the device to make sure its going to give you data when you need it, and to the right resolution.
Read the datasheet... then read it again.
RF Developer |
|
|
cenar
Joined: 31 Jan 2012 Posts: 7
|
|
Posted: Tue Jan 29, 2013 11:02 am |
|
|
Thank you for your advice. I did know that i should read 6 bytes, but i didn't put full code because i work a little bit dirty.
Here is my code, as datasheet advises. all uart datas are 255 (0b11111111), which is data line is always high, no response from sensor. i can read mode registers OK, but not sensor datas.
So question arises, is my sensor broken?
Code: |
i2c_start();
i2c_write(0x3C);
i2c_write(0x02);
i2c_start();
i2c_write(0x3D);
data=i2c_read();
i2c_stop();
if(data=3) output_high(pin_b0); //LED lights! i2c is okay
i2c_start();
i2c_write(0x3C);
i2c_write(0x00);
i2c_write(0x70);
i2c_stop();
i2c_start();
i2c_write(0x3C);
i2c_write(0x01);
i2c_write(0xA0);
i2c_stop();
while(1) {
i2c_start();
i2c_write(0x3C);
i2c_write(0x02);
i2c_write(0x01);
i2c_stop();
delay_ms(55); //measurement time
i2c_start();
i2c_write(0x3D);
i2c_write(0x06);
data_x1= i2c_read();
data_x2= i2c_read();
data_z1= i2c_read();
data_z2= i2c_read();
data_y1= i2c_read();
data_y2= i2c_read();
i2c_stop();
delay_ms(200);
printf("%u I %u I %u I %u O",data_x1,data_y1,data_z1,data_x2);
} |
|
|
|
cenar
Joined: 31 Jan 2012 Posts: 7
|
|
Posted: Tue Jan 29, 2013 11:06 am |
|
|
And this was my code. it is not well-written so i didn't want to put it here. but here it goes
Code: |
i2c_start();
i2c_write(0x3C);
i2c_write(0x02);
i2c_start();
i2c_write(0x3D);
data=i2c_read();
i2c_stop();
if(data=3) output_high(pin_b0);
delay_ms(100);
i2c_start();
i2c_write(0x3C);
i2c_write(0x02);
i2c_write(0x00);
i2c_stop();
delay_ms(1000);
while(1) {
i2c_start();
i2c_write(0x3C);
i2c_write(0x03);
i2c_start();
i2c_write(0x3D);
//data_x = i2c_read()<<8; //msb
//data_x |= i2c_read();
data_x1 = i2c_read();
data_x2 = i2c_read();
data_z = i2c_read()<<8; //msb
data_z |= i2c_read();
data_y = i2c_read()<<8; //msb
data_y |= i2c_read();
i2c_stop();
delay_ms(100);
//printf("%Ld",data_x);
printf("%u",data_x1);
printf("%u",data_x2);
putc('I');
//printf("%Ld",data_y);
//printf("%Ld",data_z);
delay_ms(10);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 29, 2013 2:09 pm |
|
|
1. The HMC5883L runs at +3.3v, but your PIC runs at +5v. Therefore,
you need to put the i2c bus on PortB (because it has TTL input levels).
Use any two pins from B0 to B5 for SDA and SCL. You should use 3.3K
(max) pull-up resistors on SDA and SCL, and the pull-ups should
connect to +3.3v.
Note: I'm assuming that the VDDIO pin on the HMC5883L is connected to
the VDD pin on the same chip, and that the VDD is +3.3v.
2. This is a newbie mistake:
Quote: | if(data=3) output_high(pin_b0); |
Look up the difference between = and == in the C language.
3. This code doesn't have the required NACK on the final i2c read:
Quote: |
data_x1 = i2c_read();
data_x2 = i2c_read();
data_z = i2c_read()<<8; //msb
data_z |= i2c_read();
data_y = i2c_read()<<8; //msb
data_y |= i2c_read();
i2c_stop(); |
Change it to this:
Code: | data_y |= i2c_read(0); // The 0 tells compiler to do a NACK
|
The same problem is in this block:
Quote: |
i2c_start();
i2c_write(0x3C);
i2c_write(0x02);
i2c_start();
i2c_write(0x3D);
data=i2c_read();
i2c_stop(); |
If you bought an HMC5883L board (for example, from Sparkfun.com),
then post a link to the webpage for it. |
|
|
cenar
Joined: 31 Jan 2012 Posts: 7
|
|
Posted: Tue Jan 29, 2013 3:52 pm |
|
|
Thank you for your detailed info!
1. I am giving 3.0v to the magnetometer and level shifting with 2 bs108 mosfets. It works ok.
2. Yes! this newb mistake made me believe my i2c line works. I am new to i2c and don't know about NACK. Thanks for this too, I will look into that.
But my mistake is even better.
My circuit is working at first place. So i used the uart tool of pickit and separated the voltage supplies of magnetometer and pic. data=3 mistake made me believe in my i2c line is still working. But both grounds were not connected Connected the grounds together and everything is operational. Thanks for the all support, you guys are the best. |
|
|
|