PDA

View Full Version : Gyro L3G4200D Code Request



VisionWorks
- 23rd February 2015, 19:56
Thank you for considering my request for help.
I am struggling with reading data from the the Gyroscope L3G4200. I have tried SPI 4 wire and I2C. If anybody has worked this code out in PBP3 I would love to view it.

F

LinkMTech
- 24th February 2015, 15:59
Here's part of some code for ST's LSM330DLC that looks like it has all the same registers for your gyroscope. Be sure to correct the address for your device.
Since it's a lengthy program, I'll just list the basic functions.

I used the MSSP module of the PIC18F14K50 so it can run in the background.
The read routine was called using the DRDY interrupt output of the device.

MSSP config:


SSPSTAT.7 = 0 ' Slew rate control set to 400KHz
SSPSTAT.6 = 0 ' SMBus compliance disabled
SSPCON1 = %00101000 ' Enbles I2C module and Master mode
SSPADD = $1A ' Baud rate clock divider bits set for 400KHz
' Adjusted from $1D = 368KHz
CLEAR ' Set all registers to 0

XYZ_RAM VAR BYTE[12] ' Array for 16 bit data, 2 bytes each. First 6 for accelerometer, last 6 for gyro


Gyro register configs:


'================================================= ========================
' Gyroscope configuration
' Load time for all 13 Registers is 1029us at 400KHz setting
' Registers loaded in order specified by data sheet:
' 1. Write CTRL_REG2
' 2. Write CTRL_REG3
' 3. Write CTRL_REG4
' 4. Write CTRL_REG5
' 5. Write Reference
' 6. Write INT1_THS
' 7. Write INT1_DUR
' 8. Write INT1_CFG
' 9. Write CTRL_REG5
' 10. Write CTRL_REG1
'================================================= ========================
Config_Gyr:
' Load CTRL_REG2: 10100111, Edge sensitive trigger, HP filter = Normal,
' HP cutoff = 0.09Hz
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $21 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %10100111 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load CTRL_REG3: 10000000, INT1_G enabled, no Boot Status, Active High,
' Push-pull output. INT2_G disabled
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $22 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00000000 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load CTRL_REG4: 01110000, cont. update, MSB @ lower address, 2000dps
' non SPI
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $23 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %01110000 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

'////////////////// XYZ Interrupt threshold settings ////////////////////
' Threshold level = THS / 0.061dps, where THS = 540dps (1.5 turns/sec)
' Maximum threshold level is 1/2 of Full Scale
' 14bit result is loaded into HI/LO registers of each axis
'////////////////////////////////////////////////////////////////////////
' Load INT1_THS_XH: 00100010, Interrupt MSB threshold bits 14:8
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $32 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00100010 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load INT1_THS_XL: 10010100, Interrupt LSB threshold bits 7:0
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $33 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %10010100 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load INT1_THS_YH: 00100010, Interrupt MSB threshold bits 14:8
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $34 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00100010 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load INT1_THS_YL: 10010100, Interrupt LSB threshold bits 7:0
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $35 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %10010100 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load INT1_THS_ZH: 00100010, Interrupt MSB threshold bits 14:8
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $36 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00100010 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load INT1_THS_ZL: 10010100, Interrupt LSB threshold bits 7:0
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $37 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %10010100 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data
'|||||||||||||||| end XYZ Interrupt threshold settings ||||||||||||||||||

'////////////////// Duration set value //////////////////////////////////
' The ODR sets the LSB; 1/190Hz = 5.26ms
' The maximum Duration time is 6 bit or 128, Max = 128 * 5.26ms = 673ms
' The bit value = Duration/5.26ms
'///////////////////////////////////////////////////////////////////////
' Load INT1_Duration: 10000001, Wait enabled, Duration set to 1.3ms
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $38 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %10000000 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load INT1_CFG: 00101010, OR combo of INT, not Latched, interrupt request
' on measured value HIGHER than preset threshold
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $30 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00101010 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load CTRL_REG5: 00011010, Reboot mem Norm, FIFO disabled, HPen enabled,
' Out_SEL = HPF+LPF2, INT1 = HPF+LPF2
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $24 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00011010 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

