Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 18:40 15 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : HMC5883L magnetometer

     Page 1 of 3    
Author Message
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 11:50am 22 Jan 2016
Copy link to clipboard 
Print this post

Hi All,
I have ordered one of these modules, has any one done any work with this chip. I'm looking at making a compass.
Not sure if I will be able to get the calibration values from the chip, might need help with some code.
Paul.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 02:00pm 22 Jan 2016
Copy link to clipboard 
Print this post

It looks relatively easy to use. (Famous last words)

I just ordered a couple so give me a few weeks for them to arrive....
and hopefully by then, someone would have done the work.

Jim
VK7JH
MMedit
 
greybeard
Senior Member

Joined: 04/01/2010
Location: Australia
Posts: 172
Posted: 02:14pm 22 Jan 2016
Copy link to clipboard 
Print this post

Attached rough code for simple testing. It just extracts the basic data, converts it into something readable. I used it to try and get a feel for how the output data changed as you rotated the module in the different axis.


2016-01-23_001224_hmc5883l.zip
cheers
Rod
Edited by greybeard 2016-01-24
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 05:00pm 27 Feb 2016
Copy link to clipboard 
Print this post

Loaded the code that GREYBEARD supplied but there were some obvious errors with the
I2C OPEN, READ and WRITE commands that I have corrected but the line
"I2C READ HMC5883L_i2c, 0, 6, buf(0), 1, &h03" is the wrong syntax and I don't know what it should be.
Can anyone help
@TassyJim:- Did you receive your modules yet.
Paul.

Edit... Also a problem with the line "LOOP while a = a" Edited by palcal 2016-02-29
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 05:06pm 27 Feb 2016
Copy link to clipboard 
Print this post

  palcal said  
Can anyone help
@TassyJim:- Did you receive your modules yet.
Paul.

Yes I do.
I received it the day that my computers went up in smoke.
I have been putting it off in the hope that the insurance company will give me a shiny new computer to play with but I think it is time to learn to do more on this little netbook.

I find it hard reading PDF manuals on the small screen.

Jim

VK7JH
MMedit
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 07:55pm 27 Feb 2016
Copy link to clipboard 
Print this post

Here you go Paul
' test code for HMC5883L 3 axis digital compass
HMC5883L_i2c = &h1e
DIM buf(6)
PRINT "HMC5883L test"
I2C OPEN 100,100


' init hmc5883

I2C WRITE HMC5883L_i2c, 0, 2, &h00, &h70 '8-average, 15 Hz default, normal measurement
I2C WRITE HMC5883L_i2c, 0, 2, &h01, &hA0 'Gain=5, or any other desired gain
I2C WRITE HMC5883L_i2c, 0, 2, &h02, &h01 'Single-measurement mode

PAUSE 100

PRINT "init complete"
PRINT "x y z heading"

DO
I2C WRITE HMC5883L_i2c, 0, 2, &h02, &h01 'Single-measurement mode
PAUSE 6
I2C READ HMC5883L_i2c, 0, 6, buf(0) 'Read all 6 bytes
x = buf(0) * 256 + buf(1)
IF x >= &h8000 THEN x = x - 65536 ' Convert three 16-bit 2’s compliment
z = buf(2) * 256 + buf(3) ' hex values to decimal values and
IF z >= &h8000 THEN z = z - 65536 ' assign to X, Z, Y, respectively
y = buf(4) * 256 + buf(5)
IF y >= &h8000 THEN y = y - 65536
heading = DEG(Atn2(y,x))
PRINT x," ",y," ",z," ",heading
PAUSE 1000
LOOP WHILE a = a
END

FUNCTION atn2(y,x)
IF x > 0 THEN
atn2 = ATN(y/x)
ELSEIF y >= 0 AND x < 0 THEN
atn2 = PI + ATN(y/x)
ELSEIF y < 0 AND x < 0 THEN
atn2 = ATN(y/x) - PI
ELSEIF y > 0 AND x = 0 THEN
atn2 = PI / 2
ELSEIF y < 0 AND x = 0 THEN
atn2 = PI / -2
ENDIF
IF atn2 < 0 THEN
atn2 = atn2 + 2 * PI
ENDIF

END FUNCTION


I changed the I2C code to the current syntax.
I changed the reading mode to single shot rather than continuous.
The original code had the readings as x,y,z
The actual order should be x,z,y
Why, I don't know but that's the way it is.


I will worry about the self-test stuff later.

Jim

VK7JH
MMedit
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 09:55pm 27 Feb 2016
Copy link to clipboard 
Print this post

Thanks for that Jim it works OK but there is quite a variation in the heading without moving the module, I don't know what would cause that.
Here is a sample;

  Quote  HMC5883L test
init complete
x y z Heading

