PIC I2C Code for 3-Axis Gyroscope - Parallax 27911-RT - Gyroscope L3G4200D

Here is some code I put together for myself to interface with the Parallax 27911-RT 3-Axis gyroscope with a PIC16F690. I organized it in a header and source file so that it could be included within another project. It uses I2C communication, and the pins must be configured in the header file.

Here is the header file:

#ifndef GYRO_H
#define GYRO_H

/* Parallax Gyro 27911-RT

        Pins:
        GND  -> GND
        VIN  -> 5V
        CS   -> 5V (I2C Mode)
        SCL  -> I2C CLK
        SDA  -> I2C DATA
        SDO  -> GND (LSB of Slave Address)
        INT1 -> EMPTY
        INT2 -> OPTIONAL (Data Ready Interrupt)
*/

int xen,yen,zen;

// I2C Bit Configuration
sbit Soft_I2C_Scl           at RC4_bit;
sbit Soft_I2C_Scl_Direction at TRISC4_bit;

sbit Soft_I2C_Sda           at RC5_bit;
sbit Soft_I2C_Sda_Direction at TRISC5_bit;

#define GYRO_WRITE_ADDRESS 0xD0
#define GYRO_READ_ADDRESS 0xD1

#define X_MSB 0x29
#define X_LSB 0x28
#define Y_MSB 0x2B
#define Y_LSB 0x2A
#define Z_MSB 0x2D
#define Z_LSB 0x2C

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define FIFO_CTRL_REG 0x2E

#define WHO_AM_I 0x0F
#define TEMPERATURE 0x26
#define STATUS 0x27

void initGyro();
void writeGyro(unsigned short reg, unsigned short val);
unsigned short getGyroReg(unsigned char regAddress);
void getGyroX();
void getGyroY();
void getGyroZ();

#include "gyro.c"
#endif

Here is the source file. Note: You can comment out the TEST_MAIN if you want to add into another project.

#ifndef GYRO_C
#define GYRO_C

#define TEST_MAIN

/* Parallax Gyro 27911-RT

        Pins:
        GND  -> GND
        VIN  -> 5V
        CS   -> 5V (I2C Mode)
        SCL  -> I2C CLK
        SDA  -> I2C DATA
        SDO  -> GND (LSB of Slave Address)
        INT1 -> EMPTY
        INT2 -> OPTIONAL (Data Ready Interrupt)
*/

#include "gyro.h"

#ifndef bit
#define bit(n) (1 << (n))
#endif

unsigned short LSB, MSB;
unsigned short ack;

int start_gyro(unsigned short id) {
     int attempts;
     for (attempts=0; attempts<25;attempts++) {
         Soft_I2C_start();
         ack=Soft_I2C_Write(id);
         if(ack==0) return 1;
     }
     return 0;
}

void writeGyro(unsigned short reg, unsigned short val){
     start_gyro(GYRO_WRITE_ADDRESS);
     ack = Soft_I2C_Write(reg);
     ack = Soft_I2C_Write(val);
     Soft_I2C_stop();
}

unsigned short recieved;
unsigned short getGyroReg(unsigned char regAddress){
         start_gyro(GYRO_WRITE_ADDRESS);
         ack = Soft_I2C_Write(regAddress);
         Soft_I2C_stop();

         start_gyro(GYRO_READ_ADDRESS);
         recieved = Soft_I2C_Read(0);
         Soft_I2C_stop();

         return recieved;
}

void initGyro() {
     delay_ms(10);   // Wait for device to completely power up
     Soft_I2C_Init(); // Initiate I2C Connection
     writeGyro(CTRL_REG1,0b00001111); //Turn on all axis's, turn of power down mode
     writeGyro(CTRL_REG2,0b00000000); // No filtering
     writeGyro(CTRL_REG3,0b00001000);  // Initialize data ready interrupt on INT2
     writeGyro(CTRL_REG4,0b00000000); // Little Endian
     writeGyro(CTRL_REG5,0b00000000); // Disable the FIFO
     writeGyro(FIFO_CTRL_REG,0b00000000);
}

void getGyroX(){
     MSB = getGyroReg(X_MSB);
     LSB = getGyroReg(X_LSB);

     xen = ((MSB << 8) | LSB);
}

void getGyroY(){
     MSB = getGyroReg(Y_MSB);
     LSB = getGyroReg(Y_LSB);

     yen = ((MSB << 8) | LSB);
}

void getGyroZ(){
     MSB = getGyroReg(Z_MSB);
     LSB = getGyroReg(Z_LSB);

     zen = ((MSB << 8) | LSB);
}

#ifdef TEST_MAIN

 //function for outputing string to uart
void outstr(char s[])
{
    int k;
    for (k = 0; s[k] != 0; k++)
        Uart1_Write(s[k]);
    Uart1_Write(' ');
}

char tempstring[10];
void main() {
         ANSEL = ANSELH = 0;
         PORTA = PORTB = PORTC = 0;
         TRISA = TRISB = TRISC = 0xFF;
         TRISA.F0 = 1;   // So UART Tool will work with Programmer

         TRISB.F4 = 0;   // LED
         PORTB.F4 = 1;

         UART1_Init(1200);
         initGyro();

         while(1){

                  getGyroX();
                  IntToStr((int)xen,tempstring);
                  outstr(tempstring);

                  getGyroY();
                  IntToStr((int)yen,tempstring);
                  outstr(tempstring);

                  getGyroZ();
                  IntToStr((int)zen,tempstring);
                  outstr(tempstring);

                  UART1_Write('\n');

                  delay_ms(100);
         }

}
#endif

#endif

Hope this can help someone. I believe the code should be pretty portable, at least across the PIC devices.

Let us know when you have it ported to Arduino.