' Load CTRL_REG1: 00111111, ODR=95Hz, LPF1=12.5Hz, LPF2=50Hz, Norm PWR,
' ZYX axes enabled
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $20 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00001111 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data

RETURN
'||||||||||||||||||| end Gyroscope configuration ||||||||||||||||||||||||


Gyro register reading routine:


'//////////////////// Gyroscope XYZ data reading ////////////////////////
' Recommended way of reading sequential registers
'
' Master Slave Note
' 1. ST Sends Start condition
' 2. SAD+W Sends Slave Address including Write bit
' 3. SAK Sends Acknowledge
' 4. SUB Sends Sub Address (1st register address to read)
' 5. SAK Sends Acknowledge
' 6. SR Sends a Repeated Start condition
' 7. SAD+R Sends Slave Address including Read bit
' 8. SAK Sends Acknowledge
' 9. Data Sends Data
' 10. MAK Sends Acknowledge
' 11. Data Sends Data
' 12. MAK Sends Acknowledge
' 13. Data Sends Data (Process repeated)
' 14. NMAK No Acknowledgement sent after last register read
' 15. SP Sends Stop condition ending Read process
'
' Reading all XYZ registers and loading the array takes 237us worst case.
'////////////////////////////////////////////////////////////////////////
Read_G_REG:
' Generate Start condition
GOSUB Start_Gyr

' Send first register to read with bit #1 set indicating READ and bit #7
' set indicating multiple reads
SSPBUF = %10101000 ' Register 28h with 7 set = $A8
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task

' Wait for ACK from device
WHILE SSPCON2.6 : WEND ' Wait until device sends an ACK

' Send Repeated Start condition
SSPCON2.1 = 1 ' Send Repeated Start condition
WHILE SSPCON2.1 = 1: WEND ' Wait until MSSP module finishes task

' Send device address with Read bit set
SSPBUF = $D7 ' Transmit device address w/READ bit
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task

' Wait for ACK from device
WHILE SSPCON2.6 : WEND ' Wait until device sends an ACK

'///////////////////// Read the next 6 registers ////////////////////////
' This portion loops through Read sequence 6 times. The Master sends an
' ACK after each read indicating "send another" so no ACK is sent after
' the 6th data packet, a Stop Condition is sent instead to end the READ.
'////////////////////////////////////////////////////////////////////////
FOR e = 6 TO 11
' Receive the 8 bit data from gyroscope
SSPCON2.3 = 1 ' Enable the Receiver to clock in data
WHILE !SSPSTAT.0: WEND ' Wait until Buffer Full bit is set
XYZ_RAM[e] = SSPBUF ' Load each XYZ_RAM byte in array

' Master sends ACK for first 5 data packets
IF e != 11 THEN
SSPCON2.4 = 1 ' Initiate Acknowledge sequence
WHILE SSPCON2.4 = 1: WEND ' Wait until Acknowledge sequence Idle
ENDIF
NEXT e

' Send Stop condition to end Read function
GOSUB Stop_I2C ' Complete RX data read

RETURN
'||||||||||||||||||| end Gyroscope XYZ data reading |||||||||||||||||||||


I2C Start and Stop routines:


'================================================= ========================
' Generate Gyroscope Start condition
'================================================= ========================
Start_Gyr:
' Start condition to the transmit device address
SSPCON2.0 = 1 ' Generate Start condition
WHILE SSPCON2.0 = 1: WEND ' Wait until MSSP module ready to TX
PIR1.3 = 0 ' Clear the Interrupt flag
SSPBUF = $D6 ' Transmit address that includes WRITE bit
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
RETURN

'================================================= ========================
' Stop I2C routine
'================================================= ========================
Stop_I2C:
SSPCON2.2 = 1 ' Initiate Stop condition
WHILE SSPCON2.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
@ nop ; Had to slow it down or it didn't work!
@ Nop ; Only 1 was needed but 1 more won't hurt
RETURN

