#rem
Test of magnetometer type HMC5883L.
At power up, initialise the reference value that will be used to compare with test read values.
The initialise routine takes 5 readings and this is averaged to give the reference value.
The store is words W9 to W13.
The reference value is then calculated on a rolling average of the previous saved readings.
The reading is saved every 5000 readings and allows for slow variations over time.
The test read is made and compared to the reference value. If it is more than "alarmlvl" from
the reference value, the alarm activates. Once activated, it loops until the alarm situation is removed
before returning to the read and test loop.
Portions of this code directly related to the setup and reading of the magnetometer were supplied by
members of the Picaxe forum. With thanks.
#endrem
Symbol x = w0 'x, y, z are values read from the magnetometer
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
Symbol storex = w3 'store the reference value
Symbol strlow = w4 'low reference value
Symbol strhigh = w5 'high reference value
symbol i = b12 'i is use as a counter
symbol alarmlvl = b13 'offset from average value to trigger alarm
alarmlvl = 10
symbol n = w8 'counter for update average value loop
#rem
symbol str1 = w9 'reserved for storage
symbol str2 = w10
symbol str3 = w11
symbol str4 = w12
symbol str5 = w13
#endrem
bptr = 18 'point to start of storage area
'****************************************************************************************************
Main:
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)
gosub init 'Initialise magnetometer alarm values
'Main program loop starts here
repeat:
gosub readmag 'Get x, y & z readings
x = x+y+z/3 'get average value
'check for alarm before saving and calculating new reference values.
if x > strhigh then 'Compare with the reference values
gosub alarm
goto repeat
elseif x < strlow then
gosub alarm
goto repeat 'do not save this value into store.
endif
n=n+1 'count the number of readings done
if n = 5000 then
gosub update 'update reference value
endif
goto repeat 'go and get another reading
'**************************************************************************
init:
'Initialise magnetometer default alarm setting by averaging 5 readings at power on.
'This is used to compare future reading to determine if vehicle is close.
'5 readings of x,y & z (15 values) are averaged.
for i = 1 to 5 'take 5 readings and get average
gosub readmag
x = x+y+z/3 'get the average of the x, y and z readings
gosub update
@bptrinc = b0 'save it in the store and increment ptr
@bptrinc = b1
if bptr = 28 then
bptr =18 'end of store, goto start
endif
next i
storex = w9+w10+w11+w12+w13/5 'add all stored values and get average
strlow = storex-alarmlvl 'set reference limit values
strhigh = storex+alarmlvl
return
'*************************************************************************
readmag: 'Read the magnetometer
hi2cout $02, ($01) 'Request single measurement Reg 02 = mode reg.
pause 100 'Allow time for measurement and display
HI2cIn $03, (x.msb, x.lsb, z.msb, z.lsb, y.msb, y.lsb) 'Read from reg 03 onwards into variables
x = x+2048
y = y+2048
z = z+2048
return
'*****************************************************************************
alarm:
high c.4 'turn on the relay
high c.0 'turn on LED
pause 500
low c.4 'turn off the relay
Gosub alarmover 'wait until the alarm condition clears before going back
low c.0
return
'**********************************************************************************
alarmover: 'check for alarm still active.
gosub readmag
x = x+y+z/3 'get average value
if x > strhigh then 'Compare with the reference value before the alarm detected.
goto alarmover 'loop around until alarm condition gone
elseif x < strlow then
goto alarmover
endif
return
'************************************************************************************
Update: 'save every 5000th reading in store
@bptrinc = b0 'save it in the store and increment ptr
@bptrinc = b1
if bptr = 28 then
bptr =18 'end of store, set pointer to start
endif
storex = w9+w10+w11+w12+w13/5 'add all values and get average
strlow = storex-alarmlvl 'set reference limit values
strhigh = storex+alarmlvl
n = 0 'reset the update counter
return