HMC5883L magnetometer

MFB

Senior Member
Just received the new low cost 3-axis magnetometer board from Sparkfun (http://www.sparkfun.com/products/10530) and it seems to work with the following 28X2 code...

hi2csetup i2cmaster, $3C, i2cslow_16, i2cbyte 'Setup I2C
hi2cout $00, ($70) 'Set requister A, for 8-average, 15Hz, normal measurement
hi2cout $01, ($A0) 'Set requister B, for gain = 5

start:
hi2cout $02, ($01) 'Request single measurement
pause 1000
hi2cin $03, (b0,b1,b2,b3,b4,b5) 'Read the six output requisters (but documantation said use $06?)
sertxd (#w0,",",#w1,",",#w2,cr) 'Combine into three data words and send to PC
goto start 'Next three measurements

However, please can anyone help with additional code to convert the 16-bit 2's compliment outputs to decimal?
 

hippy

Technical Support
Staff member
From the datasheet (table 2) the X, Y and Z registers seem to be from $03 onwards so ...

Code:
Symbol x     = w0
Symbol x.lsb = b0
Symbol x.msb = b1

[i]Similar for Y and Z[/i]

HI2cIn $03, (x.mb, x.lsb, z.msb, z.lsb, y.msb, y.lsb )

If x >= $8000 Then
  x = -x
  SerTxd( "X= -", #x )
Else
  SerTxd( "X= +", #x )
End If

[i]Similar for Y and Z[/i]
Edit : Check out page 11, "Register Access". Reading from location $03 may not be as simple as shown above.
 
Last edited:

MFB

Senior Member
Thanks hippy for the help with the 2's compliment conversion.

The raw output seems to work using $03 as the start address (Data Out X MSB Register) shown on page 11 of the Honeywell data sheet. However, I'm a bit confused
because the example "single-measurement mode" example shown at the foot of page 18 gives $06 as the start address but (according to page 11 again) this would be
part way through the data output registers at Z LSB. Any guidance would be welcome here.

The raw data looks promising but adding the decimal conversion will give me a better idea.

BTW, Rather than buying Sparkfun products direct, I now get them via Active Robots in the UK. Don't be put off by their very limited cataloque because they are happy
to obtain other products from the SparkFun range. The price is about the same as buying direct from the states, when VAT and postage is included.
 

MFB

Senior Member
The following code includes hippy's 2's compliment conversion to give +/- decimal output. This is great for initial tests but can anyone please suggest best way to convert 2's compliment to StampPlot format (e.g. 0 to 4094)?




Filename:MagTest 2
; Date: 23-7-2011
; File Version: 0.2
; Written by: MFB
; Function:Sets up HMC5883L, converts data from 2's compliment to +/- decimal and send to PC
; Last Revision:
; Target: PICAXE:28X2 with 16MHz crystal
' Status: Outputs seems to relate to changes in attitude and test magnet, but real-time plot would help confirm


; *******************************

Symbol x = w0
Symbol x.lsb = b0
Symbol x.msb = b1

Symbol y = w1
Symbol y.lsb = b2
Symbol y.msb = b3

Symbol z = w2
Symbol z.lsb = b4
Symbol z.msb = b5


hi2csetup i2cmaster, $3C, i2cslow_16, i2cbyte 'Setup PICAXE I2C port
hi2cout $00, ($18) 'Set mag req A for non-average,75Hz,normal measurement
hi2cout $01, ($00) 'Set mag req B for range of +/- 0.88Ga (Earth = +/-0.5Ga)

start:
hi2cout $02, ($01) 'Request single measurement
pause 500 'Allow time for measurement and display
HI2cIn $03, (x.msb, x.lsb, z.msb, z.lsb, y.msb, y.lsb)'Read six bytes of 2's compliment data

If x >= $8000 Then 'Convert X to +/- decimal and send to PC *
x = -x
SerTxd( " X -", #x )
Else
SerTxd( " X +", #x )
End If


If y >= $8000 Then 'Convert Y to +/- decimal and send to PC *
y = -y
SerTxd( " Y -", #y )
Else
SerTxd( " Y +", #y )
End If


If z >= $8000 Then 'Convert Z to +/- decimal and send to PC *
z = -z
SerTxd( " Z -", #z )
Else
SerTxd( " Z +", #z )
End If

sertxd (cr)

goto start 'Next measurements


'* Output range $F800 to $07FF (-2048 to +2047)
 

hippy

Technical Support
Staff member
can anyone please suggest best way to convert 2's compliment to StampPlot format (e.g. 0 to 4094)?
I'm not familiar with StampPlot so if we had values from the magnetometer of -2, -1, 0, +1 and +2, what values would you want sending to StampPlot ?

It should be easy enough, just depends on what that mapping is.
 

MFB

Senior Member
Thanks hippy. The default format for StampPlot Pro is comma separated decimal values terminated by a carriage return. A three channel example would be sertxd (#w0,",",#w1,",",#w2,cr) with each values start at zero and increasing to a maximum of 4096.
 

marks

Senior Member
try something like this

Symbol x = w0
Symbol x.lsb = b0
Symbol x.msb = b1

Symbol y = w1
Symbol y.lsb = b2
Symbol y.msb = b3

Symbol z = w2
Symbol z.lsb = b4
Symbol z.msb = b5


hi2csetup i2cmaster, $3C, i2cslow_16, i2cbyte 'Setup PICAXE I2C port
hi2cout $00, ($18) 'Set mag req A for non-average,75Hz,normal measurement
hi2cout $01, ($00) 'Set mag req B for range of +/- 0.88Ga (Earth = +/-0.5Ga)

start:
hi2cout $02, ($01) 'Request single measurement
pause 500 'Allow time for measurement and display
HI2cIn $03, (x.msb, x.lsb, z.msb, z.lsb, y.msb, y.lsb)

x = x+2048

y = y+2048

z = z+2048


sertxd (#w0,",",#w1,",",#w2,cr)
goto start 'Next measurements
 

MFB

Senior Member
Marks, thanks that works fine!
I can certainly recommend this new magnetometer from Honeywell. I had been using the basic HMC1053, which needed a significant amount of analog circuitry (FETs for reset and an instrumentation amp per axis) to interface to a microcontroller. Not only does the 5883 have integral signal conditioning but it's much cheaper at less than £10.

BTW, SelmaWare released an updated version of StampPlot Pro in June. Download for free!
 

julianE

Senior Member
Gents,
I've been struggling to get the HMC5883L module to work for many days and am ready to throw in the towel.
I tried it with a 28X2, 18M2 and the trusty 20X2. To verify the Picaxe I tried it with a 24LC256 and it works fine.
To test the HMC5883L module I attached it to the 'duino and it works like a champ.
i tried all the sample codes mentioned in the post other then Hippy's skeleton code.
The one thing I have not tried is using an external crystal, is that absolutely necessary?
Must it be run at 16Mhz, I would think it should work at 8.

As always any help would be appreciated.
 

MPep

Senior Member
Did you adjust the commands to reflect you are using 8MHz? ie "hi2csetup i2cmaster, $3C, i2cslow_16, i2cbyte" --> "hi2csetup i2cmaster, $3C, i2cslow_8, i2cbyte"

Also, please remember the [ code ] [ /code ] tags as this makes the post much easier to read.
 

MFB

Senior Member
Crystal will not make much difference when using I2C. Are you running the magnetometer from 3.3V and what value pullup resistors are you using?
 

julianE

Senior Member
Crystal will not make much difference when using I2C. Are you running the magnetometer from 3.3V and what value pullup resistors are you using?
yes, i am running it at 3.3 V and the board comes with it's own pull up resistor. The schematic does not show the resistor value. I guess i can measure it.
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/BreakoutBoards/HMC5883L_Breakout-v11.pdf

as a precaution, I went and added my own pull ups in addition, 47K, which would end up lowering whatever value sparkfun used.

to further experiment i used a sure electronics, compass module with I2C and it worked right away.

The one thing i noticed in the 'duino program is that they check the ready line, i think register 6 to verify that the module has made a reading, but i need to check on that.
 

MFB

Senior Member
I'll double check my setup and get back to you if I find anything else worth trying.
 

crowland

Member
The Sparkfun circuit shows a couple of pull ups but they aren't fitted.

I am using 10k pull ups with this and it works very well.

I don't have the exact code to hand but with an 08M2 running at the default 4MHz I've had no problem. I set it to the sleep mode then when I want to read do something like this:
Code:
readCompass:
	hi2cout 2,($01)	; single conversion
	pause 10			; wait
	hi2cin 3, (XH,XL, ZH,ZL, YH,YL)	; read
	; check for a valid conversion
	if X = $F000 or Y = $F000 or z = $F000 then
		dataValid = 0
	else
		dataValid = 1
	endif
	return
Chris
 

MFB

Senior Member
Yes, crowland has found the problem. I checked my circuit and found that it was necessary to add two 3.3K pull up resistors at the PICAXE end. My be your Arduino test setup already had pull ups.
 

julianE

Senior Member
I will try your suggestion first chance I get. I have an 8M2 handy so I will try the code as well. I looked at the board and there are pull ups on it but then again they may not be hooked up.
Thanks for all the effort, I will reply as soon as I test it.
 

julianE

Senior Member
Hello MFB and Crowland I tested and all is well. I also measured the breakout board and sure enough there are no pull up resistors. There are resistors on the board but they must not be used. I used 8K resistors for pull ups. I know I tried using external resistors before but probably missed something else, juggling too many variables.

Thanks very much for all the help.
 

klyball

New Member
Hi I am trying to use the hmc5883l as a compass for a project I am using the code below i believe the data is broken into 4 quadrants 315-45, 45-135, 135-225, 225-315

when i run the code i get a accurate reading from 315-45 but before or after that the results are wrong, i have been trying to understand the math ,but can't get my head around it, i believe i need to add to this section highlighted to have the results be corrected , if someone can explain or point me in the right direction that would be a great help.

Code:
symbol x = w0 ' x coord
 symbol ax = w0 ' absolute x (same word as x)
 symbol y = w1 ' y coord
 symbol bias = w2 ' angle bias
 symbol sign = w3 ' sign, 1 or -1
 symbol temp = w4 ' temporary var for calculations
 symbol r = w5 ' temporary var for approximation
 symbol angle = w6 ' result
 symbol scale = 8 ' scale (tenths of a degree), needed for fixed point arithmetic
 symbol scsq = scale * scale ' scale squared
 symbol pi14 = 45 * scale ' (360 degs + 45 degs) * scale
 symbol pi34 = 135 * scale ' (360 degs + 135 degs) * scale
 symbol neg = 32768 ' negative numbers start here
 symbol pos = 32767 ' positive numbers end here
 symbol neg1 = 65535 ' negative one
 symbol fact1 = 11 * scale ' factor 1 for approximation: 11.247 * scale
 symbol fact2 = 56 * scale ' factor 2 for approximation: 56.247 * scale
 symbol circle = 360 * scale ' 360 degs * scale

 ' get your values here!

 
atan2:

 atan2init:
 ' determine final sign
 [COLOR="#FF0000"]sign = 1
 if x > pos then : sign = 65535 : ax = -x : endif

 temp = ax + y
 r = y - ax
 bias = pi14 
 if y > pos then : temp = ax - y : r = y + ax : bias = pi34 : endif[/COLOR]


 ' remember that with picaxes operations are performed in the order they are written!!!
 approx:
 if r < neg then : r = r * scsq / temp : else r = -r : r = r * scsq / temp : r = -r : endif
 angle = fact1 * r / scsq * r / scsq - fact2 * r
 if angle < neg then : angle = angle / scsq : else angle = -angle : angle = angle / scsq : angle = -angle : endif
 angle = angle + bias * sign + circle % circle * 10 / scale
 sertxd ("Angle:",#angle,13,10) ' note the *10 above - answer is returned in 5ths of a degree
 
Last edited:

AllyCat

Senior Member
Hi,

I haven't examined your code in great detail, but two items look rather "suspicious". Also, my PE (5.5.6) didn't seem to like the variable "neg" so I changed it (to negx). When I changed "scale = 8" to "scale = 10", the simulator produced a different result. That suggets a mistake, for example that the scale factor has been omitted from one of the expressions. Also, "....+ circle % circle ...." doesn't do anything useful, similar to adding zero (I had to use the manual to look up the meaning of %, personally I prefer // for the remainder from a division).

However, the main issue is probably that the calculation needs to be divided into eight octants (or sectors), to cover all permutations of the sign of X the sign of Y, and whether X>Y or Y>X (to avoid overflows, due to division by small numbers or zero).

By chance, I needed an ARCTAN routine just a few weeks ago which I was planning to eventually submit to the "code snippets" section of the forum, but I think it can be improved first. However, I estimated that using only two "piecewise linear" sections produces a maximum error of one degree (around 17 and 38 degrees), so I only calculated wth byte variables and predominantly integer degrees (good enough for my needs). Here's a "preview" of my first attempt:

Code:
#picaxe 20m2        ; or probably any other
#no_data

symbol negx = 128
symbol deltx= b10
symbol delty= b11 
symbol sect = b0 				; Sector number from 0 (0 - 45 degs) to 7 (315 - 360 degs) MUST BE b0
symbol vect  = w12

deltx = 50     ; test values
delty = 86     ;
arctan:
		if deltx < negx then 
			sect = 0
		else
			sect = 7
			deltx = - deltx
		endif		 
		if delty > negx then
			sect = sect xor 3
			delty = - delty	
		endif	
		if deltx > delty then
			sect = sect xor 1
			swap deltx, delty						; swap uses 12 - 14 bytes of codespace!
		endif
		vect = 256 * deltx / delty and 255  	; Calc ATAN from fractional byte (0-255) [AND patches 0/0]
		if vect < 129  then						; ATAN 0.5 = 26 degrees
			vect = vect * 26 / 128					; Sector from 0 to 26 degrees
		else
			vect = vect - 128 * 19 / 128 + 27	; Second line section from 0.5 to 1 (26 - 45 degrees)
		endif
		b0 = sect
		if bit0 = 1 then
			vect = 45 - vect						; Reverse the sector from 90 to 45 degrees
		endif
		vect = sect * 45 + vect
	sertxd(#vect)
Cheers, Alan.
 
Last edited:

radiogareth

Senior Member
Symbol x = w0
Symbol x.lsb = b0
Symbol x.msb = b1

Symbol y = w1
Symbol y.lsb = b2
Symbol y.msb = b3

Symbol z = w2
Symbol z.lsb = b4
Symbol z.msb = b5


hi2csetup i2cmaster, $3C, i2cslow_16, i2cbyte 'Setup PICAXE I2C port
hi2cout $00, ($18) 'Set mag req A for non-average,75Hz,normal measurement
hi2cout $01, ($00) 'Set mag req B for range of +/- 0.88Ga (Earth = +/-0.5Ga)

start:
hi2cout $02, ($01) 'Request single measurement
pause 500 'Allow time for measurement and display
HI2cIn $03, (x.msb, x.lsb, z.msb, z.lsb, y.msb, y.lsb)

x = x+2048

y = y+2048

z = z+2048


sertxd (#w0,",",#w1,",",#w2,cr)
goto start 'Next measurements
I've just got three of these from China Ebay and I hope to hook them up to an 08M2. This listing checks Ok with an 08M2 as the processor, so I guess I just hook up pins C.1 and C.2 as per the PCB markings, plus power supply. I'm using these http://www.ebay.co.uk/itm/390654140041?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649
It looks like they have pull-ups fitted, but I'll check with a magnifier and multi-meter. If it works the next step is to make it talk to an LCD via serial and in degrees.
 

techElder

Well-known member
Would these magnetometers be sensitive enough to detect a "vehicle", such as in a driveway "vehicle" detector using Earth magnetic field?

The specs say, "Measuring range: ± 1.3-8 Gauss"
 

radiogareth

Senior Member
'Probably' if they can sense the earths magnetic field and essentially tiny changes in it, then they should detect variations in it caused by a large metallic object. Need to get it connected first :)
 

AllyCat

Senior Member
Hi,

Assuming that the "vehicle" is made of steel (and not wood, carbon fibre or aluminium/aluminum, etc) then I would expect to be able to detect it passing over a (buried) sensor but probably not passing any significant distance "beside" it.

However, I believe that most vehicle sensors use (buried) induction loop principles (rather like an inverted treasure seeker's metal detector) where the resonance of a tuned circuit (the loop) is "modified" (in frequency or Q) by the presence of the vehicle.

Cheers, Alan.
 

Haku

Senior Member
Glad this thread got resurrected, a few days ago I received two of the same modules from the same seller radiogareth got his from :) and I notice the price as dropped during the weeks they took to arrive!

These ones have a 3.3v regulator onboard capable of delivering 250mA, so you can run your Picaxe from the 3.3v pin, but the regulator can only take 6v maximum input voltage.

When the christmas frenzy has settled down I'll be getting stuck into this and some other boards I haven't yet tinkered with, including a GPS module, Nokia 5110 screens, rain sensor & sound sensors.
 
Top