PDA

View Full Version : Weird values



John Abshier
11-03-2006, 01:37 PM
CON 'CMPSO3Demo
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
SCL = 0 'Define Constants
SDA = 1
VAR

OBJ
C : "CMPS03"
Tv : "Tv_Text"
PUB Main | version, bBearing, wBearing
Init
Tv.str(string("Bus check "))
Tv.dec(C.BusCheck)
Tv.out(13)
Tv.str(string("Device Present "))
Tv.dec(C.Present)
Tv.out(13)
if C.Present
Tv.str(string("Present"))
Tv.out(13)
version := C.GetVersion
Tv.str(string("Version "))
Tv.hex(version,8)
Tv.out(13)
bBearing := C.GetBBearing
Tv.str(string("Byte Bearing "))
Tv.hex(bBearing,8)
Tv.out(13)
wBearing := C.GetWBearing
Tv.str(string("Word Bearing "))
Tv.hex(WBearing,8)
PUB Init
Tv.start(12) ' should check fail
Tv.out($00) ' clear
Tv.out($01) ' home
C.Init(SDA, SCL)



CON 'CMPS03 object
CMP_ADDRESS = $C0
OBJ
I2C : "I2C LowLevel"
PUB Init(SDA, SCL)
repeat 9
I2C.i2cStop
I2C.Initialize(SDA, SCL) ' Initialize i2c MASTER in present COG
PUB GetVersion
result := ReadReg($00)
return
PUB GetBBearing
result := ReadReg($1)
return
PUB GetWBearing : wBearing
wBearing := ReadReg($2)
wBearing <<= 8
wBearing |= REadReg($3)
return
PRI ReadReg(reg)
I2C.i2cStart
I2C.i2cWrite(CMP_ADDRESS | 0, 8)
I2C.i2cWrite(reg, 8)
I2C.i2cStart
I2C.i2cWrite(CMP_ADDRESS | 1, 8)
result := I2C.i2cRead(0, 8)
return
PUB BusCheck
result := I2C.testBus
return
PUB Present
result := I2C.devicePresent(CMP_ADDRESS)
return
The output of the program that reads a CMPS03 compass is
Version 9 This is the correct value.
bBearing $9E8 This should be a byte. E8 would be reasonable.
wBearing $9E80CD6 This should be a word. $0CD6 is a consistent result with $E8 for bBearing
I don't understand what is going on. I thought that the result local variable was set to 0 on a call.

Beau Schwabe
11-03-2006, 04:02 PM
I'll need to look at this closer, but in the I2C routine the data is not cleared. It is simply shifted left. This is not an error , the Idea was to be able retain a data stream in a 4-byte FIFO approach.
This is simple to fix... if you are expecting a BYTE, then just AND the result with $FF... expecting a WORD, then AND the result with $FFFF... for a LONG, just leave it alone.

I'll make note of this when I release this object in the future.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

CJ
11-03-2006, 11:10 PM
Beau, wouldn't it do the same thing if you stuffed the returned result into the proper sized variable rather than go through the extra step of anding it? I can see anding being useful for units like the ds1620 which return 9 bits & $1FF.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who says you have to have knowledge to use it?

I've killed a fly with my bare mind.

John Abshier
11-03-2006, 11:29 PM
Beau, perhaps the answer is documentation. The misleading part is that you tell i2cRead how many bits you want and it returns more than that number of bits. I guess this is a design decision. The other part of the object that I don't understand is what to do with ack on i2cRead.

CJ, I tried stuffing the result into the proper sized variable, but Spin only allows long local variables.

Beau Schwabe
11-04-2006, 12:59 AM
CJ and John,

John, as you pointed out in a PM...
"The problem is that i2cData is global to the object. Making it local to Pub i2cRead solves the problem."

The reason I made i2cData global was so that I could use the incoming data as a FIFO (First-In-First-Out).
This kind of circumstance has been handy for some applications I have come across so I implemented the variable
this way. That said, it is difficult to design a one size fits all. The whole idea anyway is that the propeller
objects can be modified by the user to fit a specific application. In some cases, the way I did it can reduce
the amount of code space required, when in a pinch can make a real impact. For example:

a section of your code that reads....



PUB GetWBearing : wBearing
wBearing := ReadReg($2)
wBearing <<= 8
wBearing |= REadReg($3)
return

...could be re-written as...



PUB GetWBearing : wBearing
ReadReg($2)
wBearing := REadReg($3) & $FFFF
return

...it only saves a 'long' but if this can be applied several times, it could make a difference.


And yes, documentation is the answer, however the Lowlevel I2C routines John uses here have not officially been released
to the object exchange, instead they were used in an object (DS1307) which has been released.


As far as the ack bit ... this depends on the i2c device itself. On some devices they don't care, on others they either
look for a "1" or a "0". From the documentation, it looks like the CMPS03 wants to see a "0".

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.