PDA

View Full Version : HMC5883L Magnetometer chip Possibilities.



andybarrett1
- 8th June 2014, 17:58
Hi all

Am looking at the possibly of using a HMC5883L Magnetometer in a compass application with a PIC.

Has anybody had any experience in these chips and interfacing to a PIC using PicBasic Pro 2.50 or similar.

Any advice / help Welcome

BR
Andy

aerostar
- 9th June 2014, 06:52
Google is your Friend !!! Link to stamp demo on Parallex site http://www.parallax.com/downloads/compass-module-example-basic-stamp-2-source-code

longpole001
- 9th June 2014, 06:53
just some google search results
http://www.protonbasic.co.uk/showthread.php/71398-trying-to-get-a-HMC5883L-compass-working

andybarrett1
- 10th June 2014, 22:22
Thank you for help both...

I think will just buy a couple and have a play

Buying 2.... As first one will go pop :)

BR Andy

visnja30
- 24th December 2014, 13:56
Hi,

is any body try the code from parallax site and get good results.I connect HMC5883L module to PIC18f452 and 2x16LCD display and I can read the RAW values.If I turn module RAW values are changing , but the value oh azimuth and degree dont work.

andybarrett1
- 25th December 2014, 21:38
Hi,

is any body try the code from parallax site and get good results.I connect HMC5883L module to PIC18f452 and 2x16LCD display and I can read the RAW values.If I turn module RAW values are changing , but the value oh azimuth and degree dont work.

Any chance of sharing code.... We can see what might be happening ??

BR
Andy

visnja30
- 29th December 2014, 20:37
Hi,
here is code with I test the MHC5883L chip.
I can get some raw readings but I dont now are they correct.Range of readings are from 64000 to 1000.when I turn the module reading are change.


' HMC5883L_Demo.bs2 - This is a Demo program for the HMC5883L Compass
' Module (PN: 29133). It displays the compass heading north, east, south and west
' clockwise from north.
'
' Author.... (C) John A. Williams
'
' {$STAMP BS2p}
' {$PBASIC 2.5}
' ================================================== ==========================
define OSC 4

'KONFIGURACIJA LCD DISPLEJA 2X16

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 0
DEFINE LCD_BITS 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 4
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 5
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 40
'SET UP PORTS
TRISA = %00111111 'port a je cijeli ulazni
TRISB = %00000000
TRISC = %11111111
TRISD = %00000000
TRISE = %1111
ADCON1 = 7 ' PORTA i PORTE su digitalni ISKLJUCI KOMPARATORE I ANALOGNE ULAZE
' -----[ Pins/Constants/Variables ]-------------------------------------------
SDA var PORTC.4
SCL VAR PORTC.3

WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation

MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
SCALEFACTOR CON 4081 'SCALEFACTOR = 65536 * (255/4095) = 4081
SCALEOFFSET CON 2048 'The output range of the HMC5883L is -2048 to 2047; therefore to get a 0 (LOWRANGE)to 4095 range
'to 4095 (HIGHRANGE) range 2048 must be added to the sensor value.
ATNFACTOR CON 127 'the ATN function input range is -127 TO 127. In order to get the positive scaled range of
'0 to 255 into the range of -127 to 127, 127 must be subtracted.
LOWRANGE CON 0 'see SCALEOFFSET
HIGHRANGE CON 4095 'see SCALEOFFSET

X VAR Word 'x sensor measured value
Y VAR Word 'y sensor measured value
Z VAR Word 'z sensor measured value
brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
azimuth VAR Word 'value calculated using X ATN -Y
degr=0





PAUSE 500
LCDOUT $FE,$01'clear DISPLAY
LCDOUT $FE,$01,"test "
PAUSE 500
LCDOUT $FE,$01'clear DISPLAY




' -----[ Main Routine ]-------------------------------------------------------

PAUSE 10
I2Cwrite SDA,SCL, $3c, $00, [$70] '(8-average, 15 Hz default, normal measurement)
I2Cwrite SDA,SCL, $3c, $01, [$A0] ; $00 hoogste gain setting
I2CWRITE SDA,SCL,WRITE_DATA,MODE, [cont_Mode] ' Send continuous output command

main:
LCDOUT $FE,$01'BRISI DISPLAY
GOSUB GetRawReading ' Get RAW Compass reading

'RAW X,Y,Z data...

lCDOUT $FE,$80, "X= " , sdec x
LCDOUT $FE,$80+8, "Y= ", sdec y
LCDOUT $FE,$C0, "Z= ", sdec z


'Calculate Azimuth

GOSUB GetAzimuth

brads = azimuth 'get angle
degr = brads */ 361 'convert to degrees

LCDOUT $FE,$80,"Degree " , sdec degr

pause 500
goto main

' -----[ Subroutines ]--------------------------------------------------------

GetRawReading: 'Compass module subroutine


PAUSE 400 'Wait for new data to become available


I2CREAD SDA,SCL, READ_DATA, X_MSB, [X.HIGHBYTE] 'Read the data starting at x_msb 3
I2CREAD SDA,SCL, READ_DATA ,X_LSB, [X.LOWBYTE]

I2CREAD SDA,SCL, READ_DATA, Z_MSB, [Z.HIGHBYTE]
I2CREAD SDA,SCL, READ_DATA ,Z_LSB, [Z.LOWBYTE]

I2CREAD SDA,SCL, READ_DATA, Y_MSB, [Y.HIGHBYTE]
I2CREAD SDA,SCL, READ_DATA ,Y_LSB, [Y.LOWBYTE]

RETURN

GetAzimuth:
'The output range of the HMC5883L is -2048 to 2047 and the input range of the ATN function
'is -127 to 127. I used the method to scale the output to the input discribed in Parallax's Smart
'Sensors Student Guide v1 starting on page 76.
'SCALEFACTOR = 65536 * (255/4095) = 4081
'SCALEOFFSET = 2048
'ATNFACTOR = 127
'LOWRANGE = 0
'HIGRANGE = 4095 (2048 + 2047 = 4095)