95 30 135 17.5256
104 27 137 14.5536
93 33 133 19.5367
106 28 136 14.7968
99 30 135 16.8584
98 31 134 17.5535
107 26 137 13.6576
94 32 133 18.7999
102 29 135 15.8712
103 28 136 15.208
94 33 133 19.3443
107 27 137 14.1622
99 30 135 16.8584
98 31 134 17.5535
107 26 137 13.6576
95 31 134 18.0723
100 30 134 16.6992
105 26 136 13.9078
93 33 133


Paul

Edit...It also shows East as 0 Degrees.Edited by palcal 2016-02-29
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 11:20pm 27 Feb 2016
Copy link to clipboard 
Print this post

This is my output with no movement:
x y z heading
-64 -71 183 227.968
-65 -71 182 227.526
-65 -71 183 227.526
-64 -71 183 227.968
-64 -70 183 227.564
-64 -71 182 227.968
-64 -71 182 227.968
-65 -70 183 227.121
-64 -70 183 227.564
-64 -71 182 227.968
-65 -71 182 227.526
-65 -71 182 227.526
-64 -71 182 227.968
-65 -71 183 227.526
-64 -71 182 227.968
-65 -71 182 227.526
-64 -70 182 227.564
-64 -71 182 227.968
-65 -71 183 227.526
-64 -70 182 227.564
>


Which way is zero degrees is something that depends on the orientation of the chip on the board.
On mine, what I thought would be zero is at 45 degrees. (North East)
That can easily be adjusted in the maths.

Jim
VK7JH
MMedit
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2934
Posted: 11:29pm 27 Feb 2016
Copy link to clipboard 
Print this post

Is the (large) variation in heading with Paul's setup likely to be caused by the HMC's external circuit?
6deg of variation is not as expected. Jim's is well within the 1-2deg tolerance.

Paul, what external circuit are you using?

I am needing a compass in a future project so keen to understand what is happening . . .
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 10:11am 28 Feb 2016
Copy link to clipboard 
Print this post

I have the module connected to a 170, but it is in my metal workshop with a lot of wiring and equipment close by. When I get a TFT connected I will take it outside and see if that makes a difference.
Paul.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 02:23pm 28 Feb 2016
Copy link to clipboard 
Print this post

OK it is much more stable when I take it away from my workshop bench.
Since z is not used in the calculation I take it I have to adjust for Declination, also why the line, LOOP until a = a , why not just LOOP.
Paul.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 06:48pm 28 Feb 2016
Copy link to clipboard 
Print this post

Paul,
LOOP WHILE a = a was one way of running the loop 'forever'. I guess that it was needed in earlier versions of MMBasic or left over from other programming styles.
I have changed to LOOP in this version.

I have added a selftest SUB. It should let you know that your device is working correctly and I would be interested in comparing results.
AS far as Mag Declination goes, yes this device give you magnetic north and you need to adjust for 'true' north.
A good site to get your mag dec from is http://www.magnetic-declination.com/

I have converted the raw data into microTesla and allowed for setting different gain.

' test code for HMC5883L 3 axis digital compass
DIM buf(6)
DIM HMC5883L_i2c = &h1e
DIM HMC5883_MAGGAIN_1_3 = &h20' +/- 1.3
DIM HMC5883_MAGGAIN_1_9 = &h40' +/- 1.9
DIM HMC5883_MAGGAIN_2_5 = &h60' +/- 2.5
DIM HMC5883_MAGGAIN_4_0 = &h80' +/- 4.0
DIM HMC5883_MAGGAIN_4_7 = &hA0' +/- 4.7
DIM HMC5883_MAGGAIN_5_6 = &hC0' +/- 5.6
DIM HMC5883_MAGGAIN_8_1 = &hE0' +/- 8.1
DIM hmc5883_Gauss_LSB_XY
DIM hmc5883_Gauss_LSB_Z
DIM GAUSS_TO_MICROTESLA = 100

DIM magGain = HMC5883_MAGGAIN_4_7

SELECT CASE magGain
CASE HMC5883_MAGGAIN_1_3
hmc5883_Gauss_LSB_XY = 1100
hmc5883_Gauss_LSB_Z = 980
CASE HMC5883_MAGGAIN_1_9
hmc5883_Gauss_LSB_XY = 855
hmc5883_Gauss_LSB_Z = 760
CASE HMC5883_MAGGAIN_2_5
hmc5883_Gauss_LSB_XY = 670
hmc5883_Gauss_LSB_Z = 600
CASE HMC5883_MAGGAIN_4_0
hmc5883_Gauss_LSB_XY = 450
hmc5883_Gauss_LSB_Z = 400
CASE HMC5883_MAGGAIN_4_7
hmc5883_Gauss_LSB_XY = 400
hmc5883_Gauss_LSB_Z = 255
CASE HMC5883_MAGGAIN_5_6
hmc5883_Gauss_LSB_XY = 330
hmc5883_Gauss_LSB_Z = 295
CASE HMC5883_MAGGAIN_8_1
hmc5883_Gauss_LSB_XY = 230
hmc5883_Gauss_LSB_Z = 205
CASE ELSE
magGain = HMC5883_MAGGAIN_4_7
hmc5883_Gauss_LSB_XY = 400
hmc5883_Gauss_LSB_Z = 255
END SELECT


