Example program connecting a MAG3110 3-axis magnetometer to a Picaxe 08M2.
The Mag3110:
A critical parameter for a meaningfull measurement is the offset in each direction X, Y, and Z. To estimate these values have the program run with all 3 Offsets set at $0000, while turning and twisting the Mag3110 in all directions. Note down the max en min values for X, Y and Z. The midpoint between X-max and X-min is the estimate for the X Offset, same for Y, Z (you need to convert them to their two's-complements values in the program below).
Enjoy
Thierry
The Mag3110:
- has an I2C interface
- is very sensitive (0,1uT resolution, while the Earth's magnetic field is 50uT strong around here (and pointing almost straight down, about 65-70 degrees downwards, didn't realise that)
- it's speed is OK (max 80 3D readings per second)
- is very small, you need a breakout board to use it, but these are not too expensive, see: www.sparkfun.com or www.olimex.com
- runs on 3.3V, so don't connect it to 5V, it will be fried
A critical parameter for a meaningfull measurement is the offset in each direction X, Y, and Z. To estimate these values have the program run with all 3 Offsets set at $0000, while turning and twisting the Mag3110 in all directions. Note down the max en min values for X, Y and Z. The midpoint between X-max and X-min is the estimate for the X Offset, same for Y, Z (you need to convert them to their two's-complements values in the program below).
Enjoy
Thierry
Code:
;Testprogram for MAG3110 3-axis Magnetometer
; -Uses MAG3110 (Mag) I2C interface
; -Reads XYZ values from Mag
; -Applies XYZ Offset values in program (instead of in-chip)
; -Displays XYZ values on LCD module (AXE133)
; -Currently runs at approx 180ms per loop, measurements + displays
; Most of this is display time to Serial LCD
; Should be possible to run it close at max speed of less than 20ms per loop, without slow display
; v1 ThierryP, April 2012
#picaxe 08M2
;Connections 08M2
;--Pin--Name----Function--------Remark
; 1 +V Supply Voltage IMPORTANT! USE 3.3V, 5V WILL FRY THE MAG3110!!
; 2 C.5 Serial In Programming Interface Rx
; 3 C.4 Out Serial Tx Interface to LCD Panel AXE133 (I use idle=hi levels in AXE133, "T2400", can be changed)
; 4 C.3 In Irq from Mag (not used in this test)
; 5 C.2 hi2c SDA I2C SDA interface with Mag, with 4k7 Pull-Up
; 6 C.1 hi2c SCL I2C SCL interface with Mag, with 4k7 Pull-Up
; 7 C.0 Serial Out Programming Interface Tx
; 8 0V Ground Again, use 3.3V as +!!
;-------------------------------
symbol RawX= w0 ;Raw X value of Magnetic Field, b1-b0
symbol RawY= w1 ;Raw Y value of Magnetic Field, b3-b2
symbol RawZ= w2 ;Raw Z value of Magnetic Field, b5-b4
symbol MagnX= w3 ;Converted X value of Magnetic Field, b7-b6
symbol MagnY= w4 ;Converted Y value of Magnetic Field, b9-b8
symbol MagnZ= w5 ;Converted Z value of Magnetic Field, b11-b10
symbol OffsX= w6 ;X Offset value of Magnetic Field, b13-b12
symbol OffsY= w7 ;Y Offset value of Magnetic Field, b15-b14
symbol OffsZ= w8 ;Z Offset value of Magnetic Field, b17-b16
symbol SignX= b18 ;Sign of Converted X value
symbol SignY= b19 ;Sign of Converted Y value
symbol SignZ= b20 ;Sign of Converted Z value
symbol SignBit = b26 'temp variable
symbol CntConv = b27 'to check the speed of loops
symbol K4D = b21 'ten-thousand in readout
symbol K3D = b22 'thousand in readout
symbol K2D = b23 'hundred in readout
symbol K1D = b24 'ten in readout
symbol K0D = b25 'units in readout
symbol SerLCD = C.4
symbol baud = T2400_16
;Change these Offset values for each Mag (Calibration)
;Initially set all offsets at $0000 and check range extremes of the Raw XYZ values
;Then the Offsets are the means of Max and Min XYZ values
;########################################
let OffsX = $0CD2 '2-complement of +3282
let OffsY = $F778 '2-complement of -2183
let OffsZ = $F591 '2-complement of -2670
;########################################
CntConv=0
setfreq m16
serout SerLCD, baud, (254,1) ;Clear LCD Display
pause 300
hi2csetup i2cmaster, %00011100, i2cfast_16, i2cbyte
;MAG3110 Address is $0E. In bits 7-1 that becomes: %000 1110 x
hi2cin $07, (b0) ;Test presence of Mag if needed: ID=$C4, ignored here
hi2cout $11, ($80) ;Init Mag Ctrl_reg2: operation mode, RESET
hi2cout $10, ($01) ;Init Mag Ctrl_reg1: operation mode, ACTIVE
main:
;---Measure XYZ------------
hi2cin 1,(b1, b0, b3, b2, b5, b4) ;read 6 raw bytes from address 1, 2-complement
;---Calc X------------------------------
let RawX = RawX - OffsX ;substract X-offset, 2-complement
SignX = "+"
MagnX = RawX
SignBit = RawX / 256 / 128
if SignBit=1 then
SignX="-"
MagnX= RawX ^ $FFFF + 1 ;Convert 2-complement negative to normal binary
endif
;---Display X on 16x2 display, top line - Left
bintoascii MagnX, b21,b22,b23,b24,b25
serout SerLCD, baud, (254,128)
serout SerLCD, baud, ("X=", SignX, b22,b23,b24,b25, " ") ; 10k's suppressed, display will overflow with strong fields
'---Calc YX------------------------------
let RawY = RawY - OffsY
SignY = "+"
MagnY = RawY
SignBit = RawY / 256 / 128
if SignBit=1 then
SignY="-"
MagnY= RawY ^ $FFFF + 1 ;Convert 2-complement negative to normal binary
endif
'---Display Y on 16x2 display, top line - Right
bintoascii MagnY, b21,b22,b23,b24,b25
serout SerLCD, baud, ("Y=", SignY, b22,b23,b24,b25)
'---Calc Z------------------------------
let RawZ = RawZ - OffsZ
SignZ = "+"
MagnZ = RawZ
SignBit = RawZ / 256 / 128
if SignBit=1 then
SignZ="-"
MagnZ= RawZ ^ $FFFF + 1 ;Convert 2-complement negative to normal binary
endif
'---Display Z on 16x2 display, 2nd line - Left
bintoascii MagnZ, b21,b22,b23,b24,b25
serout SerLCD, baud, (254,192)
serout SerLCD, baud, ("Z=", SignZ, b22,b23,b24,b25, " ")
CntConv=CntConv+1
bintoascii CntConv, b21, b22, b23
serout SerLCD, baud, ("Cnt=", b21,b22,b23)
'debug
goto main