x = x + SCALEOFFSET
x = (x MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

y = y + SCALEOFFSET
y = (y MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR


azimuth = x ATN -y
LCDOUT $FE,$c0,"azimuth " , DEC azimuth

RETURN

richard
- 30th December 2014, 09:26
am I wrong or would right shifting the reading 4 give the same answer without all the math
x var byte
reading var word
x= reading>>4

HenrikOlsson
- 30th December 2014, 10:26
Hi,

Shooting from the hip a bit here....

Since the ATN expects 8bit two's complement values I'm not sure it's going to work when you give it your x and y variables since they are both 16bit variables - even if the values in them are in +/-127 range. Ah, never mind, it probably will since the low byte of the word will look identical anyway....

Richard,
You can't simply shift a two's complement number like that, you'll drop the sign.
You need to remember the sign, shift the abs value and restore the sign

Sign VAR BIT
Reading VAR WORD
x VAR BYTE

Sign = Reading.15
x = ABS(Reading) >> 4
If Sign THEN x = -x


/Henrik.

richard
- 30th December 2014, 10:38
it works on paper , i'm curious to compile it and see what happens , i'm feeling a cast from word to byte and only a 4 bit r-shift might allow the loss of the sign bit to be ignorable . if it works it saves a lot of steps
I would christen it as quick and dirty code

HenrikOlsson
- 30th December 2014, 11:05
Hi,
You're quite right Richard!
It works provided that x in this case IS declared as a byte (which it was in your code of course)

x = Reading >> 4
HSEROUT["Reading: ", SDEC Reading, " X: ", SDEC x,10,13]


Reading: -2048 X: -128
Reading: 2047 X: 127
Reading: -100 X: -7
Reading: 100 X: 6
If x is declared as a WORD then it fails:

Reading: -2048 X: 3968
Reading: 2047 X: 127
Reading: -100 X: 4089
Reading: 100 X: 6


/Henrik.

richard
- 30th December 2014, 11:36
thanks for confirming that henrik ,saves me the trouble .
I worked that out with the windows7 calculator (in programmer mode) it makes it easy to visualise some solutions , another feature sadly lacking in windoze 8.1
correction
not lacking in wdoze8 just hard to find like most of anything that's useful

andybarrett1
- 30th December 2014, 14:24
Hi

I am experriment with this code... more or less same setup as Visnga30 difference being I am using a 16F818..

I can understand the raw numbers OK X.Y and Z... But I feel something is wrong in the Azimuth Calcs... All I am seeing in debug is 160 for Azimuth and 255 for degr...

Ultimatly I need it to show Degrees of compass (0 to 360) this would be degr ?

Help appreciated .

Andy

Just noticed thats what OP was saying!

visnja30
- 30th December 2014, 18:13
Dear andybarrett1 do you managed to solve the problems with code? Do you managed to show the correct angle and degrees.
Are you willing to share your code with us?

andybarrett1
- 30th December 2014, 18:20
Dear andybarrett1 do you managed to solve the problems with code? Do you managed to show the correct angle and degrees.
Are you willing to share your code with us?

Hi
I wish I had got it working.... I am working on what the others posted. But at the moment not working.

It is certainly to do with the ATN function.

BR
Andy

andybarrett1
- 30th December 2014, 21:52
Hi Richard

In short am I right in thinking if I declare :-

x var byte
readingx var word

Then Substitute :-

x = x + SCALEOFFSET
x = (x MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

With :-

x = readingx >> 4

The ATN Calculation might work ??

I am away from my desk at moment but have been struggling with this for a whilst..... :-(

BR
Andy

richard
- 30th December 2014, 22:27
you can do a similar thing with y axis too ,
my routine will give the same result as the scale offset method its just much quicker and simpler.

don't forget the ATN result is in radians so deg = atnresult*360/256

I suspect that without using floats all round for these calcs the resulting resolution may be a little disappointing , but its worth a look

andybarrett1
- 31st December 2014, 10:44
Thank you for reading

Hi Have tried suggestions...

But now the I2CRead command is failing on on the HIGHBYE and LOWBYTE locations, I think it due to the X declare beng a Byte now not a Word.

My solution was to just use the MSB part and comment out the LSB putting the result into X.

This compiled OK but raw numbers refuse to move.... \i guess it needs the whole word.

HELP !!

BR
Andy

richard
- 31st December 2014, 10:54
But now the I2CRead command is failing on on the HIGHBYE and LOWBYTE locations, I think it due to the X declare beng a Byte now not a Word
the i2c read uses the word var readingx the byte var x is the "scaled" result from that reading

if you can't work that out post your code so we can see what your doing {in code tags }

andybarrett1
- 31st December 2014, 11:17
Hi Richard

Thank you for reply... Here is code to date.... With most recent error.


'************************************************* ***************
'* Name : COMPASS_818.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 24/08/2014 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************



' LCD should be connected as follows:
' LCD PIC
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K (10k)pullup resistor to 5 volts)
' E PortB.3
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 5K potentiometer (or ground)
' DB0-3 No connect





adcon1 = 7 ' Turns Analogs off

DEFINE OSC 12 'Set oscillator in MHz
'OSCCON = $70
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 6
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 7

' -----[ Pins/Constants/Variables ]-------------------------------------------
SDA var portb.1 'transceives to/from SDA
SCL var portb.4 'sends clock pulses

WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation

MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
SCALEFACTOR CON 4081 'SCALEFACTOR = 65536 * (255/4095) = 4081
SCALEOFFSET CON 2048 'The output range of the HMC5883L is -2048 to 2047; therefore to get a 0 (LOWRANGE)to 4095 range
'to 4095 (HIGHRANGE) range 2048 must be added to the sensor value.
ATNFACTOR CON 127 'the ATN function input range is -127 TO 127. In order to get the positive scaled range of
'0 to 255 into the range of -127 to 127, 127 must be subtracted.
LOWRANGE CON 0 'see SCALEOFFSET
HIGHRANGE CON 4095 'see SCALEOFFSET

X VAR byte 'x sensor measured value
Y VAR byte 'y sensor measured value
Z VAR byte 'z sensor measured value
READX VAR WORD
READY VAR WORD
READZ VAR WORD

brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
azimuth VAR Word 'value calculated using X ATN -Y


' -----[ Main Routine ]-------------------------------------------------------

PAUSE 500 ' Give sensor needed power up time

I2CWRITE SDA,SCL,WRITE_DATA,MODE,[Cont_Mode] ' Send continuous output command

DO

GOSUB GetRawReading ' Get RAW Compass reading

'RAW X,Y,Z data...


Lcdout $fe, 1 ' Clear LCD screen
Lcdout "X=",SDEC X ," Y=",SDEC Y
Lcdout $fe, $C0, "Z=",SDEC Z


'DEBUG HOME, "RAW X,Y,Z", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR
'DEBUG "Z = ",11, SDEC z, CR ' Print angle
'DEBUG CR

'Calculate Azimuth

GOSUB GetAzimuth

'Calculated Heading in Degrees

brads = azimuth 'get angle
degr = brads */ 361 'convert to degrees

'DEBUG CR
'DEBUG "Heading in NORTH, EAST, SOUTH, and WEST clockwise from NORTH:", CLREOL, CR, CR
'DEBUG "Degree " ,11, SDEC degr, CR 'display degrees
GOSUB GetHeading

LOOP


' -----[ Subroutines ]--------------------------------------------------------

GetRawReading: 'Compass module subroutine


PAUSE 400 'Wait for new data to become available


I2CREAD SDA,SCL,READ_DATA, X_MSB,[X.HIGHBYTE] 'Read the data starting at x_msb 3


I2CREAD SDA,SCL,READ_DATA ,X_LSB,[X.lowBYTE]

'Do the same for Z and Y:

I2CREAD SDA,SCL,READ_DATA, Z_MSB,[Z.HIGHBYTE]


I2CREAD SDA,SCL,READ_DATA ,Z_LSB,[Z.lowBYTE]



I2CREAD SDA,SCL,READ_DATA, Y_MSB,[Y.HIGHBYTE]


I2CREAD SDA,SCL,READ_DATA ,Y_LSB,[Y.lowBYTE]

RETURN

GetAzimuth:
'The output range of the HMC5883L is -2048 to 2047 and the input range of the ATN function
'is -127 to 127. I used the method to scale the output to the input discribed in Parallax's Smart
'Sensors Student Guide v1 starting on page 76.
'SCALEFACTOR = 65536 * (255/4095) = 4081
'SCALEOFFSET = 2048
'ATNFACTOR = 127
'LOWRANGE = 0
'HIGRANGE = 4095 (2048 + 2047 = 4095)

'x = x + SCALEOFFSET
'x = (x MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

'y = y + SCALEOFFSET
'y = (y MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

x = readx >>4
Y = readY >>4
'Z = readZ >>4

'DEBUG "SCALED X,Y", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR

azimuth = x ATN -y



'DEBUG "Azimuth ",11, SDEC azimuth, CR ' display scaled azimuth
'DEBUG "COS Azimuth ",11, SDEC COS azimuth, CR ' display scaled cos azimuth
RETURN

GetHeading:
'Gives a heading in North, South, East and West.

IF degr = 90 THEN
'DEBUG "NORTH"
'DEBUG CLREOL
ENDIF


IF degr = 0 THEN
'DEBUG "EAST"
'DEBUG CLREOL
ENDIF


IF degr = 270 THEN
'DEBUG "SOUTH"
'DEBUG CLREOL
ENDIF


IF degr = 180 THEN
'DEBUG "WEST"
'DEBUG CLREOL
ENDIF

RETURN

Excuse my issues I am still learning....

BR
Andy

richard
- 31st December 2014, 11:45
this should fix the i2c errors

'************************************************* ***************
'* Name : COMPASS_818.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 24/08/2014 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

' LCD should be connected as follows:
' LCD PIC
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K (10k)pullup resistor to 5 volts)
' E PortB.3
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 5K potentiometer (or ground)
' DB0-3 No connect


adcon1 = 7 ' Turns Analogs off

DEFINE OSC 12 'Set oscillator in MHz
'OSCCON = $70
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 6
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 7
' -----[ Pins/Constants/Variables ]-------------------------------------------
SDA var portb.1 'transceives to/from SDA
SCL var portb.4 'sends clock pulses
WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation
MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
'SCALEFACTOR CON 4081 'SCALEFACTOR = 65536 * (255/4095) = 4081
'SCALEOFFSET CON 2048 'The output range of the HMC5883L is -2048 to 2047; therefore to get a 0 (LOWRANGE)to 4095 range
'to 4095 (HIGHRANGE) range 2048 must be added to the sensor value.
'ATNFACTOR CON 127 'the ATN function input range is -127 TO 127. In order to get the positive scaled range of
'0 to 255 into the range of -127 to 127, 127 must be subtracted.
'LOWRANGE CON 0 'see SCALEOFFSET
'HIGHRANGE CON 4095 'see SCALEOFFSET
X VAR byte 'x sensor measured value
Y VAR byte 'y sensor measured value
Z VAR byte 'z sensor measured value
READX VAR WORD
READY VAR WORD
READZ VAR WORD
brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
azimuth VAR Word 'value calculated using X ATN -Y

' -----[ Main Routine ]-------------------------------------------------------
PAUSE 500 ' Give sensor needed power up time
I2CWRITE SDA,SCL,WRITE_DATA,MODE,[Cont_Mode] ' Send continuous output command
DO
GOSUB GetRawReading ' Get RAW Compass reading
'RAW X,Y,Z data...

Lcdout $fe, 1 ' Clear LCD screen
Lcdout "X=",SDEC X ," Y=",SDEC Y
Lcdout $fe, $C0, "Z=",SDEC Z


'DEBUG HOME, "RAW READX,READY,READZ", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR
'DEBUG "Z = ",11, SDEC z, CR ' Print angle
'DEBUG CR
'Calculate Azimuth
GOSUB GetAzimuth
'Calculated Heading in Degrees
brads = azimuth 'get angle
degr = brads */ 361 'convert to degrees

'DEBUG CR
'DEBUG "Heading in NORTH, EAST, SOUTH, and WEST clockwise from NORTH:", CLREOL, CR, CR
'DEBUG "Degree " ,11, SDEC degr, CR 'display degrees
GOSUB GetHeading
LOOP

' -----[ Subroutines ]--------------------------------------------------------
GetRawReading: 'Compass module subroutine

PAUSE 400 'Wait for new data to become available

I2CREAD SDA,SCL,READ_DATA, X_MSB,[READX.HIGHBYTE] 'Read the data starting at x_msb 3

I2CREAD SDA,SCL,READ_DATA ,X_LSB,[READX.lowBYTE]
'Do the same for Z and Y:
I2CREAD SDA,SCL,READ_DATA, Z_MSB,[READZ.HIGHBYTE]

I2CREAD SDA,SCL,READ_DATA ,Z_LSB,[READZ.lowBYTE]

I2CREAD SDA,SCL,READ_DATA, Y_MSB,[READY.HIGHBYTE]

I2CREAD SDA,SCL,READ_DATA ,Y_LSB,[READY.lowBYTE]
RETURN
GetAzimuth:
'The output range of the HMC5883L is -2048 to 2047 and the input range of the ATN function
'is -127 to 127. I used the method to scale the output to the input discribed in Parallax's Smart
'Sensors Student Guide v1 starting on page 76.
'SCALEFACTOR = 65536 * (255/4095) = 4081
'SCALEOFFSET = 2048
'ATNFACTOR = 127
'LOWRANGE = 0
'HIGRANGE = 4095 (2048 + 2047 = 4095)
'x = x + SCALEOFFSET
'x = (x MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR
'y = y + SCALEOFFSET
'y = (y MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

x = readx >>4
Y = readY >>4
'Z = readZ >>4
'DEBUG "SCALED X,Y", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR
azimuth = x ATN -y


'DEBUG "Azimuth ",11, SDEC azimuth, CR ' display scaled azimuth
'DEBUG "COS Azimuth ",11, SDEC COS azimuth, CR ' display scaled cos azimuth
RETURN
GetHeading:
'Gives a heading in North, South, East and West.
IF degr = 90 THEN
'DEBUG "NORTH"
'DEBUG CLREOL
ENDIF

IF degr = 0 THEN
'DEBUG "EAST"
'DEBUG CLREOL
ENDIF

IF degr = 270 THEN
'DEBUG "SOUTH"
'DEBUG CLREOL
ENDIF

IF degr = 180 THEN
'DEBUG "WEST"
'DEBUG CLREOL
ENDIF
RETURN

richard
- 31st December 2014, 11:51
to get the azimuth result in degrees

azimuth = ( x ATN -y) */ 360

towlerg
- 31st December 2014, 14:28
Not important at this point but you have East and North reversed.

I'm try to do the same thing with HMC5983, I can read data which seems reasonable ie very different and repeatable for the four directions, but I can't seem to produce a heading less than about 180.

Typical raw numbers




x

y



N

215

-176



E

-76

7



S

-265

-287



W

-12

-474




Seems like an awful lot of negative numbers? I wonder if I've killed it?

George

andybarrett1
- 31st December 2014, 17:11
Thank You....

Will try ASAP...

Have a great New Year.... Or .... Has it happened already !

BR
Andy

andybarrett1
- 31st December 2014, 19:48
Hi..

Some success.... with code as below:-

Am I correct in assuming the compass is in the X-Y Axis ..., Z is purely for Azimuth?

I think something is wrong with Azimuth and Degree calcs as Degree is only moving between 0-256...

The good news is both of them are moving now :-)

I really am wishing I paid more attention to maths now at school... Being a hardware engineer I can blag my way though it... Dabbling with S/W it not so easy...

Any pointers welcome.... Happy New year to All

BR
Andy




'************************************************* ***************
'* Name : COMPASS_818.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 24/08/2014 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************



' LCD should be connected as follows:
' LCD PIC
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K (10k)pullup resistor to 5 volts)
' E PortB.3
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 5K potentiometer (or ground)
' DB0-3 No connect





adcon1 = 7 ' Turns Analogs off

DEFINE OSC 12 'Set oscillator in MHz
'OSCCON = $70
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 6
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 7

' -----[ Pins/Constants/Variables ]-------------------------------------------
SDA var portb.1 'transceives to/from SDA
SCL var portb.4 'sends clock pulses

WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation

MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
SCALEFACTOR CON 4081 'SCALEFACTOR = 65536 * (255/4095) = 4081
SCALEOFFSET CON 2048 'The output range of the HMC5883L is -2048 to 2047; therefore to get a 0 (LOWRANGE)to 4095 range
'to 4095 (HIGHRANGE) range 2048 must be added to the sensor value.
ATNFACTOR CON 127 'the ATN function input range is -127 TO 127. In order to get the positive scaled range of
'0 to 255 into the range of -127 to 127, 127 must be subtracted.
LOWRANGE CON 0 'see SCALEOFFSET
HIGHRANGE CON 4095 'see SCALEOFFSET

X VAR byte 'x sensor measured value
Y VAR byte 'y sensor measured value
Z VAR byte 'z sensor measured value
READX VAR WORD
READY VAR WORD
READZ VAR WORD

brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
azimuth VAR Word 'value calculated using X ATN -Y


' -----[ Main Routine ]-------------------------------------------------------

PAUSE 500 ' Give sensor needed power up time

I2CWRITE SDA,SCL,WRITE_DATA,MODE,[Cont_Mode] ' Send continuous output command

DO

GOSUB GetRawReading ' Get RAW Compass reading

'RAW X,Y,Z data...


'Lcdout $fe, 1 ' Clear LCD screen
'Lcdout "X=",SDEC READX ," Y=",SDEC READY
'Lcdout $fe, $C0, "Z=",SDEC READZ


'DEBUG HOME, "RAW X,Y,Z", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR
'DEBUG "Z = ",11, SDEC z, CR ' Print angle
'DEBUG CR

'Calculate Azimuth

GOSUB GetAzimuth

'Calculated Heading in Degrees

brads = azimuth 'get angle
'degr = brads */ 361 'convert to degrees
degr = brads*360/256

Lcdout $fe, $C0, "Degrees =",SDEC degr


'DEBUG CR
'DEBUG "Heading in NORTH, EAST, SOUTH, and WEST clockwise from NORTH:", CLREOL, CR, CR
'DEBUG "Degree " ,11, SDEC degr, CR 'display degrees
GOSUB GetHeading

LOOP


' -----[ Subroutines ]--------------------------------------------------------

GetRawReading: 'Compass module subroutine


PAUSE 400 'Wait for new data to become available


I2CREAD SDA,SCL,READ_DATA, X_MSB,[READX.HIGHBYTE] 'Read the data starting at x_msb 3


I2CREAD SDA,SCL,READ_DATA ,X_LSB,[READX.lowBYTE]

'Do the same for Z and Y:

I2CREAD SDA,SCL,READ_DATA, Z_MSB,[READZ.HIGHBYTE]


I2CREAD SDA,SCL,READ_DATA ,Z_LSB,[READZ.lowBYTE]



I2CREAD SDA,SCL,READ_DATA, Y_MSB,[READY.HIGHBYTE]


I2CREAD SDA,SCL,READ_DATA ,Y_LSB,[READY.lowBYTE]

RETURN

GetAzimuth:
'The output range of the HMC5883L is -2048 to 2047 and the input range of the ATN function
'is -127 to 127. I used the method to scale the output to the input discribed in Parallax's Smart
'Sensors Student Guide v1 starting on page 76.
'SCALEFACTOR = 65536 * (255/4095) = 4081
'SCALEOFFSET = 2048
'ATNFACTOR = 127
'LOWRANGE = 0
'HIGRANGE = 4095 (2048 + 2047 = 4095)

'x = x + SCALEOFFSET
'x = (x MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

'y = y + SCALEOFFSET
'y = (y MIN LOWRANGE MAX HIGHRANGE) ** SCALEFACTOR - ATNFACTOR

x = readx >>4
Y = readY >>4
Z = readZ >>4

'DEBUG "SCALED X,Y", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR

'azimuth = x ATN -y
azimuth = ( x ATN -y) */ 360

Lcdout $fe, 1 ' Clear LCD screen
Lcdout "Azimuth=",SDEC azimuth

'DEBUG "Azimuth ",11, SDEC azimuth, CR ' display scaled azimuth
'DEBUG "COS Azimuth ",11, SDEC COS azimuth, CR ' display scaled cos azimuth
RETURN

GetHeading:
'Gives a heading in North, South, East and West.

IF degr = 90 THEN

'Lcdout "North"
'DEBUG "NORTH"
'DEBUG CLREOL
ENDIF


IF degr = 0 THEN

'Lcdout "East"

'DEBUG "EAST"
'DEBUG CLREOL
ENDIF


IF degr = 270 THEN

'Lcdout "South"

'DEBUG "SOUTH"
'DEBUG CLREOL
ENDIF


IF degr = 180 THEN

'Lcdout "West"

'DEBUG "WEST"
'DEBUG CLREOL
ENDIF

RETURN

richard
- 31st December 2014, 21:25
your degree calc is incorrect


degr = brads*360/256 this will overflow a word var causing errors


degr = brads */ 360

is the better way

andybarrett1
- 31st December 2014, 21:41
Hi Richard.

Still reading between 100 to 900 on degrees.

Close to the River Mersey in Liverpool here fireworks are all ready noisy

Thank you for help ....

richard
- 31st December 2014, 22:13
looks like you are converting azimuth to degrees twice
once here

'Calculate Azimuth

GOSUB GetAzimuth

'Calculated Heading in Degrees

brads = azimuth 'get angle
'degr = brads */ 361 'convert to degrees
degr = brads*360/256 and this is still wrong needs to be degr = brads */ 360


Lcdout $fe, $C0, "Degrees =",SDEC degr


and once here



x = readx >>4
Y = readY >>4
Z = readZ >>4

'DEBUG "SCALED X,Y", CR
'DEBUG "X = ",11, SDEC x, CR
'DEBUG "Y = ",11, SDEC y, CR

'azimuth = x ATN -y
azimuth = ( x ATN -y) */ 360


surly once is enough


azimuth = x ATN -y

andybarrett1
- 31st December 2014, 22:43
I am now more confused than I was before....

Aximuth is the angle between ground and the Z-Plane

Degree is the heading (ie Compass Bearing)

I am most interested in getting the display to show degrees on North, East, West .... Whatever...


Confused...

Andy

richard
- 31st December 2014, 23:03
your prg as provided does nothing with the "Z" reading

the term you have designated as azimuth is derived from azimuth = x ATN -y ie an " x " and a " y " reading , these readings are a vector (rectangular co-ordinates) the ATAN function gives you the (polar ) direction of the vector in radians where 0-255 corresponds to 0-360 degrees , so to get a degree reading the
degr = brads */ 360 scales the atn result to degrees

z is right out and your variable names aren't strictly meaningful

andybarrett1
- 31st December 2014, 23:14
Hi

Z just got commented out by accident... My Bad.. It back now and was anyway !

Sorry again my misunderstanding if the ATN result is radians 0 to 255 the equation as I remember is:-

Degree = radians x 180 over PI

You see my confusion ?

richard
- 31st December 2014, 23:36
from the pbp manual

ATN returns the 8-bit arctangent of 2 two's-complement 8-bit values. If a byte is
greater than 127 (high bit set), it is treated as a negative value. The arctangent
returned is in binary radians, 0 to 255, representing a range of 0 to 359 degrees.

andybarrett1
- 1st January 2015, 00:02
Hi Richard...

Will tidy code and play more later ...today !!

Thanks for help

I non too good with S/W

andybarrett1
- 3rd January 2015, 15:23
Hi

Have tided code.... And it does seem to work better now. But Degrees are reversed (360 to 0) Clockwise. Or am I reading the sensor upside down?

Azimuth is renamed Radians... the resulting calculation now used to give degrees.

Z... is not used at all... Maybe I can add or subtract the locale degree error (Unknown at time of writing) into code once degrees working the right way round.

Latest code show below.... Bear in mind I am not a software guy so any suggestions of further advice welcome.


'************************************************* ***************
'* Name : COMPASS_818.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 24/08/2014 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************



' LCD should be connected as follows:
' LCD PIC
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K (10k)pullup resistor to 5 volts)
' E PortB.3
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 5K potentiometer (or ground)
' DB0-3 No connect

adcon1 = 7 ' Turns Analogs off
'DEFINE OSC 12 'Set oscillator in MHz
OSCCON = $70
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 6
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 7

' -----[ Pins/Constants/Variables ]-------------------------------------------
SDA var portb.1 'transceives to/from SDA
SCL var portb.4 'sends clock pulses

WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation

MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
X VAR byte 'x sensor measured value
Y VAR byte 'y sensor measured value
Z VAR byte 'z sensor measured value
READX VAR WORD
READY VAR WORD
READZ VAR WORD

brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
Radians VAR Word 'value calculated using X ATN -Y


' -----[ Main Routine ]-------------------------------------------------------

PAUSE 500 ' Give sensor needed power up time

I2CWRITE SDA,SCL,WRITE_DATA,MODE,[Cont_Mode] ' Send continuous output command

DO

GOSUB GetRawReading ' Get RAW Compass reading

'RAW READX,READY,READZ data...

'Lcdout $fe, 1 ' Clear LCD screen
'Lcdout "X=",SDEC READX ," Y=",SDEC READY
'Lcdout $fe, $C0, "Z=",SDEC READZ

'Calculate Azimuth

GOSUB GetRadians

'Calculated Heading in Degrees
brads = Radians 'get angle
degr = brads */360 'convert to degrees


Lcdout $fe, $C0, "Degrees =",SDEC degr

GOSUB GetHeading

LOOP
' -----[ Subroutines ]--------------------------------------------------------

GetRawReading: 'Compass module subroutine

PAUSE 400 'Wait for new data to become available

I2CREAD SDA,SCL,READ_DATA, X_MSB,[READX.HIGHBYTE] 'Read the data starting at x_msb 3
I2CREAD SDA,SCL,READ_DATA ,X_LSB,[READX.lowBYTE]

I2CREAD SDA,SCL,READ_DATA, Z_MSB,[READZ.HIGHBYTE]
I2CREAD SDA,SCL,READ_DATA ,Z_LSB,[READZ.lowBYTE]

I2CREAD SDA,SCL,READ_DATA, Y_MSB,[READY.HIGHBYTE]
I2CREAD SDA,SCL,READ_DATA ,Y_LSB,[READY.lowBYTE]

RETURN

GetRadians:
'The output range of the HMC5883L is -2048 to 2047 and the input range of the ATN function
'is -127 to 127.

x = readx >>4
Y = readY >>4
Z = readZ >>4

'Lcdout $fe, 1 ' Clear LCD screen
'Lcdout "X=",SDEC X ," Y=",SDEC Y
'Lcdout $fe, $C0, "Z=",SDEC Z

Radians = x ATN -y

Lcdout $fe, 1 ' Clear LCD screen
Lcdout "Radians =",SDEC Radians

RETURN

GetHeading:
'Gives a heading in North, South, East and West.

IF degr = 90 THEN
'Lcdout "North"
ENDIF

IF degr = 0 THEN
'Lcdout "East"
ENDIF

IF degr = 270 THEN
'Lcdout "South"
ENDIF

IF degr = 180 THEN
'Lcdout "West"
ENDIF

RETURN

towlerg
- 3rd January 2015, 15:56
Andy, you still have North and East reversed and South and West reversed as well, North is 0, East is 90, South is 180 and West is 270.
http://commons.wikimedia.org/wiki/File:Compass_Card.png Although I guess you'd be better off saying greater than 315 or less than 45 it's North.

George

BTW I'm trying and failing to get a 5983 (supposedly updated version) working with little or no success, I think I killed it!

andybarrett1
- 3rd January 2015, 16:10
Hi George

I think the reversal on the last bit of the code is to do with headings and angles etc.. So not all that worried.
Is the 5983 the same layout as mine... If so will the code not crow bar into it ?

Am also not to sure about gain settings etc.... Have left mine at default.

BR
Andy

towlerg
- 3rd January 2015, 23:43
My understanding (perhaps wrong) is that 5983 is an improved version of 5883. It is temperature compensated and will output at a greater rate appearently. I'm working on the assumption that it is software compatible - but you know what they say about assume.

George

towlerg
- 4th January 2015, 00:17
I can't edit my last post and I wanted to add

My understanding is that you want the gain as high as possible without saturating. X,Y and Z values are in the range -2048 to 2047 so I guess you're looking for something like -1500 to 1500.

I see you don't allow for declination, the difference between magnetic and true north. You can get your local declination from http://www.magnetic-declination.com/

I'm assuming the the X coordinate points North, although now I think of it I can't see why. the only reference I can find is "Arrow indicates direction of magnetic field that generates a positive output reading in Normal Measurement configuration" take from that what you will.

George

andybarrett1
- 4th January 2015, 09:25
Hi George

I agree with gain... Reading the datasheet seems to be way to go ... If it over saturates you get the -4096 figure.

I also am assuming that X is north... Certainly shows like that at in most of places I have looked.

Y seems to be either West (left) or East (right).... depending on what you look at... I did find a useful Honeywell document yesterday, will post a little later on.

There is certainly a shortage of info around as to how to use these devices with PicBasic

BR
Andy

towlerg
- 4th January 2015, 16:33
Are you using one of the break-out boards, GY0281 or GY282? Could you post a circuit diagram? The two break-out boards above both have 3.3v regulators on them, I'm curious as to what Vcc you run the PIC at and if you use level changers. If X is North Y must be West. George

andybarrett1
- 4th January 2015, 19:39
Hi George

This is the exact one I am using ... The ebay link has Pics and Circuit... I am running it at 5v.. As the LCD needs 5v

http://www.ebay.co.uk/itm/111214140844?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT

BR
Andy

towlerg
- 5th January 2015, 00:06
So you are connecting the clock and data from the PIC directly to the break-out board pins? Do you have pull-ups? if so to 5 or 3.3?

george

andybarrett1
- 5th January 2015, 14:33
Hi George

I wondered about this

I have measured 2K2 to the 5v rail on the breakout board.

The Ic2 link seems to run OK so happy with that.

My issue remains to be the conversion from radians to degrees.

richard
- 22nd January 2015, 01:33
I bought one to play with

after looking at the raw data I came up with this , works ok if device is held level , tilt compensation is elusive at this stage




'************************************************* ***************
'* Name : hmc5883l.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2011 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 29/04/2011 *
'* Version : *
'* Notes : *
'* : 12f1822
'* :
'
'************************************************* ***************
#CONFIG
cfg1 = _FOSC_INTOSC
cfg1&= _WDTE_ON
cfg1&= _PWRTE_OFF
cfg1&= _MCLRE_ON
cfg1&= _CP_OFF
cfg1&= _CPD_OFF
cfg1&= _BOREN_ON
cfg1&= _CLKOUTEN_OFF
cfg1&= _IESO_ON
cfg1&= _FCMEN_ON
__CONFIG _CONFIG1, cfg1
cfg2 = _WRT_OFF
cfg2&= _PLLEN_OFF
cfg2&= _STVREN_ON
cfg2&= _BORV_19
cfg2&= _LVP_OFF
__CONFIG _CONFIG2, cfg2
#ENDCONFIG


osccon=$6A '4 mhz
anselA=0 'dig i/o

trisA=1110




pause 2000
serout2 porta.0,84, ["ready",13,10]
lata.0=1


SDA var porta.2 'transceives to/from SDA
SCL var porta.4 'sends clock pulses
WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation
MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
X VAR byte 'x sensor measured value
Y VAR byte 'y sensor measured value
Z VAR byte 'z sensor measured value
READX VAR WORD
READY VAR WORD
READZ VAR WORD
brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
Radians VAR Word 'value calculated using X ATN -Y

' -----[ Main Routine ]-------------------------------------------------------
PAUSE 50 ' Give sensor needed power up time
I2CWRITE SDA,SCL,WRITE_DATA,MODE,[0,1,Cont_Mode] ' Send continuous output command
PAUSE 10
DO
GOSUB GetRawReading ' Get RAW Compass reading
serout2 porta.0,84, ["x ",SDEC x," y ",SDEC y ," z ",SDEC z,13,10]

brads = -x ATN -y ;
degr = brads */360 'convert to degrees
;serout2 porta.0,84, ["xy ",SDEC Radians ,","]
serout2 porta.0,84, ["xy ",DEC degr ,13,10]
brads = -x ATN -z ;
degr = brads */360 'convert to degrees
; serout2 porta.0,84, ["xz ",SDEC Radians ,","]
serout2 porta.0,84, ["xz ",DEC degr ,13,10]
brads = -y ATN -z
degr = brads */360 'convert to degrees
;serout2 porta.0,84, ["yz ",SDEC Radians ,","]
serout2 porta.0,84, ["yz ",DEC degr ,13,10]

PAUSE 2000
LOOP
' -----[ Subroutines ]--------------------------------------------------------
GetRawReading: 'Compass module subroutine
'Wait for new data to become available
I2CREAD SDA,SCL,READ_DATA, X_MSB,[READX,READZ,READY] 'Read the data starting at x_msb 3

x = readx >>2
Y = readY >>2
Z = readZ >>2
RETURN

andybarrett1
- 22nd January 2015, 10:16
Hi Richard

Had put this on the back burner for a whilst....

Will revisit it later... I see you have done a few things differently!

Thank you for Ideas. Andy

towlerg
- 22nd January 2015, 18:53
Hi Richard,

you need to add a 3-axis accelerometer to do tilt compensation, something like LSM303DLM.

George

richard
- 22nd January 2015, 22:25
turns out that the premise of using this chip alone as a compass is basically flawed. it can't do its own tilt compensation because the earths magnetic field is not necessarily parallel to the earth .
as George says an accelerometer needs to be added to compensate for tilt. (read, complicated math probably needs floats for any decent accuracy)

no wonder they are so cheap , not a total loss it makes a pretty sensitive 3 axis hall effect sensor , nice colour

towlerg
- 22nd January 2015, 22:55
Richard,

Not if your application will not be required to tilt or has some mechanical (gimbals) way to negate the problem.

George

andybarrett1
- 22nd January 2015, 23:04
Hi both

Yeah.... I put your code in Richard ... Does pretty much same as before... So I think I need find a better chip
Or use a real needle

Thank you again for ideas .... Appreciated !

gunayburak
- 2nd February 2015, 15:14
I bought one to play with

after looking at the raw data I came up with this , works ok if device is held level , tilt compensation is elusive at this stage




'************************************************* ***************
'* Name : hmc5883l.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2011 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 29/04/2011 *
'* Version : *
'* Notes : *
'* : 12f1822
'* :
'
'************************************************* ***************
#CONFIG
cfg1 = _FOSC_INTOSC
cfg1&= _WDTE_ON
cfg1&= _PWRTE_OFF
cfg1&= _MCLRE_ON
cfg1&= _CP_OFF
cfg1&= _CPD_OFF
cfg1&= _BOREN_ON
cfg1&= _CLKOUTEN_OFF
cfg1&= _IESO_ON
cfg1&= _FCMEN_ON
__CONFIG _CONFIG1, cfg1
cfg2 = _WRT_OFF
cfg2&= _PLLEN_OFF
cfg2&= _STVREN_ON
cfg2&= _BORV_19
cfg2&= _LVP_OFF
__CONFIG _CONFIG2, cfg2
#ENDCONFIG


osccon=$6A '4 mhz
anselA=0 'dig i/o

trisA=1110




pause 2000
serout2 porta.0,84, ["ready",13,10]
lata.0=1


SDA var porta.2 'transceives to/from SDA
SCL var porta.4 'sends clock pulses
WRITE_DATA CON $3C 'Used to perform a Write operation
READ_DATA CON $3D 'Used to perform a Read operation
MODE CON $02 'Read/Write Register, Selects the operating mode. Default = Single measurement
'Send $3C $02 $00 on power up to change to continuous measurement mode.
X_MSB CON $03 'Read Register, Output of X MSB 8-bit value.
X_LSB CON $04 'Read Register, Output of X LSB 8-bit value.
Z_MSB CON $05 'Read Register, Output of Z MSB 8-bit value.
Z_LSB CON $06 'Read Register, Output of Z LSB 8-bit value.
Y_MSB CON $07 'Read Register, Output of Y MSB 8-bit value.
Y_LSB CON $08 'Read Register, Output of Y LSB 8-bit value.
Cont_Mode CON $0
X VAR byte 'x sensor measured value
Y VAR byte 'y sensor measured value
Z VAR byte 'z sensor measured value
READX VAR WORD
READY VAR WORD
READZ VAR WORD
brads VAR Word 'angle in brads
degr VAR Word 'angle in degrees
Radians VAR Word 'value calculated using X ATN -Y

