ADXL345 & ITG3200 on I2C

26 Jan 2011

Hello,

I use this code (below) to test a 6 Degree of Freedom Combo from SparkFun. The Accelerator values displayed on the HyperTerminal are not stable within acceptable ranges. Readings can be from –app5000 to +app5000 without touching the sensor. Since I have 2 of those 6DOF, and both do have the same behaviour; my code is somewhere wrong. But I do not see it…. Can someone use the red pen and point the error ? Thanks in advance Benny.

/#include "mbed.h"
// Test PRGM voor de Combo van SparkFun
// ITG-3200  triple axis digital gyroscope.
// ADXL345   triple axis, digital interface, accelerometer.

// Used mBed Pin's : 
//     P01=  Gnd                    P11= SPI mosi               P21= Pwm Out                P31= USB D+                          
//     P02=  4.5v - 14.0v           P12= SPI miso               P22= Pwm Out                P32= USB D-                          
//     P03= VB                      P13= SPI sck, Serial Tx     P23= Pwm Out                P33= Ethernet TD+                          
//     P04= nR                      P14= Serial Rx              P24= Pwm Out                P34= Ethernet TD-                          
//     P05= SPI mosi                P15= Analog In              P25= Pwm Out                P35= Ethernet RD+                          
//     P06= SPI miso                P16= Analog In              P26= Pwm Out                P36= Ethernet RD-                          
//     P07= SPI sck                 P17= Analog In              P27= I2C scl, Serial Rx     P37= IF+                           
//     P08=                         P18= Analog In, Anal Out    P28= I2C sda, Serial Tx     P38= IF-                          
//     P09= I2C sda, Serial Tx      P19= Analog In              P29= CAN td                 P39= VU 5v USB out                          
//     P10= I2C scl, Serial Rx      P20= Analog In              P30= CAN rd                 P40= Vout 3.3v Regulated 


//  AnalogIn myPotm1(p20);

DigitalOut myled(LED1)  ;
DigitalOut myled2(LED2) ;
DigitalOut myled3(LED3) ;
DigitalOut myled4(LED4) ;



int i=0                 ;   // Teller
int j=0                 ;   // Teller
      

float Gyro_Temp         ;
int Gyro_DevID          ;

int Acce_DevID          ;

int FiFo = 20           ;   // Aantal metingen voor de FiFo Buffer



// i2c Initialisation  --------------------------
I2C i2c(p9, p10)        ;           // sda, scl

// USB Serial init
Serial pc(USBTX, USBRX) ;           // tx, rx
 




 
//-----------------------------//
// Gyro Registers ITG3200 Gyro //
//-----------------------------//
//  Angular rate sensors.   14.375 LSBs per deg/sec and full-scale range of 2000 deg/sec, 16-bit ADC
//  Fast Mode I2C (400kHz) serial interface 
#define Gyro_ITG3200_I2C_Address    0x68        //7-bit address.   01101000
#define    Gyro_Addr_Read           0xD1        //8-bit address.   011010001
#define    Gyro_Addr_Write          0xD0        //8-bit address.   011010000
#define    Gyro_Who_am_I_Reg        0x00
#define    Gyro_SMPLRT_DIV_Reg      0x15
#define    Gyro_DLPF_FS_Reg         0x16
#define    Gyro_INT_CFG_Reg         0x17
#define    Gyro_INT_Status          0x1A
#define    Gyro_Temp_out_H_Reg      0x1B        // 280 LSB/degC,  Offset: -13200 LSB = 35 degC, Range -30 to +85 degC
#define    Gyro_Temp_out_L_Reg      0x1C        //Offset = -35 degrees, 13200 counts. 280 counts/degrees C.
#define    Gyro_Xout_H_Reg          0x1D        //  Typical sensitivity is 14.375 LSB/(degrees/sec). Angular rate sensors 
#define    Gyro_Xout_L_Reg          0x1E
#define    Gyro_Yout_H_Reg          0x1F
#define    Gyro_Yout_L_Reg          0x20
#define    Gyro_Zout_H_Reg          0x21
#define    Gyro_Zout_L_Reg          0x22
#define    Gyro_PWR_MGM_Reg         0x3E

// Gyro - Low Pass Filter Bandwidths // 
#define     Gyro_LPFBW_256HZ        0x00
#define     Gyro_LPFBW_188HZ        0x01
#define     Gyro_LPFBW_98HZ         0x02
#define     Gyro_LPFBW_42HZ         0x03
#define     Gyro_LPFBW_20HZ         0x04
#define     Gyro_LPFBW_10HZ         0x05
#define     Gyro_LPFBW_5HZ          0x06

