by John Schimmel

This PicBasic Pro code reads a Parallax HM55B Compass module.

Back to Compass Sensor Report


'Parallax / Hitachi Compass Module code
' John Schimmel October 2005
' http://itp.nyu.edu/physcomp/sensors/
'

include "modedefs.bas"



DinDout var portc.3
Clk     var portc.2
En      var portc.1

output clk
output en

Reset   con %0000
Measure Con %1000
Report  CON %1100
Ready   CON %1100
NegMask Con %1111100000000000

x       Var word
y       var word
newX    var byte
newY    var byte

stats  var byte
angle   var word
product var byte

'serial variables
TX      var portc.6
RX      var portc.7
serialSet   CON 16468


main:

  gosub Compass_Get_Axes

  Serout2 TX,serialSet,[SDEC x,"  |   "]
  serout2 tx,serialSet,[Sdec y,"  |   "]

          if x.bit10 = 1 then
            serout2 tx, serialSet, ["-x  |   "]
          else
            serout2 tx, serialSet, ["+x  |   "]
          endif

          if y.bit10 = 1 then
            serout2 tx, serialSet, ["-y  |   "]
          else
            serout2 tx, serialSet, ["+y  |   "]
          endif


          serout2 tx,serialSet,[dec abs(y.lowbyte),"/",DEC abs(x.lowbyte),"  |   "]
          serout2 tx,serialSet,[DEC (abs(y.lowbyte)/abs(x.lowbyte)*10),"  |   "]

   gosub get_direction

goto main


'-----------------------------------------------
' Get_Directions subroutine is a hack
' It was made from observing the compass's output
' when pointed in the 4 main directions: N, S, E, W
' 
' The data was aligned with the directions and
' conditional IF statements were made to fit.
' Again, this is a hack, but a decent one.
'
' The compass returns both positive and negative numbers
' check for x.BIT10 = 1 or y.BIT10=1 to see if the number is
' negative. Use the negative numbers like this:
' +X = NORTH, -X = SOUTH
' +Y = WEST, -Y = EAST
'
' The compass is not really calibrated, and the magenetic fields
' of the circuit could even throw the data off. Please review your
' compass data then calibrate the PRODUCT values in the IF statements below 
'-----------------------------------------------
Get_Direction:
    product = abs(y.lowbyte)/abs(x.lowbyte) * 10 'get absolute value of (y/x) * 10 to lose the decimal problem
     if NOT x.bit10 and (product <= 10) then  'IF X is positive and the product <= 10 then NORTH
        serout2 tx,serialSet,["NORTH!",13,10]
        return
     endif

      if x.Bit10 and y.bit10 and (product>=0) and (product<=40) then  'if X is negative and y is negative and product is between 0 and 40 then EAST
         serout2 tx,serialSet,["EAST!",13,10]
         return
     endif

     if x.Bit10 and NOT y.bit10 and (product=0) then  ' if X is negative and Y is positive and product=0 then SOUTH
         serout2 tx,serialSet,["SOUTH!",13,10]
         return
     endif

     if x.Bit10 and not y.bit10 and (product>=10) and (product<=40) then ' if X is negative and Y is positive and product is between 10 and 40.
         serout2 tx,serialSet,["WEST!",13,10]
         return
     endif

     serout2 tx,serialSet,[13,10]
return

'-------------------------------------------------------
' Compass_Get_Axes was originally written by Parallax for 
' the BASIC STAMP 2. The code is identical for PICBasic Pro.
'
' From parallax:
' "The polling is a  combination of SHIFTOUT commands that request the status,
' and SHIFTIN commands that acquire the  status.  When the SHIFTIN receives
' status flags indicating that the measurement is complete, a second  and third
' SHIFTIN command can then store the 11-bit x and y axis measurements in variables."
'-------------------------------------------------------
Compass_Get_Axes:
    High En:Low En  ' Turn the enable pin high then low to prepare compass for message
    Shiftout DinDout,clk,MSBFIRST,[Reset\4] ' SHIFTOUT the first 4 bits of Reset (i.e. 0000)

    High En:Low En  ' Again,Turn the enable pin high then low to prepare compass for message
    Shiftout DinDout,Clk,MSBFIRST,[Measure\4] ' SHIFTOUT the first 4 bits of Measure (i.e 1000)
    stats = 0

    While Ready != stats  'Loop until the SHIFTIN command receives stats AND stats = ready
        high en:low en ' prepare for message
        shiftout dindout,clk,MSBFIRST,[Report\4] ' shiftout out command for compass reading
        shiftin DinDout,CLk,MSBPOST,[stats\4] 'shiftin the status of the reading
    WEND

    'when the status of the compass is ready, SHIFTIN the X and Y values
    Shiftin DinDout,clk,MSBPOST,[x\11,y\11]
    high en ' turn off compass

    'deal with negative numbers
    if (y.10 = 1) then y=y | negmask
    if (x.10 = 1) then x=x | negmask

return