PRINT "HMC5883L test"

I2C OPEN 100,100

selftest ' not usually needed

' init hmc5883
I2C WRITE HMC5883L_i2c, 0, 2, &h00, &h70 '8-average, 15 Hz default, normal measurement
I2C WRITE HMC5883L_i2c, 0, 2, &h01, magGain 'Gain=5, or any other desired gain
I2C WRITE HMC5883L_i2c, 0, 2, &h02, &h01 'Single-measurement mode

PAUSE 100

PRINT "init complete"
PRINT " x y z heading"

DO
I2C WRITE HMC5883L_i2c, 0, 2, &h02, &h01 'Single-measurement mode
PAUSE 6
I2C READ HMC5883L_i2c, 0, 6, buf(0) 'Read all 6 bytes
x = buf(0) * 256 + buf(1)
IF x >= &h8000 THEN x = x - 65536 ' Convert three 16-bit 2’s compliment
z = buf(2) * 256 + buf(3) ' hex values to decimal values and
IF z >= &h8000 THEN z = z - 65536 ' assign to X, Z, Y, respectively
y = buf(4) * 256 + buf(5)
IF y >= &h8000 THEN y = y - 65536
xt = x /hmc5883_Gauss_LSB_XY * GAUSS_TO_MICROTESLA
yt = y / hmc5883_Gauss_LSB_XY * GAUSS_TO_MICROTESLA
zt = z / hmc5883_Gauss_LSB_Z * GAUSS_TO_MICROTESLA
heading = DEG(Atn2(y,x))
PRINT STR$(xt,3,2),"uT ",STR$(yt,3,2),"uT ",STR$(zt,3,2),"uT ",STR$(heading,3,1)
PAUSE 2000
LOOP
END

SUB selftest
PRINT "Positive self test"
PRINT "values should be 243 to 575 for Gain=5"

I2C WRITE HMC5883L_i2c, 0, 2, &h00, &h71 '8-average, 15 Hz default, pos self test
I2C WRITE HMC5883L_i2c, 0, 2, &h01, magGain 'Gain=5, or any other desired gain
I2C WRITE HMC5883L_i2c, 0, 2, &h02, &h00 'Single-measurement mode
PAUSE 6

FOR n = 1 TO 10
I2C READ HMC5883L_i2c, 0, 6, buf(0) 'Read all 6 bytes
x = buf(0) * 256 + buf(1)
IF x >= &h8000 THEN x = x - 65536 ' Convert three 16-bit 2’s compliment
z = buf(2) * 256 + buf(3) ' hex values to decimal values and
IF z >= &h8000 THEN z = z - 65536 ' assign to X, Z, Y, respectively
y = buf(4) * 256 + buf(5)
IF y >= &h8000 THEN y = y - 65536
I2C WRITE HMC5883L_i2c, 0, 1, &h03 ' reset pointer to start of data
PAUSE 100
PRINT x," ",y," ",z
NEXT n
I2C WRITE HMC5883L_i2c, 0, 2, &h00, &h70
PAUSE 100
PRINT ""
PRINT "Negative self test"
PRINT "values should be -243 to -575 for Gain=5"
I2C WRITE HMC5883L_i2c, 0, 2, &h00, &h72 '8-average, 15 Hz default, neg self test
I2C WRITE HMC5883L_i2c, 0, 2, &h01, magGain 'Gain=5, or any other desired gain
I2C WRITE HMC5883L_i2c, 0, 2, &h02, &h00 'Single-measurement mode
PAUSE 6

FOR n = 1 TO 10
I2C READ HMC5883L_i2c, 0, 6, buf(0) 'Read all 6 bytes
x = buf(0) * 256 + buf(1)
IF x >= &h8000 THEN x = x - 65536 ' Convert three 16-bit 2’s compliment
z = buf(2) * 256 + buf(3) ' hex values to decimal values and
IF z >= &h8000 THEN z = z - 65536 ' assign to X, Z, Y, respectively
y = buf(4) * 256 + buf(5)
IF y >= &h8000 THEN y = y - 65536
I2C WRITE HMC5883L_i2c, 0, 1, &h03 ' reset pointer to start of data
PAUSE 100
PRINT x," ",y," ",z
NEXT n
I2C WRITE HMC5883L_i2c, 0, 2, &h00, &h70
PRINT ""
PRINT "Self test completed"