VisionWorks
- 24th February 2015, 22:54
Louie,

Thanks big time. I'll post once I get it going......or not.

Fritz

LinkMTech
- 25th February 2015, 15:22
You're welcome and good luck with your project.

VisionWorks
- 2nd March 2015, 22:04
Louie,

Please pardon me for my ignorance. But I am not seeing the condition in the code fragment "WHILE SSPSTAT.2: WEND". Do I read this as "wait until bit 2 of the SSPSTAT register is not set"?

Thank you for your help. I just can't find the answer in the PBP3 manual or of course the data sheet.

F

LinkMTech
- 3rd March 2015, 00:43
Yes, that's exactly what that means.
This bit is high while "Transmit in progress", which is a very short time.
Look in your PIC datasheet under MSSP Module and I2C Mode then SSPSTAT under Registers.

Which PIC are you using?
Are you getting an ACK from the gyro?

VisionWorks
- 3rd March 2015, 18:20
Hi Louie,

I have been wanting to migrate to !8F from 16F for some time now. Since your code is written for the 18F it provided me with the motivation to make the switch. My test bed was a LabX1 with a 16F877. But now I will jumper in the 18F14K50. The application is for fusion of accelerometer and gyroscope data into an IMU deceleration detection and warning device for vehicles.

The PIC arrived yesterday and I should have it jumpered in today then will start testing code. It compiles now.

Fritz

VisionWorks
- 5th March 2015, 23:49
Hi Louie,

The 18F is jumpered in to the LABX1 and running fine. I set the OSC to run at 32Mhz. I am debugging with SEROUT2 command.

It appears that I am getting ACK from the Gyro because I am getting a debug statement out just after the "WHILE SSPCON2.6 : WEND.

I am freezing up though at "WHILE !SSPSTAT.0 : WEND". So I am not seeing any data out yet.

Here is that code segment along with my SEROUT2 Debug Statements in that section.

FOR e = 6 TO 11

SEROUT2 PORTB.7,84,[" READ GYRO ",10,10]
' Receive the 8 bit data from gyroscope
SSPCON2.3 = 1 ' Enable the Receiver to clock in data
WHILE !SSPSTAT.0: WEND ' Wait until Buffer Full bit is set
XYZ_RAM[e] = SSPBUF ' Load each XYZ_RAM byte in array

SEROUT2 PORTB.7,84,[" XYZ_RAM ",DEC XYZ_RAM[E],10,10]
' Master sends ACK for first 5 data packets
IF e != 11 THEN
SSPCON2.4 = 1 ' Initiate Acknowledge sequence
WHILE SSPCON2.4 = 1: WEND ' Wait until Acknowledge sequence Idle
ENDIF
NEXT e

Again your help is very much appreciated.

Fritz

LinkMTech
- 6th March 2015, 01:41
Hey Fritz,

Cool project, close to the crash sensor I was working on.

It sounds as though there's nothing in the buffer to give, causing it to stay there. Now what would keep the gyro from actually working? CTRL_REG1 bits 2:0 enable/disable the 3 axes.

Busy looking at datasheet.....

Do you get an interrupt output signal at DRDY or INIT indicating the device is updating?

Edit:
I looked at the code I provided and noticed that I stopped using the INT1 and DRDY outputs, bits 7 and 3. So you'll have to set these in order to verify data updates.
Besides the typos, I see a few discrepancies within the comments and actual SSPBUF values so confirm what you need to use, sorry about that.


' Load CTRL_REG3: 10000000, INT1_G enabled, no Boot Status, Active High,
' Push-pull output. INT2_G disabled
GOSUB Start_Gyr ' Adresss the device
SSPBUF = $22 ' Transmit register address
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
SSPBUF = %00000000 ' Transmit the 8bit data to register
WHILE SSPSTAT.2: WEND ' Wait until MSSP module finishes task
PIR1.3 = 0 ' Clear interrupt flag
GOSUB Stop_I2C ' Complete TX data