#define     Gyro_SleepMode          0x40
#define     Gyro_XYZ_StandbyMode    0x38
#define     Gyro_NormalMode         0x00



//-------------------------------------//
// Acce  Registers ADXL345 Accelerator //
//-------------------------------------//
// 13-bit resolution at �16 g (maintaining 4 mg/LSB scale factor in all g ranges)
// High resolution (3.9 mg/LSB) enables measurement of inclination changes less than 1.0 deg
#define Acce_ADXL345_I2C_Address        0x53    //7-bit address.   1010011
#define    Acce_Addr_Write              0xA6    //8-bit address.   10100110
#define    Acce_Addr_Read               0xA7    //8-bit address.   10100111
#define    Acce_DevID_Reg               0x00 
#define    Acce_Thresh_TAP_Reg          0x1D 
#define    Acce_OffsetX_Reg             0x1E 
#define    Acce_OffsetY_Reg             0x1F 
#define    Acce_OffsetZ_Reg             0x20 
#define    Acce_DUR_Reg                 0x21 
#define    Acce_Latent_Reg              0x22 
#define    Acce_Window_Reg              0x23 
#define    Acce_Thresh_ACT_Reg          0x24 
#define    Acce_Thresh_INACT_Reg        0x25 
#define    Acce_Time_INACT_Reg          0x26 
#define    Acce_ACT_INACT_CTL_Reg       0x27 
#define    Acce_Thresh_FF_Reg           0x28 
#define    Acce_Time_FF_Reg             0x29 
#define    Acce_TAP_Axes_Reg            0x2A 
#define    Acce_ACT_TAP_Status_Reg      0x2B 
#define    Acce_BW_Rate_Reg             0x2C 
#define    Acce_Power_CTL_Reg           0x2D 
#define    Acce_INT_Enable_Reg          0x2E 
#define    Acce_INT_MAP_Reg             0x2F 
#define    Acce_INT_Source_Reg          0x30 
#define    Acce_Data_Format_Reg         0x31 
#define    Acce_DataX0_Reg              0x32        // The output data is twos complement, 
#define    Acce_DataX1_Reg              0x33        //  with DATAx0 as the least significant byte and 
#define    Acce_DataY0_Reg              0x34        //  DATAx1 as the most significant byte
#define    Acce_DataY1_Reg              0x35        
#define    Acce_DataZ0_Reg              0x36 
#define    Acce_DataZ1_Reg              0x37 
#define    Acce_FIFO_CTL_Reg            0x38 
#define    Acce_FIFO_Status_Reg         0x39 

//Data Rate Codes                  
#define    Acce_ADXL345_3200HZ          0x0F
#define    Acce_ADXL345_1600HZ          0x0E
#define    Acce_ADXL345_800HZ           0x0D
#define    Acce_ADXL345_400HZ           0x0C
#define    Acce_ADXL345_200HZ           0x0B
#define    Acce_ADXL345_100HZ           0x0A
#define    Acce_ADXL345_50HZ            0x09
#define    Acce_ADXL345_25HZ            0x08
#define    Acce_ADXL345_12HZ5           0x07
#define    Acce_ADXL345_6HZ25           0x06
#define    Acce_ADXL345_SPI_READ        0x80
#define    Acce_ADXL345_SPI_WRITE       0x00
#define    Acce_ADXL345_MULTI_BYTE      0x60
#define    Acce_ADXL345_X               0x00
#define    Acce_ADXL345_Y               0x01
#define    Acce_ADXL345_Z               0x02
#define    Acce_SleepMode               0x04
#define    Acce_NormalMode              0x08


// ITG-3200  triple axis digital gyroscope.
// ADXL345   triple axis, digital interface, accelerometer.


