![]() |
Forum Index : Microcontroller and PC projects : HMC5883L magnetometer
Page 1 of 3 ![]() ![]() |
|||||
Author | Message | ||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1989 |
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: AustraliaPosts: 6270 |
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: AustraliaPosts: 172 |
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 |
||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1989 |
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" "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: AustraliaPosts: 6270 |
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: AustraliaPosts: 6270 |
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: AustraliaPosts: 1989 |
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; Paul Edit...It also shows East as 0 Degrees. "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: AustraliaPosts: 6270 |
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 KingdomPosts: 2934 |
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: AustraliaPosts: 1989 |
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: AustraliaPosts: 1989 |
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: AustraliaPosts: 6270 |
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: AustraliaPosts: 1989 |
@ 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: AustraliaPosts: 6270 |
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: AustraliaPosts: 1989 |
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 KingdomPosts: 2934 |
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 ![]() ![]() WW |
||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1989 |
@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 KingdomPosts: 2934 |
Thats great to hear! Hoping now that the postman brings my chips this morning!! |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6270 |
@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 KingdomPosts: 2934 |
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 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |