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
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
Google is your Friend !!! Link to stamp demo on Parallex site http://www.parallax.com/downloads/co...-2-source-code
just some google search results
http://www.protonbasic.co.uk/showthr...ompass-working
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
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.
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.
Code:' 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
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
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/Henrik.Code:Sign VAR BIT Reading VAR WORD x VAR BYTE Sign = Reading.15 x = ABS(Reading) >> 4 If Sign THEN x = -x
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
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)Code:x = Reading >> 4 HSEROUT["Reading: ", SDEC Reading, " X: ", SDEC x,10,13]If x is declared as a WORD then it fails:Code:Reading: -2048 X: -128 Reading: 2047 X: 127 Reading: -100 X: -7 Reading: 100 X: 6/Henrik.Code:Reading: -2048 X: 3968 Reading: 2047 X: 127 Reading: -100 X: 4089 Reading: 100 X: 6
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
Last edited by richard; - 30th December 2014 at 12:38.
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!
Last edited by andybarrett1; - 30th December 2014 at 15:37. Reason: Latter addition !
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 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
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
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
the i2c read uses the word var readingx the byte var x is the "scaled" result from that readingBut 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
if you can't work that out post your code so we can see what your doing {in code tags }
Last edited by richard; - 31st December 2014 at 11:57. Reason: edit
Hi Richard
Thank you for reply... Here is code to date.... With most recent error.
Excuse my issues I am still learning....Code:'**************************************************************** '* 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
BR
Andy
this should fix the i2c errors
Code:'**************************************************************** '* 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
to get the azimuth result in degrees
azimuth = ( x ATN -y) */ 360
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
Thank You....
Will try ASAP...
Have a great New Year.... Or .... Has it happened already !
BR
Andy
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
Code:'**************************************************************** '* 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
your degree calc is incorrect
this will overflow a word var causing errorsCode:degr = brads*360/256
is the better wayCode:degr = brads */ 360
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 ....
looks like you are converting azimuth to degrees twice
once here
and once hereCode:'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
surly once is enoughCode: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
Code:azimuth = x ATN -y
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
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
Last edited by richard; - 1st January 2015 at 00:10. Reason: typo its not vectors its a vector and removed the dual degree conversion again
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 ?
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.
Hi Richard...
Will tidy code and play more later ...today !!
Thanks for help
I non too good with S/W
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.
Code:'**************************************************************** '* 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
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!
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
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
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
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
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
Bookmarks