|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 05, 2013 11:38 pm |
|
|
Here is a sample driver. I don't have a HMC5883L to test, so I can't
guarantee this code will work, but at least it has a chance to work.
I don't have the PCD compiler, but I do have PCH. That's why I did it for
the 18F4520. If you convert this code to PCD, remember that in PCD
most data types are signed by default, whereas in PCH they are unsigned
by default. Also, in PCD you use "%x" to display a 16-bit value, but
in PCH you use "%lx".
Code: |
#include <18F4520.h>
#fuses INTRC_IO, NOWDT, PUT, BROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, UART1, ERRORS)
// i2c slave addresses
#define HMC5883L_WRT_ADDR 0x3C
#define HMC5883L_READ_ADDR 0x3D
// Register addresses
#define HMC5883L_CFG_A_REG 0x00
#define HMC5883L_CFG_B_REG 0x01
#define HMC5883L_MODE_REG 0x02
#define HMC5883L_X_MSB_REG 0x03
//------------------------------
// Low level routines
//------------------------------
void hmc5883l_write_reg(int8 reg, int8 data)
{
i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(reg);
i2c_write(data);
i2c_stop();
}
//------------------------------
int8 hmc5883l_read_reg(int8 reg)
{
int8 retval;
i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(reg);
i2c_start();
i2c_write(HMC5883L_READ_ADDR);
retval = i2c_read(0);
i2c_stop();
return(retval);
}
//------------------------------
typedef struct
{
int16 x;
int16 y;
int16 z;
}hmc5883l_result;
// This global structure holds the values read
// from the HMC5883L x,y,z registers.
hmc5883l_result compass = {0,0,0};
//------------------------------
void hmc5883l_read_data(void)
{
int8 x_lsb;
int8 x_msb;
int8 y_lsb;
int8 y_msb;
int8 z_lsb;
int8 z_msb;
i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(HMC5883L_X_MSB_REG); // Point to X-msb register
i2c_start();
i2c_write(HMC5883L_READ_ADDR);
x_msb = i2c_read();
x_lsb = i2c_read();
y_msb = i2c_read();
y_lsb = i2c_read();
z_msb = i2c_read();
z_lsb = i2c_read(0); // do a NACK on last read
i2c_stop();
// Combine high and low bytes into 16-bit values.
compass.x = make16(x_msb, x_lsb);
compass.y = make16(y_msb, y_lsb);
compass.z = make16(z_msb, z_lsb);
}
//==========================================
void main()
{
delay_ms(500); // A power-on init delay may be needed
printf("\n\rStart:\n\r");
// Init the HMC5883L. Set Mode register for
// continuous measurements.
hmc5883l_write_reg(HMC5883L_CFG_A_REG, 0x70);
hmc5883l_write_reg(HMC5883L_CFG_B_REG, 0xA0);
hmc5883l_write_reg(HMC5883L_MODE_REG, 0x00);
// Continuously read and display the x,y,z results.
// Wait at least 67 ms between reads, re the HMC5883L data sheet.
while(1)
{
delay_ms(100);
hmc5883l_read_data();
printf("%lx, %lx, %lx \n\r", compass.x, compass.y, compass.z);
}
} |
|
|
|
Tom1234
Joined: 06 Jan 2013 Posts: 39
|
HMC5883L Help |
Posted: Sun Apr 07, 2013 6:02 pm |
|
|
Thanks PCM Programmer.
I test this code and is look like that is working. (I will further study and i will ask some things).
But firstly there is any way to check if the sensor is give me correct data??
and also why you write the function int8 hmc5883l_read_reg(int8 reg) (below) but you never use it !!!
Code: |
int8 hmc5883l_read_reg(int8 reg)
{
int8 retval;
i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(reg);
i2c_start();
i2c_write(HMC5883L_READ_ADDR);
retval = i2c_read(0);
i2c_stop();
return(retval);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 07, 2013 6:24 pm |
|
|
You might want to read the Status register or the Identification Registers
sometime. |
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Sat May 11, 2013 1:27 pm |
|
|
Question ::
When the x-axis in the sensor points to the North,
what should the output be ?
I Have changed the display type to be :
Code: |
fprintf(COM_LCD,"%Lu, %Lu, %Lu ", compass.x, compass.y, compass.z);
|
TO have integers
I want the value to be 0 at North, and 90 at East |
|
|
savotech
Joined: 13 Dec 2012 Posts: 12
|
|
Posted: Sun Jan 19, 2014 6:17 pm |
|
|
pcm programmer, please thanks for that code, its working very fine. i edited the printf code and make it display on lcd and i saw the the X Y and Z values are changing as i change direction.
Please help me, my challenge now is that i don't know how to interpret those values to get my real north, east, west, south stuff or interpret it to degrees stuff.
I read on net that arctan of Yvalue/Xvalue gives the angle but i tried that but i don't get a tangible result, and again, i don't know what to use the Zvalue for.
So please anybody that can help me modify pcm programmer code to give me the result in degrees, thanks in expectance of favourable reply |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sun Jan 19, 2014 6:40 pm |
|
|
The values are often raw magnetometer readings. If you understand geometry and trigonometry you have a chance of succeeding. I don't see you succeeding by asking questions of this forum it is not so far a forum that teaches mathematics. You might find some code for ardruino's. Multiwi is open source and there is c code you might be able to throw at the wall and have something useful stick. Then again without an understanding of the mathematics it will be difficult. As far as the Z axis it has a role since the x and y axis can rotate into the z axis as the platform pitches and rolls. The Earth's magnetic field has a declination that is dependent on latitude and longitude ...the field varies in 3 dimensions so X,Y and Z are needed unless the Z axis is always vertical and fixed as well as the lat and long. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
savotech
Joined: 13 Dec 2012 Posts: 12
|
|
Posted: Mon Jan 20, 2014 8:02 am |
|
|
Thank you all for replying me. I have really gained a lot here
I have successfully converted the the values to degree (sorry i can't paste the code, i am browsing the with my phone).
I have another challenge: i am not getting 0-360 degrees on the x-y axis, i.e. when i put the sensor on a plane table, and rotate, it wont give me a full range, its giving me a value between 21 and 150 degrees. But when i turn it through Z-axis, it gives me a full range.
When i rotate it on a table, it the angle displayed begins to decrease till 21 degrees and begins to increase till 150 degrees and then decreases again, until i rotate it through the zaxis. It gives a full range turning it like a circle going in 3D. What could be the problem, please help me sir. |
|
|
savotech
Joined: 13 Dec 2012 Posts: 12
|
|
Posted: Mon Jan 20, 2014 8:16 am |
|
|
Ooooh! I am sorry guys, i have seen my mistake, i misinterpreted the xyz diagram on the hmc5883l sensor, i laid it down flat instead of making it stand upright. Thats why the system is reading Zaxis variation instead of Yaxis.
I now have a full working digital compass, thanks to God and thanks to you all. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|