| Author |
Message |
victorf
Joined: 01 Jan 2006
Location: Schenectady, New York
|
|
Posted: 05 March 2010, 16:21 PM Post subject: HMC6343 Tilt-compensated compass help |
|
|
I would like to interface a ZX-24 with a SparkFun HMC6343 tilt compensated compass breakout board. I have been trying to
get my mind around how to do the I2C thing, Has anyone any experience with this hardware? I would like to hear from anyone
who has any experience with this device. Code would be nice too!
Any enlightenment will be appreciated.
Vic |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 05 March 2010, 17:42 PM Post subject: Re: HMC6342 Tilt-compensated compass help |
|
|
| victorf wrote: | | Code would be nice too! | I haven't used the device and don't have one on hand so the code below may or may not work. This sample code reads the 16 bytes of EEPROM on the HMC6342. Assuming this works, you should be able to extend the code to implement other useful command codes.
Note that the code contains two different ways of interacting with the device: high-level and low-level. I suspect that the low-level mode will be required due to a substantial required delay between sending the command and reading the reply. Unfortunately, the required delay varies significantly depending on the particular command.
| Code: | Private Const sclPin as Byte = 12
Private Const sdaPin as Byte = 11
Private Const i2CRate as UnsignedInteger = 66 ' 100KHz
Private const i2cAddr as Byte = &H32
Private Const i2cChan as Byte = 0
Private Const startupDelay as Single = 0.5
Private Const respDelay as Single = 10e-3
' HMC5343 Command Codes
Private Const HMC6343_ReadEEPROM as Byte = &He1
' uncomment the line below to use low-level I2C commands
#define USE_LOW_LEVEL_I2C
Sub Main()
Dim i as Byte
Call Sleep(startupDelay)
Call OpenI2C(i2cChan, 0, 0, i2CRate)
For i = 0 to 15
Dim stat as Integer
Dim res as Byte
' prepare and execute a command to read 1 byte of eeprom data
#if defined(USE_LOW_LEVEL_I2C)
Dim bval as Boolean
' perform the "write" portion of the cycle
Call I2CStart(i2cChan)
bval = I2CPutByte(i2cChan, i2cAddr And &Hfe)
bval = I2CPutByte(i2cChan, HMC6343_ReadEEPROM)
bval = I2CPutByte(i2cChan, i)
Call Sleep(respDelay)
' perform the "read" portion of the cycle
Call I2CStart(i2cChan)
bval = I2CPutByte(i2cChan, i2cAddr Or 1)
res = I2CGetByte(i2cChan, False)
Call I2CStop(i2cChan)
#else
Dim data(1 to 4) as Byte
data(1) = HMC6343_ReadEEPROM
data(2) = i
stat = I2CCmd(i2cChan, i2cAddr, 2, data, 1, res)
#endif
' display the result
Debug.Print "Addr &H"; CStrHex(i);
#if defined(USE_LOW_LEVEL_I2C)
Debug.Print ", bval="; bval;
#else
Debug.Print ", stat="; stat;
#endif
Debug.Print ", data=&H"; CStrHex(res)
Next i
End Sub |
Last edited by dkinzer on 06 March 2010, 16:49 PM; edited 2 times in total |
|
| Back to top |
|
 |
victorf
Joined: 01 Jan 2006
Location: Schenectady, New York
|
|
Posted: 05 March 2010, 20:17 PM Post subject: |
|
|
Don,
Thank you for the quick response. I assume that your 5343 is a typo!
Would you explain to me what is going on here:
bval = I2CPutByte(i2cChan, i2cAddr And &Hfe)
and here:
bval = I2CPutByte(i2cChan, i2cAddr Or 1)
res = I2CGetByte(i2cChan, False)
Any further enlightenment will be appreciated.
Vic |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 05 March 2010, 20:43 PM Post subject: |
|
|
| victorf wrote: | | I assume that your 5343 is a typo! | Yes. I corrected it in the code above.
| victorf wrote: | | Would you explain to me what is going on here | It is important to know that an I2C slave address is 7-bits wide and occupies the most significant bits of the address byte. The LSB of the address byte is used to indicate whether you're addressing the slave for writing (0) or reading (1). In the I2C transaction shown, the first phase is a write operation; the AND with &Hfe simply ensures that the LSB is zero as needed.
The second phase is a read operation; the OR operation ensures that the address byte has a 1 in the LSB. In the read phase, it is possible to read multiple bytes of data for some commands. All but the last of the I2CGetByte() calls should have the second parameter set to True. This value is used to acknowledge the byte received from the slave. The acknowledgment value indicates whether additional reads will be done.
You could, of course, define two different constants: | Code: | Private const i2cAddrBase as Byte = &H32
Private const i2cAddrWrite as Byte = i2cAddrBase And &hfe
Private const i2cAddrRead as Byte = i2cAddrBase Or &h01 |
The I2CCmd() function implements exactly the same sequence shown for the low-level operation. The problem relative to this devices is that the delay between writing and reading is not controllable. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 06 March 2010, 17:13 PM Post subject: |
|
|
Further research on the HMC6343 seems to indicate that the module properly implements slave clock stretching in order to synchronize the read cycle with data availability. If this is true, the I2CCmd() form should work.
There are also reports that the HMC6343 datasheet is incomplete, misleading or incorrect regarding some of the command sequences, e.g. pitch and roll values may be swapped. Example:
http://forums.parallax.com/forums/default.aspx?f=25&m=299138 |
|
| Back to top |
|
 |
victorf
Joined: 01 Jan 2006
Location: Schenectady, New York
|
|
Posted: 06 March 2010, 19:57 PM Post subject: |
|
|
Don,
I read the Parallax Forum posts. Did you notice that they were dated Oct 2008? This is the same month/year as Honeywell's HMC6343.pdf. Since I am looking to use the Break-Out-Board from SparkFun, I will bring the thread to their attention and see if they can shed some light on the subject.
Vic |
|
| Back to top |
|
 |
|