L3G4200D Gyroscope Module
MoZak18
Posts: 26
Hello,
I am trying to use the example spin code for the L3G4200D gyroscope to yield the raw data output....however, I am getting 0's for the X, Y, and Z axes. I have the SDA and SCL pins connected and assigned appropriately to the P8X32A microcontroller. I have modified the code slightly to provide an output using "parallax serial terminal" (which turns out to work better for me) but it provides the same output if I use "full duplex serial", so this is not the problem. If anyone can help it would be greatly appreciated, I have a feeling something obvious is likely the problem. My code is below. Thanks!
CON
_clkmode = xtal1 + pll16x
_clkfreq = 80_000_000
SCLpin = 17
SDApin = 16
'****Registers****
WRITE = $D2
READ = $D3
CTRL_REG1 = $20 'SUB $A0
CTRL_REG3 = $22
CTRL_REG4 = $23
STATUS_REG = $27
OUT_X_INC = $A8
x_idx = 0
y_idx = 1
z_idx = 2
VAR
long x
long y
long z
long cx
long cy
long cz
long ff_x
long ff_y
long ff_z
long multiBYTE[3]
OBJ
pst : "parallax serial terminal"
PUB Main | last_ticks
''Main routine for example program - Shows RAW X,Y,Z data and example of calculated data for degrees
pst.start(38400) 'start a pstinal Object (rxpin, txpin, mode, baud rate)
Wrt_1B(CTRL_REG3, $08) 'set up data ready signal
Wrt_1B(CTRL_REG4, $80) 'set up "block data update" mode (to avoid bad reads when the values would get updated while we are reading)
Wrt_1B(CTRL_REG1, $1F) 'write a byte to control register one (enable all axis, 100Hz update rate)
pst.str(string("initialized", 13))
Calibrate
pst.str(string("calibrated", 13))
last_ticks := cnt
pst.str(string("about to enter loop", 13))
repeat
pst.str(string("in the loop", 13))
WaitForDataReady
Read_MultiB(OUT_X_INC) 'Read out multiple bytes starting at "output X low byte"
pst.str(string("ran some stuff", 13))
x := x - cx 'subtract calibration out
y := y - cy
z := z - cz
' at 250 dps setting, 1 unit = 0.00875 degrees,
' that means about 114.28 units = 1 degree
' this gets us close
x := x / 114
y := y / 114
z := z / 114
RawXYZ 'Print the Raw data output of X,Y and Z
waitcnt(80_000_000 + cnt)
PUB RawXYZ
''Display Raw X,Y,Z data
pst.str(string("RAW X ",11))
pst.dec(x)
pst.str(string(13, "RAW Y ",11))
pst.dec(y)
pst.str(string(13, "RAW Z ",11))
pst.dec(z)
pst.str(string(13))
PUB Calibrate
cx := 0
cy := 0
cz := 0
repeat 25
WaitForDataReady
Read_MultiB(OUT_X_INC) ' read the 3 axis values and accumulate
cx += x
cy += y
cz += z
cx /= 25 ' calculate the average
cy /= 25
cz /= 25
PUB WaitForDataReady | status
repeat
status := Read_1B(STATUS_REG) ' read the ZYXZDA bit of the status register (looping until the bit is on)
if (status & $08) == $08
quit
PUB Wrt_1B(SUB1, data)
''Write single byte to Gyroscope.
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB1) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
send(data) 'data you want to send
'slave ACK
stop
PUB Wrt_MultiB(SUB2, data, data2)
''Write multiple bytes to Gyroscope.
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB2) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
send(data) 'data you want to send
'slave ACK
send(data2) 'data you want to send
'slave ACK
stop
PUB Read_1B(SUB3) | rxd
''Read single byte from Gyroscope
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB3) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
stop
start 'SR condition
send(READ) 'device address as read command
'slave ACK
rxd := receive(false) 'recieve the byte and put in variable rxd
stop
result := rxd
PUB Read_MultiB(SUB3)
''Read multiple bytes from Gyroscope
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB3) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
stop
start 'SR condition
send(READ) 'device address as read command
'slave ACK
multiBYTE[x_idx] := (receive(true)) | (receive(true)) << 8 'Receives high and low bytes of Raw data
multiBYTE[y_idx] := (receive(true)) | (receive(true)) << 8
multiBYTE[z_idx] := (receive(true)) | (receive(false)) << 8
stop
x := ~~multiBYTE[x_idx]
y := ~~multiBYTE[y_idx]
z := ~~multiBYTE[z_idx]
PRI send(value) ' I²C Send data - 4 Stack Longs
value := ((!value) >< 8)
repeat 8
dira[SDApin] := value
dira[SCLpin] := false
dira[SCLpin] := true
value >>= 1
dira[SDApin] := false
dira[SCLpin] := false
result := not(ina[SDApin])
dira[SCLpin] := true
dira[SDApin] := true
PRI receive(aknowledge) ' I²C receive data - 4 Stack Longs
dira[SDApin] := false
repeat 8
result <<= 1
dira[SCLpin] := false
result |= ina[SDApin]
dira[SCLpin] := true
dira[SDApin] := (aknowledge)
dira[SCLpin] := false
dira[SCLpin] := true
dira[SDApin] := true
PRI start ' 3 Stack Longs
outa[SDApin] := false
outa[SCLpin] := false
dira[SDApin] := true
dira[SCLpin] := true
PRI stop ' 3 Stack Longs
dira[SCLpin] := false
dira[SDApin] := false
I am trying to use the example spin code for the L3G4200D gyroscope to yield the raw data output....however, I am getting 0's for the X, Y, and Z axes. I have the SDA and SCL pins connected and assigned appropriately to the P8X32A microcontroller. I have modified the code slightly to provide an output using "parallax serial terminal" (which turns out to work better for me) but it provides the same output if I use "full duplex serial", so this is not the problem. If anyone can help it would be greatly appreciated, I have a feeling something obvious is likely the problem. My code is below. Thanks!
CON
_clkmode = xtal1 + pll16x
_clkfreq = 80_000_000
SCLpin = 17
SDApin = 16
'****Registers****
WRITE = $D2
READ = $D3
CTRL_REG1 = $20 'SUB $A0
CTRL_REG3 = $22
CTRL_REG4 = $23
STATUS_REG = $27
OUT_X_INC = $A8
x_idx = 0
y_idx = 1
z_idx = 2
VAR
long x
long y
long z
long cx
long cy
long cz
long ff_x
long ff_y
long ff_z
long multiBYTE[3]
OBJ
pst : "parallax serial terminal"
PUB Main | last_ticks
''Main routine for example program - Shows RAW X,Y,Z data and example of calculated data for degrees
pst.start(38400) 'start a pstinal Object (rxpin, txpin, mode, baud rate)
Wrt_1B(CTRL_REG3, $08) 'set up data ready signal
Wrt_1B(CTRL_REG4, $80) 'set up "block data update" mode (to avoid bad reads when the values would get updated while we are reading)
Wrt_1B(CTRL_REG1, $1F) 'write a byte to control register one (enable all axis, 100Hz update rate)
pst.str(string("initialized", 13))
Calibrate
pst.str(string("calibrated", 13))
last_ticks := cnt
pst.str(string("about to enter loop", 13))
repeat
pst.str(string("in the loop", 13))
WaitForDataReady
Read_MultiB(OUT_X_INC) 'Read out multiple bytes starting at "output X low byte"
pst.str(string("ran some stuff", 13))
x := x - cx 'subtract calibration out
y := y - cy
z := z - cz
' at 250 dps setting, 1 unit = 0.00875 degrees,
' that means about 114.28 units = 1 degree
' this gets us close
x := x / 114
y := y / 114
z := z / 114
RawXYZ 'Print the Raw data output of X,Y and Z
waitcnt(80_000_000 + cnt)
PUB RawXYZ
''Display Raw X,Y,Z data
pst.str(string("RAW X ",11))
pst.dec(x)
pst.str(string(13, "RAW Y ",11))
pst.dec(y)
pst.str(string(13, "RAW Z ",11))
pst.dec(z)
pst.str(string(13))
PUB Calibrate
cx := 0
cy := 0
cz := 0
repeat 25
WaitForDataReady
Read_MultiB(OUT_X_INC) ' read the 3 axis values and accumulate
cx += x
cy += y
cz += z
cx /= 25 ' calculate the average
cy /= 25
cz /= 25
PUB WaitForDataReady | status
repeat
status := Read_1B(STATUS_REG) ' read the ZYXZDA bit of the status register (looping until the bit is on)
if (status & $08) == $08
quit
PUB Wrt_1B(SUB1, data)
''Write single byte to Gyroscope.
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB1) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
send(data) 'data you want to send
'slave ACK
stop
PUB Wrt_MultiB(SUB2, data, data2)
''Write multiple bytes to Gyroscope.
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB2) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
send(data) 'data you want to send
'slave ACK
send(data2) 'data you want to send
'slave ACK
stop
PUB Read_1B(SUB3) | rxd
''Read single byte from Gyroscope
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB3) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
stop
start 'SR condition
send(READ) 'device address as read command
'slave ACK
rxd := receive(false) 'recieve the byte and put in variable rxd
stop
result := rxd
PUB Read_MultiB(SUB3)
''Read multiple bytes from Gyroscope
start
send(WRITE) 'device address as write command
'slave ACK
send(SUB3) 'SUB address = Register MSB 1 = reg address auto increment
'slave ACK
stop
start 'SR condition
send(READ) 'device address as read command
'slave ACK
multiBYTE[x_idx] := (receive(true)) | (receive(true)) << 8 'Receives high and low bytes of Raw data
multiBYTE[y_idx] := (receive(true)) | (receive(true)) << 8
multiBYTE[z_idx] := (receive(true)) | (receive(false)) << 8
stop
x := ~~multiBYTE[x_idx]
y := ~~multiBYTE[y_idx]
z := ~~multiBYTE[z_idx]
PRI send(value) ' I²C Send data - 4 Stack Longs
value := ((!value) >< 8)
repeat 8
dira[SDApin] := value
dira[SCLpin] := false
dira[SCLpin] := true
value >>= 1
dira[SDApin] := false
dira[SCLpin] := false
result := not(ina[SDApin])
dira[SCLpin] := true
dira[SDApin] := true
PRI receive(aknowledge) ' I²C receive data - 4 Stack Longs
dira[SDApin] := false
repeat 8
result <<= 1
dira[SCLpin] := false
result |= ina[SDApin]
dira[SCLpin] := true
dira[SDApin] := (aknowledge)
dira[SCLpin] := false
dira[SCLpin] := true
dira[SDApin] := true
PRI start ' 3 Stack Longs
outa[SDApin] := false
outa[SCLpin] := false
dira[SDApin] := true
dira[SCLpin] := true
PRI stop ' 3 Stack Longs
dira[SCLpin] := false
dira[SDApin] := false
Comments
Did you try with the original example code, and what were the results?
Once the example works, then you can start changing things.
In your original post, find the EDIT POST button on the bottom to add the code tags. This will allow you to format the code as it looks in the propeller tool, and formating is important, as it controls aspects of compilation.
Istvan
Thanks
I may have left them that way and forgot to switch them around before I took the picture. I have tried every combination of connecting them with given pin assignments in the code, I literally made a table to try just about every combination out of the chance that the datasheet may have been incorrect (I've seen it happen several times before with certain components) or that there was some glitch in the code. That was probably why, but that wouldn't be my problem.
I ordered two more gyros and found out the one I had was indeed defective. This is the 3rd defective part from Parallax that I have purchased, so I'm not too happy about that, especially since I'm short on time for this project. Thanks for all the help and replies, I greatly appreciate it. The new gyro works great.