' -----[ Main Routine ]-------------------------------------------------------
PAUSE 50 ' Give sensor needed power up time
I2CWRITE SDA,SCL,WRITE_DATA,MODE,[0,1,Cont_Mode] ' Send continuous output command
PAUSE 10
DO
GOSUB GetRawReading ' Get RAW Compass reading
serout2 porta.0,84, ["x ",SDEC x," y ",SDEC y ," z ",SDEC z,13,10]

brads = -x ATN -y ;
degr = brads */360 'convert to degrees
;serout2 porta.0,84, ["xy ",SDEC Radians ,","]
serout2 porta.0,84, ["xy ",DEC degr ,13,10]
brads = -x ATN -z ;
degr = brads */360 'convert to degrees
; serout2 porta.0,84, ["xz ",SDEC Radians ,","]
serout2 porta.0,84, ["xz ",DEC degr ,13,10]
brads = -y ATN -z
degr = brads */360 'convert to degrees
;serout2 porta.0,84, ["yz ",SDEC Radians ,","]
serout2 porta.0,84, ["yz ",DEC degr ,13,10]

PAUSE 2000
LOOP
' -----[ Subroutines ]--------------------------------------------------------
GetRawReading: 'Compass module subroutine
'Wait for new data to become available
I2CREAD SDA,SCL,READ_DATA, X_MSB,[READX,READZ,READY] 'Read the data starting at x_msb 3

x = readx >>2
Y = readY >>2
Z = readZ >>2
RETURN


So according to your code , we get x , y , z raw readings as byte datas .... and xy xz yz calculations obtained using some trigonometry .. But what do those datas mean ? I think these xy xz yz readings are referring a direction but which one is what ? Does xy give me the magnetic north ? or is it xz or maybe yz ...

I'd be so happy if any of you guys could help me with that ...

Thanks ..

richard
- 2nd February 2015, 22:19
maybe this will help

http://www.starlino.com/imu_guide.html

gunayburak
- 3rd February 2015, 10:21
I still can't understand which vector shows me the magnetic north in this picture ... But as far as I read the datasheet of this IC , it mentions about a term called Hnorth which is the resultant force of X and Y vectors ... so which one is it then ? Is it XY calculation that shows me the north ?

richard
- 3rd February 2015, 10:54
if the device is held so that the xy plane is perfectly!!!! level then the xy angle is magnetic north (sort of). if the device is tilted then the xy angle needs to compensated for that tilt . the device alone cannot really be used as a compass . the device output is a 3d vector as drawn by the black line in my previous post, as you can see the result is relative to the devices orientation , if that is unknown (and it is without an external reference ) then its virtually impossible to ascertain a direction from its output. even a small tilt creates substantial error.
furthermore magnetic field lines are not parallel with the earths surface they tilt into the earth or up to the sky depending on location. not to mention magnetic inclination/deviation etc
basically the concept of using this chip as a compass is unworkable see post 47

richard
- 3rd February 2015, 11:06
I must add , the vector does not point north . it indicates the [ direction and magnitude ] of the magnet field relative to the device orientation.
the link I posted is for accelerometers but the math is the same . the big difference is that gravity always points to the centre of the planet so orientation can be established

gunayburak
- 3rd February 2015, 11:09
if the device is held so that the xy plane is perfectly!!!! level then the xy angle is magnetic north (sort of). if the device is tilted then the xy angle needs to compensated for that tilt . the device alone cannot really be used as a compass . the device output is a 3d vector as drawn by the black line in my previous post, as you can see the result is relative to the devices orientation , if that is unknown (and it is without an external reference ) then its virtually impossible to ascertain a direction from its output. even a small tilt creates substantial error.
furthermore magnetic field lines are not parallel with the earths surface they tilt into the earth or up to the sky depending on location. not to mention magnetic inclination/deviation etc
basically the concept of using this chip as a compass is unworkable see post 47

That was a nice a explanation Richard ... As you've previously said , we can at least use this IC to observe the pitch then ... For example I'm intending to read XZ or YZ to see the pitch angle for the control of an inverted pendulum ... I personally thought it's a low cost way of doing it compared to an encoder ... Bye the way .. For my module , should I keep it horizontally flat just like in the picture or upside down , does it matter ?

Here is my module

http://i.ebayimg.com/00/s/NjUwWDY1MA==/z/vpkAAOxyUgtTOmRY/$_35.JPG

richard
- 3rd February 2015, 11:27
For example I'm intending to read XZ or YZ to see the pitch angle for the control of an inverted pendulum ... I personally thought it's a low cost way of doing it compared to an encoder
not sure how effective that will be , it would probably need to be calibrated every time you relocate it (or maybe even rotate it) . don't forget its own orientation is its only reference point . an accelerometer might be more appropriate

gunayburak
- 3rd February 2015, 11:33
Well , Yeah actually I'm planning to calibrate it right before every operation with a quick push button click ... So that It can assume the present values as exact zero .. It's all about math I guess .... I'm also aware of that It won't be that accurate ... But I still wanna use it :) ... Thanks for your all prompt answers Richard ...

towlerg
- 3rd February 2015, 15:15
For example I'm intending to read XZ or YZ to see the pitch angle for the control of an inverted pendulum ... I personally thought it's a low cost way of doing it compared to an encoder

Surely what you need is an accelerometer, you know that the period is always the same, it just moves faster when first set in motion (I'm not totally sure that's correct, my knowledge of basic physics is pretty ragged). If that's correct, there will be a relationship between angle and acceleration. With calibration you should end up with a look up table of acceleration/angle. Of course you'll only need to generate the table once.

Also I cant imagine how you would orient the magnetometer to even hint at the angle.

BTW anyway, you couldn't use an encoder if you want the pendulum to be "true", pivot must be frictionless.

Sounds like an interesting project, have fun.

George