Connecting the CMPS03 to the BS2 

Introduction
The compass module uses either a PWM output or the I2C bus for communications. This example uses the I2C Bus. The SDA (data) and SCL (clock) lines are connected to pins P8 and P9 on the BS2. These are the pins used by the BS2p for the I2CIN and I2COUT commands. The I2CIN and I2COUT commands do not work correctly on early BS2p modules as they did not implement the I2C SCL bus hold feature. Later BS2p modules (from around late 2002 onwards) are fine. If you have an old BS2p or one of the other BS2 variants, you can still use the following code.

 This example uses a combination of bit bashing and the SHIFTIN and SHIFTOUT commands. It has been tested with the BS2 and BS2p.
The BS2 internal 5v regulator is not suitable for powering much external circuitry. I therefore recommend you use a separate 5v regulator.

Circuit Schematic for connecting the BS2 Stamp to the CMPS03 Compass Module using the I2C bus

Note the switch connecting pin 6 to Ground. This is all that is needed for calibration of Rev7 Firmware.


Software for BS2, BS2e, BS2sx and BS2p

The sample code below displays the compass bearing as both BRAD's (0-255) and Degrees (0-359) in a Debug window on the PC.
It can be downloaded here

'{$STAMP BS2}

'***********************************************************
'**                                                       **
'**           I2C Routines for the Basic Stamp            **
'**        using the CMPS01/CMPS03 Compass Module         **
'**                                                       **
'**            Copyright 2002 - Devantech Ltd             **
'**     Commercial use of this software is prohibited     **
'**     Private and educational use only is permitted     **
'**                                                       **
'**        Written by Gerald Coe - January 2002           **
'**                                                       **
'**     This Code has been Tested on BS2 and BS2p         **
'**  It should work equally well on the BS2e and BS2sx    **
'**                                                       **
'***********************************************************

SDA con 8                                ' I2C data
SCL con 9                                ' I2C clock
SDAin var in8
SDAout var out8                          ' To change the pins used, alter these 5 lines
SDAdir var dir8                          ' The 4 SDA numbers must be the same, of course

loop var byte                            ' just a looping counter
I2cBuf var byte                          ' I2c read/write buffer
I2cAddr var byte                         ' Address of I2C device
I2cReg var byte                          ' Register number within I2C device
I2cData var word                         ' Data to read/write
I2cAck var bit                           ' Acknowledge bit

Main:
I2cAddr = $c0                            ' CMPS01/03 Compass module address
I2cReg = 1                               ' Bearing as 0-255 (BRAD)
gosub I2cByteRead
debug 2,0,0, "Compass Bearing (0-255 BRAD) ", dec3 I2cData
I2cReg = 2                               ' Bearing as 0-359.9 degrees
gosub I2cWordRead
debug 2,0,1, "Compass Bearing (0-359 Degrees ", dec3 I2cData/10

goto main

'--------------------------------------------------------------------------------------------
' I2C subroutines follow
'--------------------------------------------------------------------------------------------

I2cByteWrite:                            ' writes I2cData.lowbyte to I2cReg at I2cAddr
gosub I2cStart
I2cBuf = I2cAddr
gosub I2cOutByte                         ' send device address
I2cBuf = I2cReg
gosub I2cOutByte                         ' send register number
I2cBuf = I2cData.lowbyte
gosub I2cOutByte                         ' send the data
gosub I2cStop
return

I2cWordWrite:                            ' writes I2cData to I2cReg at I2cAddr
gosub I2cStart
I2cBuf = I2cAddr
gosub I2cOutByte                         ' send device address
I2cBuf = I2cReg
gosub I2cOutByte                         ' send register number
I2cBuf = I2cData.highbyte
gosub I2cOutByte                         ' send the data - high byte
I2cBuf = I2cData.lowbyte
gosub I2cOutByte                         ' send the data - low byte
gosub I2cStop
return

I2CByteRead:
gosub I2cStart
I2cBuf = I2cAddr
gosub I2cOutByte                         ' send device address
I2cBuf = I2cReg
gosub I2cOutByte                         ' send register number
gosub I2cStart                           ' repeated start
I2cBuf = I2cAddr | 1
gosub I2cOutByte                         ' send device address (with read set)
I2cAck = 0                               ' send Nak
gosub I2cInByte
I2cData.lowbyte = I2cBuf                 ' read the data
I2cData.highbyte = 0
gosub I2cStop
return

I2CWordRead:
gosub I2cStart
I2cBuf = I2cAddr
gosub I2cOutByte                         ' send device address
I2cBuf = I2cReg
gosub I2cOutByte                         ' send register number
gosub I2cStart                           ' repeated start
I2cBuf = I2cAddr | 1
I2cAck = 1                               ' send Ack
gosub I2cOutByte                         ' send device address (with read set)
gosub I2cInByte
I2cData.highbyte = I2cBuf                ' read the data
I2cAck = 0                               ' send Nak
gosub I2cInByte
I2cData.lowbyte = I2cBuf
gosub I2cStop
return

I2cOutByte:
shiftout SDA, SCL, MSBFIRST, [I2cBuf]
input SDA
high SCL                                 ' clock in the ack' bit
low SCL
return

I2cInByte:
shiftin SDA, SCL, MSBPRE, [I2cBuf]
SDAout = 0
SDAdir = I2cAck
high SCL                                 ' clock out the ack' bit
low SCL
input SDA
return

I2cStart                                 ' I2C start bit sequence
high SDA
high SCL
low SDA
low SCL
return

I2cStop:                                 ' I2C stop bit sequence
low SDA
high SCL
high SDA
return