int main() {
    
   // HyperTerminal  Wissen van het scherm -----------------------------------------------------------      
     pc.printf("\x1B\x48");        //Cursor Home
     pc.printf("\x1B\x4A");        //wissen vanaf Cursor
             
             
    int16_t aXout[FiFo+1]         ;       // FiFo om te averagen
    int16_t aYout[FiFo+1]         ;       // FiFo
    int16_t aZout[FiFo+1]         ;       // FiFo
    int16_t gXout[FiFo+1]         ;       // FiFo
    int16_t gYout[FiFo+1]         ;       // FiFo
    int16_t gZout[FiFo+1]         ;       // FiFo
    
    float aXoutAverage = 0        ;       // Averages
    float aYoutAverage = 0        ;       //
    float aZoutAverage = 0        ;       //
    float gXoutAverage = 0        ;       //
    float gYoutAverage = 0        ;       //
    float gZoutAverage = 0        ;       //
    
    for ( i=0 ; i <= FiFo ; i++ ) {
            aXout[i] = 0          ;       // initialiseren FiFO Buffers
            aYout[i] = 0          ;       
            aZout[i] = 0          ;       
            gXout[i] = 0          ;       
            gXout[i] = 0          ;       
            gXout[i] = 0          ;
        }          
                   

    char tx[2]                    ;
    char rx[6]                    ;
    
    
    // i2c Initialisation  --------------------------
      i2c.frequency(400000)       ;

    
    
    
    // Gyro Initialisation  --------------------------
     tx[0] = Gyro_DLPF_FS_Reg   ;   // 0x16 ,register die wij gaan vullen met tx[1] 
     tx[1] = 0x03 << 3          ;   // FS_SEL bits sit in bits 4 and 3 (0x03) of DLPF_FS register. See datasheet for details. = 0x18
                                    // 2000deg/sec, 256Hz low passfilter bandwith, 8kHz sample rate
     i2c.write(Gyro_Addr_Write, tx, 2)  ;  

     
     
     tx[0] = Gyro_PWR_MGM_Reg   ;        tx[1] = Gyro_NormalMode    ;
     i2c.write(Gyro_Addr_Write, tx, 2)  ;
     
  
    
    // Acce Initialisation  --------------------------
     tx[0] = Acce_Power_CTL_Reg         ;       // Go into standby mode to configure the device. 
     tx[1] = 0x00                       ;
     i2c.write(Acce_Addr_Write, tx, 2)  ; 
     
     tx[0] = Acce_Data_Format_Reg       ;       // 0x0B : Full resolution, +/-16g, 4mg/LSB. 
     tx[1] = 0x0B                       ;       // 0x08 : Full resolution, +/-2g,   mg/LSB. 
     i2c.write(Acce_Addr_Write, tx, 2)  ;       // 0x00 : 10bit resolution,+/-2g,   mg/LSB.  
     
     tx[0] = Acce_BW_Rate_Reg           ;       // 800Hz data rate.
     tx[1] = Acce_ADXL345_800HZ         ;
     i2c.write(Acce_Addr_Write, tx, 2)  ;
     
     tx[0] = Acce_Power_CTL_Reg         ;       // 0x08 : Measurement mode.
     tx[1] = 0x08                       ;
     i2c.write(Acce_Addr_Write, tx, 2)  ; 
     
    
     wait(0.022)                        ;
    
    while(1) {
        
        myled=1                         ;
        
   // Gyro ----------------------------------------------------------------------------------------------
        rx[0]=0, rx[1]=0, rx[2]=0, rx[3]=0, rx[4]=0, rx[5]=0 ;
        
        tx[0] = Gyro_Who_am_I_Reg                                           ;   // Gyro Id uitlezing
            i2c.write(Gyro_Addr_Write, tx, 1)                               ;
            i2c.read(Gyro_Addr_Read, rx, 1)                                 ;
            Gyro_DevID = (int) rx                                           ;

        
        tx[0] = Gyro_Temp_out_H_Reg                                         ;   // Gyro Temperatuur uitlezing
            i2c.write(Gyro_Addr_Write, tx, 1)                               ;
            i2c.read(Gyro_Addr_Read, rx, 2)                                 ;
            int16_t Gyro_OutputTemp = ((int) rx[0] << 8) | ((int) rx[1])    ;
            Gyro_Temp = ((13200+ (float)Gyro_OutputTemp )/280.0) +35.0;
        
        tx[0] = Gyro_Xout_H_Reg                                             ;   // Gyro X uitlezing
            i2c.write(Gyro_Addr_Write, tx, 1)                               ;
            i2c.read(Gyro_Addr_Read, rx, 2)                                 ;
            int16_t Gyro_OutputX = ((int) rx[0] << 8) | ((int) rx[1])       ;
 
        tx[0] = Gyro_Yout_H_Reg                                             ;   // Gyro Y uitlezing
            i2c.write(Gyro_Addr_Write, tx, 1)                               ;
            i2c.read(Gyro_Addr_Read, rx, 2)                                 ;
            int16_t Gyro_OutputY = ((int) rx[0] << 8) | ((int) rx[1])       ;
 
        tx[0] = Gyro_Zout_H_Reg                                             ;   // Gyro Z uitlezing
            i2c.write(Gyro_Addr_Write, tx, 1)                               ;   
            i2c.read(Gyro_Addr_Read, rx, 2)                                 ;
            int16_t Gyro_OutputZ = ((int) rx[0] << 8) | ((int) rx[1])       ;
          
          
            
    // Acce ---------------------------------------------------------------------------------------------------
        rx[0]=0, rx[1]=0, rx[2]=0, rx[3]=0, rx[4]=0, rx[5]=0                ;
         
        tx[0] = Acce_DevID_Reg                                              ;   // Acce Id uitlezing
            i2c.write(Acce_Addr_Write, tx, 1)                               ;
            i2c.read(Acce_Addr_Read, rx, 1)                                 ;
            Acce_DevID = (int) rx                                           ;           
        
        tx[0] = Acce_DataX0_Reg                                             ;   // X,Y,Z na mekaar uitlezen 
            i2c.write(Acce_Addr_Write, tx, 1)                               ;
            i2c.read(Acce_Addr_Read, rx, 6)                                 ;
            int16_t Acce_OutputX = ((int) rx[0] << 8) | ((int) rx[1])       ;   // Acce X uitlezing
            int16_t Acce_OutputY = ((int) rx[2] << 8) | ((int) rx[3])       ;   // Acce Y uitlezing
            int16_t Acce_OutputZ = ((int) rx[4] << 8) | ((int) rx[5])       ;   // Acce Z uitlezing
            
            
        // FiFo vullen
        for ( i=FiFo-1 ; i >= 1 ; i-- ) {
             aXout[i] = aXout[i-1]          ;   
             aYout[i] = aYout[i-1]          ;
             aZout[i] = aZout[i-1]          ;
             gXout[i] = gXout[i-1]          ;
             gYout[i] = gYout[i-1]          ;
             gZout[i] = gZout[i-1]          ;
             }
             
        aXout[0] = Acce_OutputX             ;           
 aYout[0] = Acce_OutputY             ;     
        aZout[0] = Acce_OutputZ             ;
        gXout[0] = Gyro_OutputX             ;
        gYout[0] = Gyro_OutputY             ;
        gZout[0] = Gyro_OutputZ             ;
        
        for ( i=0 ; i <= FiFo-1 ; i++ ) {       
            aXoutAverage = aXoutAverage +  (float)aXout[i] ;
            aYoutAverage = aYoutAverage +  (float)aYout[i] ;
            aZoutAverage = aZoutAverage +  (float)aZout[i] ;
            gXoutAverage = gXoutAverage +  (float)gXout[i] ;
            gYoutAverage = gYoutAverage +  (float)gYout[i] ;
            gZoutAverage = gZoutAverage +  (float)gZout[i] ;
            }
            
        // Averaging 
        aXoutAverage = aXoutAverage / ( float )FiFo    ;
        aYoutAverage = aYoutAverage / ( float )FiFo    ;
        aZoutAverage = aZoutAverage / ( float )FiFo    ;
        gXoutAverage = gXoutAverage / ( float )FiFo    ;
        gYoutAverage = gYoutAverage / ( float )FiFo    ;
        gZoutAverage = gZoutAverage / ( float )FiFo    ;
       
   
        
        j=j+1                   ;   // # metingen
    
    
    // HyperTerminal  ---------------------------------------------------------------------------------------------------      
            //wait(0.1)   ;
            pc.printf("\x1B\x48");        //Cursor Home
            
            pc.printf("FiFo = %i    Meting = %i \n\n\r",FiFo, j )     ;
            pc.printf("gX %8.1f      gY %8.1f      gZ %8.1f         %4.1fC        \n\r", 
                     gXoutAverage, gYoutAverage, gZoutAverage,  Gyro_Temp);
                    
            pc.printf("aX %8.1f      aY %8.1f      aZ %8.1f          \n\n\r", 
                     aXoutAverage, aYoutAverage, aZoutAverage);
                     
     
            pc.printf("Id %i   gX %i    gY %i    gZ %i       gTemp %i   %4.1fC       \n\n\r", 
                    Gyro_DevID, Gyro_OutputX, Gyro_OutputY, Gyro_OutputZ, Gyro_OutputTemp, Gyro_Temp);
                    
            pc.printf("Id %i   aX %i    aY %i    aZ %i         \n\n\r", 
                    Acce_DevID, Acce_OutputX, Acce_OutputY, Acce_OutputZ);
            
            
        aXoutAverage = 0        ;
        aYoutAverage = 0        ;
        aZoutAverage = 0        ;
        gXoutAverage = 0        ;
        gYoutAverage = 0        ;
        gZoutAverage = 0        ;
       
    }
}
27 Jan 2011

I did find the error. It is much better like that :

int16_t Acce_OutputX = ((int) rx[1] << 8) | ((int) rx[0]) int16_t Acce_OutputY = ((int) rx[3] << 8) | ((int) rx[2]) int16_t Acce_OutputZ = ((int) rx[5] << 8) | ((int) rx[4])

Sorry...

Benny.