END SUB

FUNCTION atn2(y,x)
IF x > 0 THEN
atn2 = ATN(y/x)
ELSEIF y >= 0 AND x < 0 THEN
atn2 = PI + ATN(y/x)
ELSEIF y < 0 AND x < 0 THEN
atn2 = ATN(y/x) - PI
ELSEIF y > 0 AND x = 0 THEN
atn2 = PI / 2
ELSEIF y < 0 AND x = 0 THEN
atn2 = PI / -2
ENDIF
IF atn2 < 0 THEN
atn2 = atn2 + 2 * PI
ENDIF
END FUNCTION


Jim
VK7JH
MMedit
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 09:07pm 28 Feb 2016
Copy link to clipboard 
Print this post

@ TassyJim
I ran the test, but have absolutely no idea what it does.
These are my results.

HMC5883L test
Positive self test
values should be 243 to 575 for Gain=5
419 417 394
419 417 394
419 417 394
419 417 394
419 417 394
419 417 394
419 417 394
419 417 394
419 417 394
419 417 394

Negative self test
values should be -243 to -575 for Gain=5
121 -63 148
-410 -422 -384
-410 -424 -382
-411 -423 -383
-410 -422 -384
-411 -422 -383
-412 -422 -383
-411 -423 -384
-411 -423 -384
-411 -423 -382

Paul.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 09:38pm 28 Feb 2016
Copy link to clipboard 
Print this post

My readings were similar:
Positive self test
values should be 243 to 575 for Gain=5
481 452 443
481 452 443
481 452 443
481 452 443
481 452 443
481 452 443
481 452 443
481 452 443
481 452 443
480 456 443

Negative self test
values should be -243 to -575 for Gain=5
66 -455 181
-475 -457 -435
-473 -455 -435
-473 -455 -434
-471 -458 -435
-471 -455 -435
-472 -455 -434
-473 -456 -435
-471 -456 -435
4112 4112 4112

Self test completed
init complete
x y z heading
16.50 uT -1.00 uT 70.98 uT 356.5
16.50 uT -1.00 uT 70.59 uT 356.5
16.50 uT -1.25 uT 70.98 uT


According to the datasheet, this means that the chip is working correctly and the gain setting chosen is correct.

You can now rem out the call to selftest and forget that you ever saw those figures.

Jim

VK7JH
MMedit
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 09:53pm 28 Feb 2016
Copy link to clipboard 
Print this post

Thanks for all the help Jim.
Paul.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2934
Posted: 09:55pm 28 Feb 2016
Copy link to clipboard 
Print this post

With a keen eye on this thread (and still awaiting my HMC5883's to arrive) I have to ask if this latest code is giving consistent headings; and using all data available to calculate a meaningful 'direction'

Also, does this latest code work any better for you (PalCal) in your workshop? The HMC is meant to be good to use in 'noise' environments. I intend to be using this chip on a robot buggy i.e. near 'noisy' motors so am keen to play with this asap.

@matherp EDIT: SORRY - I mean TassyJim - is your code 'heading' ( ) towards another version, or are all the calculations looking good from the responses here?

WW Edited by WhiteWizzard 2016-03-01
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 1989
Posted: 11:13pm 28 Feb 2016
Copy link to clipboard 
Print this post

@WW
My module now displays steady readings on the bench in my workshop. I don't know what the cause of the fluctuations was but it is OK now.
Paul.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2934
Posted: 11:22pm 28 Feb 2016
Copy link to clipboard 
Print this post

  palcal said   @WW
My module now displays steady readings on the bench in my workshop. I don't know what the cause of the fluctuations was but it is OK now.
Paul.


Thats great to hear! Hoping now that the postman brings my chips this morning!!
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6270
Posted: 11:33pm 28 Feb 2016
Copy link to clipboard 
Print this post

@WW
There haven't been any real changes to my code.
All I did was convert the raw data to microTesla (data from the datasheets and an Arduino program)
My skills with 3D aren't good enough to play with the 3 axis any more than whats there so far.

My chip output agrees with a standard compass. It is off a lot on the bench and is probably within the quote 1-2 degrees when out in the clear.

Jim
VK7JH
MMedit
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2934
Posted: 11:39pm 28 Feb 2016
Copy link to clipboard 
Print this post

Thanks Jim.

If you were to stand with your module held like a 'manual' compass (pointing out in front of you) and get a reading; does that reading remain consistent even if you turn the module upside down but still pointing in the same direction?

Make sense? I am basically wondering if 'spin' affects the reading while the unit points in a consistent direction (don't want to say 'spin about the axis' as this may be mis-interprretted!!)

WW
 
     Page 1 of 3    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025