CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Program for L3G4200D has been giving strange values
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

Program for L3G4200D has been giving strange values
PostPosted: Wed Feb 26, 2014 6:13 pm     Reply with quote

Hi everyone!
Please, could someone help me? I'm trying to make a code to read a L3G4200D gyroscope sensor http://www.pololu.com/file/0J491/L3G4200D.pdf

but my program has been giving strange values and they are changing very strange

e.g: (sequency of some readings without moving the sensor; X,Y,Z)
0, 16482190, 753550
8321, 16088974, 556942
129, 16285582, 425870
16513, 16416654, 884622
128, 16482190, 1146766
8321, 16220046, 425870
0, 16285582, 819086

I'm using the CCS Compiler version 5.018

my current program:

Code:

#include <18F4520.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(crystal=20000000,restart_wdt)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master, FORCE_HW, RESTART_WDT)
#use i2c(sda=PIN_B0, scl=PIN_B1)

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D

float x=0;
float y=0;
float z=0;
signed long xMSB;
signed long xLSB;
signed long yMSB;
signed long yLSB;
signed long zMSB;
signed long zLSB;

void setupL3G4200D(int scale);
void writeRegister(int deviceAddress, int address, int val);
int readRegister(int deviceAddress, int address);
void gyro_values();

void main(){

setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

while(1){
gyro_values();
}
}

void setupL3G4200D(int scale){

  writeRegister(L3G4200D_Address, CTRL_REG1, WHO_AM_I);   // 100Hz, 12.5, Power Up
  writeRegister(L3G4200D_Address, CTRL_REG2, 0x0);
  writeRegister(L3G4200D_Address, CTRL_REG3, 0x8);
   
  if(scale == 250){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x00);
  }else if(scale == 500){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x10);
  }else{
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x20);
}
  writeRegister(L3G4200D_Address, CTRL_REG5, 0x0);
 
}

void writeRegister(int deviceAddress, byte address, byte val){
i2c_start();// start transmission to device
i2c_write(deviceAddress);// send device address
i2c_write(address);// send register address
i2c_write(val);// send value to write
i2c_stop();// end transmission
}

int readRegister(int deviceAddress, byte address){
int v;
i2c_start(); // start transmission to device
i2c_write(deviceAddress); //This is where you have to _write_ the register number you want
i2c_write(address); // register to read
i2c_start(); //restart - the bus is now set to _read_
i2c_write(deviceAddress + 1); //now turn the bus round
v = i2c_read(0);
i2c_stop(); //This will update x, y, and z with new values
return v;
}

void gyro_values(){

  xMSB = readRegister(L3G4200D_Address,OUT_X_H);
  xLSB = readRegister(L3G4200D_Address,OUT_X_L);
  x=make16(xMSB,xLSB);
  yMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegister(L3G4200D_Address, OUT_Y_L);
  y=make16(yMSB,yLSB);
  zMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  zLSB = readRegister(L3G4200D_Address, OUT_Z_L);
  z=make16(zMSB,zLSB);

printf("%lu, %lu, %lu\n",x,y,z);
}


Tks! Very Happy

if i get it for sure i'll post here then to share the program working properly!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 7:21 pm     Reply with quote

You're using the wrong printf format string to display a float.
Look at the help file for printf.
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 8:41 pm     Reply with quote

I know it! Embarassed
I made this mistake by inattention. Maybe it resolved the problem, but im not sure...I continue unsafe about the results!

My current program is below, please, have a look!

Tks!! Very Happy


Code:

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D

signed long x=0;
signed long y=0;
signed long z=0;
int xMSB;
int xLSB;
int yMSB;
int yLSB;
int zMSB;
int zLSB;

void setupL3G4200D(int scale);
void writeRegister(int deviceAddress, int address, int val);
int readRegister(int deviceAddress, int address);
void gyro_values();

void main(){

setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

while(1){
gyro_values();
}
}

void setupL3G4200D(int scale){

  writeRegister(L3G4200D_Address, CTRL_REG1, WHO_AM_I);   // 100Hz, 12.5, Power Up
  writeRegister(L3G4200D_Address, CTRL_REG2, 0x0);
  writeRegister(L3G4200D_Address, CTRL_REG3, 0x8);
   
  if(scale == 250){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x00);
  }else if(scale == 500){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x10);
  }else{
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x20);
}
  writeRegister(L3G4200D_Address, CTRL_REG5, 0x0);
 
}

void writeRegister(int deviceAddress, byte address, byte val){
i2c_start();// start transmission to device
i2c_write(deviceAddress);// send device address
i2c_write(address);// send register address
i2c_write(val);// send value to write
i2c_stop();// end transmission
}

int readRegister(int deviceAddress, byte address){
int v;
i2c_start(); // start transmission to device
i2c_write(deviceAddress); //This is where you have to _write_ the register number you want
i2c_write(address); // register to read
i2c_start(); //restart - the bus is now set to _read_
i2c_write(deviceAddress + 1); //now turn the bus round
v = i2c_read(0);
i2c_stop(); //This will update x, y, and z with new values
return v;
}

void gyro_values(){

  xMSB = readRegister(L3G4200D_Address,OUT_X_H);
  xLSB = readRegister(L3G4200D_Address,OUT_X_L);
  x=make16(xMSB,xLSB);
  yMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegister(L3G4200D_Address, OUT_Y_L);
  y=make16(yMSB,yLSB);
  zMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  zLSB = readRegister(L3G4200D_Address, OUT_Z_L);
  z=make16(zMSB,zLSB);

printf("%lu, %lu, %lu\n",x,y,z);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 8:50 pm     Reply with quote

Quote:

signed long x=0;
signed long y=0;
signed long z=0;

printf("%lu, %lu, %lu\n",x,y,z);

Please download the CCS manual.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf

Go to the printf section on page 189 and carefully read the Format
section. Then choose the correct format string (it's not %lu) for
your variables.
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Thu Feb 27, 2014 11:38 am     Reply with quote

Tks PCM programmer!! I read the manual and I made changes. The results seems too much better now!

I'm comparing the results by PIC and by Arduino and the results by PIC for the Z axis are too different than by Arduino! (Results for X and Y axis are similar between both microcontroler)

I'm sure the program for arduino is correct because i tested it by Processing and it works properly.

I made the comparison test without moving the sensor and then I took 200 samples by each microcontroler:

by PIC i got results between -255 and -239
by Arduino i got results between -1 and 15

could someone help me again?

newer code:

Code:

#include <18F4520.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(crystal=20000000,restart_wdt)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master, FORCE_HW, RESTART_WDT)
#use i2c(sda=PIN_B0, scl=PIN_B1)

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D

signed long int x=0;
signed long int y=0;
signed long int z=0;
int xMSB;
int xLSB;
int yMSB;
int yLSB;
int zMSB;
int zLSB;

void setupL3G4200D(int scale);
void writeRegister(int deviceAddress, int address, int val);
int readRegister(int deviceAddress, int address);
void gyro_values();

void main(){

setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

while(1){
gyro_values();
}
}

void setupL3G4200D(int scale){

  writeRegister(L3G4200D_Address, CTRL_REG1, WHO_AM_I);   // 100Hz, 12.5, Power Up
  writeRegister(L3G4200D_Address, CTRL_REG2, 0x0);
  writeRegister(L3G4200D_Address, CTRL_REG3, 0x8);
   
  if(scale == 250){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x00);
  }else if(scale == 500){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x10);
  }else{
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x20);
}
  writeRegister(L3G4200D_Address, CTRL_REG5, 0x0);
 
}

void writeRegister(int deviceAddress, byte address, byte val){
i2c_start();// start transmission to device
i2c_write(deviceAddress);// send device address
i2c_write(address);// send register address
i2c_write(val);// send value to write
i2c_stop();// end transmission
}

int readRegister(int deviceAddress, byte address){
int v;
i2c_start(); // start transmission to device
i2c_write(deviceAddress); //This is where you have to _write_ the register number you want
i2c_write(address); // register to read
i2c_start(); //restart - the bus is now set to _read_
i2c_write(deviceAddress + 1); //now turn the bus round
v = i2c_read(0);
i2c_stop(); //This will update x, y, and z with new values
return v;
}

void gyro_values(){

  xMSB = readRegister(L3G4200D_Address,OUT_X_H);
  xLSB = readRegister(L3G4200D_Address,OUT_X_L);
  x=make16(xMSB,xLSB);
  yMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegister(L3G4200D_Address, OUT_Y_L);
  y=make16(yMSB,yLSB);
  zMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  zLSB = readRegister(L3G4200D_Address, OUT_Z_L);
  z=make16(zMSB,zLSB);

printf("%ld, %ld, %ld\n",x,y,z);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 27, 2014 2:26 pm     Reply with quote

Going through your code, I see a lot errors.

Quote:
writeRegister(L3G4200D_Address, CTRL_REG1, WHO_AM_I);

WHO_AM_I is actually a register, with the address of 0x0F. It's just a
coincidence that 0xF is what you want to write to CTRL_REG1. Don't
do this type of thing in programming. Don't grab any convenient symbol
that accidently happens to match the constant that you want.
Either create a new symbol, such as CTRL_REG1_INIT_VALUE
or put in the direct constant. Example:
Code:
writeRegister(L3G4200D_Address, CTRL_REG1, 0x0F);
 


Quote:
#use i2c(Master, FORCE_HW, RESTART_WDT)
#use i2c(sda=PIN_B0, scl=PIN_B1)

There is no sequential setup with #use i2c(). Without streams, only the
last #use i2c() statement will be used by the compiler. Then, your 2nd
line, which is the one used, is incomplete. It's missing "Master", and it
probably would be wise to add "SLOW" as a parameter. it's also invoking
software i2c. Hardware i2c is only available on pins C3 and C4 on the 18F4520.

Also, another question. Your PIC runs at +5v, but your L3G4200D runs
at 3.3v. There are things that can be done to make 3.3v i2c run on
a 5v PIC. But do you have an L3G4200D board that already has level
converters on it for the i2c ? If so, then it should work OK. But if not,
then we need to know the size of your i2c pull-ups and the voltage that
they are connected to. (+3.3v or +5v).



Quote:

zMSB = readRegister(L3G4200D_Address, OUT_Y_H);
zLSB = readRegister(L3G4200D_Address, OUT_Z_L);
z=make16(zMSB,zLSB);

A bug here is that your zMSB is being taken from the OUT_Y_H register.
That comes from the copy, paste, edit, goof-on-the-edit errors that
programmers are subject to, unless they watch it.
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Fri Mar 07, 2014 1:20 pm     Reply with quote

Sorry about delay, I was having a funny carnival here in brazil Very Happy

Tks for the answer! I got it and now the program is working well!

As promised, the driver follows below but it's just to read the registers. I'll keep working in this program to process the data to know the angles. When I finish it i post at the Code Library!

Code:

#include <18F4520.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(crystal=20000000,restart_wdt)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(master, fast, sda=PIN_C4, scl=PIN_C3)

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D

signed long int x=0;
signed long int y=0;
signed long int z=0;
int xMSB;
int xLSB;
int yMSB;
int yLSB;
int zMSB;
int zLSB;

void setupL3G4200D(int scale);
void writeRegister(int deviceAddress, int address, int val);
int readRegister(int deviceAddress, int address);
void gyro_values();

void main(){

setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

while(1){
gyro_values();
}
}

void setupL3G4200D(int scale){

  writeRegister(L3G4200D_Address, CTRL_REG1, 0x0F);   // 100Hz, 12.5, Power Up
  writeRegister(L3G4200D_Address, CTRL_REG2, 0x0);
  writeRegister(L3G4200D_Address, CTRL_REG3, 0x8);
   
  if(scale == 250){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x00);
  }else if(scale == 500){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x10);
  }else{
    writeRegister(L3G4200D_Address, CTRL_REG4, 0x20);
}
  writeRegister(L3G4200D_Address, CTRL_REG5, 0x0);
 
}

void writeRegister(int deviceAddress, byte address, byte val){
i2c_start();// start transmission to device
i2c_write(deviceAddress);// send device address
i2c_write(address);// send register address
i2c_write(val);// send value to write
i2c_stop();// end transmission
}

int readRegister(int deviceAddress, byte address){
int v;
i2c_start(); // start transmission to device
i2c_write(deviceAddress); //This is where you have to _write_ the register number you want
i2c_write(address); // register to read
i2c_start(); //restart - the bus is now set to _read_
i2c_write(deviceAddress + 1); //now turn the bus round
v = i2c_read(0);
i2c_stop(); //This will update x, y, and z with new values
return v;
}

void gyro_values(){

  xMSB = readRegister(L3G4200D_Address,OUT_X_H);
  xLSB = readRegister(L3G4200D_Address,OUT_X_L);
  x=make16(xMSB,xLSB);
  yMSB = readRegister(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegister(L3G4200D_Address, OUT_Y_L);
  y=make16(yMSB,yLSB);
  zMSB = readRegister(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegister(L3G4200D_Address, OUT_Z_L);
  z=make16(zMSB,zLSB);

printf("%ld, %ld, %ld\n",x,y,z);
}
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Wed Mar 12, 2014 6:30 pm     Reply with quote

Hi everyone again!

I keep working on the same program to process the data to know the angles from the values read but i've gotten strange angles. The results is analysed by Processing 2.

whole this program is translate of another program for Arduino which is working properly (also tested by Processing 2 using the same code)

Could someone help me to find the error?

Thanks!!

Code:

#include <18F4520.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(crystal=20000000,restart_wdt)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(master, fast, sda=PIN_C4, scl=PIN_C3)
#use timer(timer=1,tick=1ms,bits=16,noisr)

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D
int xMSB;
int xLSB;
int yMSB;
int yLSB;
int zMSB;
int zLSB;
int sampleTime=20;
int rate_x;
int rate_y;
int rate_z;
int sampleNum=5;
int dc_offset_x=0;
int dc_offset_y=0;
int dc_offset_z=0;
int prev_rate_x=0;
int prev_rate_y=0;
int prev_rate_z=0;

signed long int gyrogx=0;
signed long int gyrogy=0;
signed long int gyrogz=0;

float noise=0;
float x=0;
float y=0;
float z=0;

unsigned long time;
unsigned int current_time;

void initializingL3G4200D();
void setupL3G4200D(int scale);
void writeRegisterI2C(int deviceAddress, int address, int val);
int readRegisterI2C(int deviceAddress, int address);
void gyroscope();

void main(){

initializingL3G4200D();
set_ticks(0x00000000);
while(1){
output_high(PIN_A0);
gyroscope();
output_low(PIN_A0);
}
}

void initializingL3G4200D(){
int n;

setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

for(n=0;n<sampleNum;n++){

  xMSB = readRegisterI2C(L3G4200D_Address,OUT_X_H);
  xLSB = readRegisterI2C(L3G4200D_Address,OUT_X_L);
  gyrogx=make16(xMSB,xLSB);
  yMSB = readRegisterI2C(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegisterI2C(L3G4200D_Address, OUT_Y_L);
  gyrogy=make16(yMSB,yLSB);
  zMSB = readRegisterI2C(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegisterI2C(L3G4200D_Address, OUT_Z_L);
  gyrogz=make16(zMSB,zLSB);

dc_offset_x+=gyrogx;
dc_offset_y+=gyrogy;
dc_offset_z+=gyrogz;
}
dc_offset_x=dc_offset_x/sampleNum;
dc_offset_y=dc_offset_y/sampleNum;
dc_offset_z=dc_offset_z/sampleNum;
for(n=0;n<sampleNum;n++){
  xMSB = readRegisterI2C(L3G4200D_Address,OUT_X_H);
  xLSB = readRegisterI2C(L3G4200D_Address,OUT_X_L);
  gyrogx=make16(xMSB,xLSB);
  yMSB = readRegisterI2C(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegisterI2C(L3G4200D_Address, OUT_Y_L);
  gyrogy=make16(yMSB,yLSB);
  zMSB = readRegisterI2C(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegisterI2C(L3G4200D_Address, OUT_Z_L);
  gyrogz=make16(zMSB,zLSB);
  if((gyrogz-dc_offset_z)>noise)
  noise=gyrogz-dc_offset_z;
else if((gyrogz-dc_offset_z)<-noise)
noise=-gyrogz-dc_offset_z;
}
noise=noise/100; //gyro returns hundredths of degrees/sec
delay_ms(10); //wait for the sensor to be ready
}

void setupL3G4200D(int scale){

  writeRegisterI2C(L3G4200D_Address, CTRL_REG1, 0x0F);   // 100Hz, 12.5, Power Up
  writeRegisterI2C(L3G4200D_Address, CTRL_REG2, 0x0);
  writeRegisterI2C(L3G4200D_Address, CTRL_REG3, 0x8);
   
  if(scale == 250){
    writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x00);
  }else if(scale == 500){
    writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x10);
  }else{
    writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x20);
}
  writeRegisterI2C(L3G4200D_Address, CTRL_REG5, 0x0);
 
}

void gyroscope(){
current_time=get_ticks();

if((current_time-time)> sampleTime){
set_ticks(0x00000000);
time=get_ticks(); // update the time to get the next sample

  xMSB = readRegisterI2C(L3G4200D_Address,OUT_X_H);
  xLSB = readRegisterI2C(L3G4200D_Address,OUT_X_L);
  gyrogx=make16(xMSB,xLSB);
  yMSB = readRegisterI2C(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegisterI2C(L3G4200D_Address, OUT_Y_L);
  gyrogy=make16(yMSB,yLSB);
  zMSB = readRegisterI2C(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegisterI2C(L3G4200D_Address, OUT_Z_L);
  gyrogz=make16(zMSB,zLSB);

rate_x=(gyrogx-dc_offset_x)/100;
rate_y=(gyrogy-dc_offset_y)/100;
rate_z=(gyrogz-dc_offset_z)/100;

if(rate_x >= noise || rate_x <= -noise)
x += ((float)(prev_rate_x + rate_x) * sampleTime * 1.32) / 2000;
if(rate_y >= noise || rate_y <= -noise)
y += ((float)(prev_rate_y + rate_y) * sampleTime * 1.32) / 2000;
if(rate_z >= noise || rate_z <= -noise)
z += ((float)(prev_rate_z + rate_z) * sampleTime * 1.32) / 2000;

// remember the current speed for the next loop rate integration.
prev_rate_x = rate_x;
prev_rate_y = rate_y;
prev_rate_z = rate_z;

// Keep our angle between 0-359 degrees
if (x < 0)
x += 360;
else if (x >= 360)
x -= 360;
if (y < 0)
y += 360;
else if (y >= 360)
y -= 360;
if (z < 0)
z += 360;
else if (z >= 360)
z -= 360;

printf("%f;%f;%f\n",x,y,z);
delay_ms(1); //Just here to slow down the serial to make it more readable
}
}

void writeRegisterI2C(int deviceAddress, byte address, byte val){
i2c_start();// start transmission to device
i2c_write(deviceAddress);// send device address
i2c_write(address);// send register address
i2c_write(val);// send value to write
i2c_stop();// end transmission
}

int readRegisterI2C(int deviceAddress, byte address){
int v;
i2c_start(); // start transmission to device
i2c_write(deviceAddress); //This is where you have to _write_ the register number you want
i2c_write(address); // register to read
i2c_start(); //restart - the bus is now set to _read_
i2c_write(deviceAddress + 1); //now turn the bus round
v = i2c_read(0);
i2c_stop(); //This will update x, y, and z with new values
return v;
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 12, 2014 6:41 pm     Reply with quote

Quote:
but i've gotten strange angles

If you have a problem like this, always:

1. Post the bad values that you're getting.

2. Post the good values that you expected to get (but didn't).

3. It would be helpful if you posted the raw values that are read
from your unit, before you do all the calculations. Add some printf
statements and get the raw values (gyrogx, gyrogy, gyrogz).
And post the output from your calculations that comes from those raw
values, and explain what you don't like about the calculated output.

4. Post the test conditions. Is the unit sitting on your table and not moving ?

5. Post the CCS compiler version that you're using for your latest test.
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Thu Mar 13, 2014 1:19 pm     Reply with quote

Thanks for the answer.

I can't identify the strange values observing them because the values gotten are between 0º and 360º around each axis as expected, but I know they aren't good because the drawing by Processing isn't moving correctly as by Arduino.

I added some printf to get the raw values (gyrogx, gyrogy, gyrogz) and I compared them with the raw values gotten by Arduino (with the original program before translate). Without moving the sensor, the values should be almost the same but it's not. Following is the comparison of results:

x: between -18 and 89 by Arduino and between 0 and 17 by PIC
y: between -52 and 53 by Arduino and between -12 and 2 by PIC
z: between -2 and 99 by Arduino -12 and 2 between 9 and 24 by PIC

I'm using the CCS Compiler version 5.018

Following is the code with the printf added
Code:

#include <18F4520.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(crystal=20000000,restart_wdt)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(master, fast, sda=PIN_C4, scl=PIN_C3)
#use timer(timer=1,tick=1ms,bits=16,noisr)

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D
int xMSB;
int xLSB;
int yMSB;
int yLSB;
int zMSB;
int zLSB;
int sampleTime=20;
int rate_x;
int rate_y;
int rate_z;
int sampleNum=500;
int dc_offset_x=0;
int dc_offset_y=0;
int dc_offset_z=0;
int prev_rate_x=0;
int prev_rate_y=0;
int prev_rate_z=0;

signed long int gyrogx=0;
signed long int gyrogy=0;
signed long int gyrogz=0;

float noise=0;
float x=0;
float y=0;
float z=0;

unsigned long time;
unsigned int current_time;

void initializingL3G4200D();
void setupL3G4200D(int scale);
void writeRegisterI2C(int deviceAddress, int address, int val);
int readRegisterI2C(int deviceAddress, int address);
void gyroscope();

void main(){

initializingL3G4200D();
set_ticks(0x00000000);
while(1){
output_high(PIN_A0);
gyroscope();
output_low(PIN_A0);
}
}

void initializingL3G4200D(){
int n;

setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

for(n=0;n<sampleNum;n++){

  xMSB = readRegisterI2C(L3G4200D_Address,OUT_X_H);
  xLSB = readRegisterI2C(L3G4200D_Address,OUT_X_L);
  gyrogx=make16(xMSB,xLSB);
  yMSB = readRegisterI2C(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegisterI2C(L3G4200D_Address, OUT_Y_L);
  gyrogy=make16(yMSB,yLSB);
  zMSB = readRegisterI2C(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegisterI2C(L3G4200D_Address, OUT_Z_L);
  gyrogz=make16(zMSB,zLSB);

printf("%ld;%ld;%ld\n",gyrogx,gyrogy,gyrogz);

dc_offset_x+=gyrogx;
dc_offset_y+=gyrogy;
dc_offset_z+=gyrogz;
}
dc_offset_x=dc_offset_x/sampleNum;
dc_offset_y=dc_offset_y/sampleNum;
dc_offset_z=dc_offset_z/sampleNum;
for(n=0;n<sampleNum;n++){
  xMSB = readRegisterI2C(L3G4200D_Address,OUT_X_H);
  xLSB = readRegisterI2C(L3G4200D_Address,OUT_X_L);
  gyrogx=make16(xMSB,xLSB);
  yMSB = readRegisterI2C(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegisterI2C(L3G4200D_Address, OUT_Y_L);
  gyrogy=make16(yMSB,yLSB);
  zMSB = readRegisterI2C(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegisterI2C(L3G4200D_Address, OUT_Z_L);
  gyrogz=make16(zMSB,zLSB);
  if((gyrogz-dc_offset_z)>noise)
  noise=gyrogz-dc_offset_z;
else if((gyrogz-dc_offset_z)<-noise)
noise=-gyrogz-dc_offset_z;
}
noise=noise/100; //gyro returns hundredths of degrees/sec
delay_ms(10); //wait for the sensor to be ready
}

void setupL3G4200D(int scale){

  writeRegisterI2C(L3G4200D_Address, CTRL_REG1, 0x0F);   // 100Hz, 12.5, Power Up
  writeRegisterI2C(L3G4200D_Address, CTRL_REG2, 0x0);
  writeRegisterI2C(L3G4200D_Address, CTRL_REG3, 0x8);
   
  if(scale == 250){
    writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x00);
  }else if(scale == 500){
    writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x10);
  }else{
    writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x20);
}
  writeRegisterI2C(L3G4200D_Address, CTRL_REG5, 0x0);
 
}

void gyroscope(){
current_time=get_ticks();

if((current_time-time)> sampleTime){
set_ticks(0x00000000);
time=get_ticks(); // update the time to get the next sample

  xMSB = readRegisterI2C(L3G4200D_Address,OUT_X_H);
  xLSB = readRegisterI2C(L3G4200D_Address,OUT_X_L);
  gyrogx=make16(xMSB,xLSB);
  yMSB = readRegisterI2C(L3G4200D_Address, OUT_Y_H);
  yLSB = readRegisterI2C(L3G4200D_Address, OUT_Y_L);
  gyrogy=make16(yMSB,yLSB);
  zMSB = readRegisterI2C(L3G4200D_Address, OUT_Z_H);
  zLSB = readRegisterI2C(L3G4200D_Address, OUT_Z_L);
  gyrogz=make16(zMSB,zLSB);

rate_x=(gyrogx-dc_offset_x)/100;
rate_y=(gyrogy-dc_offset_y)/100;
rate_z=(gyrogz-dc_offset_z)/100;

if(rate_x >= noise || rate_x <= -noise)
x += ((float)(prev_rate_x + rate_x) * sampleTime * 1.32) / 2000;
if(rate_y >= noise || rate_y <= -noise)
y += ((float)(prev_rate_y + rate_y) * sampleTime * 1.32) / 2000;
if(rate_z >= noise || rate_z <= -noise)
z += ((float)(prev_rate_z + rate_z) * sampleTime * 1.32) / 2000;

// remember the current speed for the next loop rate integration.
prev_rate_x = rate_x;
prev_rate_y = rate_y;
prev_rate_z = rate_z;

// Keep our angle between 0-359 degrees
if (x < 0)
x += 360;
else if (x >= 360)
x -= 360;
if (y < 0)
y += 360;
else if (y >= 360)
y -= 360;
if (z < 0)
z += 360;
else if (z >= 360)
z -= 360;

//printf("%f;%f;%f\n",x,y,z);
delay_ms(1); //Just here to slow down the serial to make it more readable
}
}

void writeRegisterI2C(int deviceAddress, byte address, byte val){
i2c_start();// start transmission to device
i2c_write(deviceAddress);// send device address
i2c_write(address);// send register address
i2c_write(val);// send value to write
i2c_stop();// end transmission
}

int readRegisterI2C(int deviceAddress, byte address){
int v;
i2c_start(); // start transmission to device
i2c_write(deviceAddress); //This is where you have to _write_ the register number you want
i2c_write(address); // register to read
i2c_start(); //restart - the bus is now set to _read_
i2c_write(deviceAddress + 1); //now turn the bus round
v = i2c_read(0);
i2c_stop(); //This will update x, y, and z with new values
return v;
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 13, 2014 1:40 pm     Reply with quote

Quote:

I compared them with the raw values gotten by Arduino (with the original
program before translate).

1. Post a link to the Arduino program.

2. Post a link to the Arduino board's website.

3. If bought the PIC board, post a link to the PIC board's website.

4. In both your test setups, Arduino and PIC, are you using the same
Polulu L3G4200D board ? And the only difference is one test setup has a
PIC board connected to the Polulu and the other setup has an Arduino
board connected to the same Polulu board ?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Mar 14, 2014 5:19 am     Reply with quote

Code:
int L3G4200D_Address = 0xD2; //I2C address of the L3G4200D
int sampleTime=20;
int sampleNum=500;

These are constants, change them to a 'const int' or #define. Doing so makes your program easier to read and will prevent you from making programming errors where you accidentally change the value. Also the compiler can create more effective code (saves 52 bytes in your program).
Since these have become a constant now, it is good practice to write the names with all capital characters:
Code:
#define L3G4200D_ADDRESS   0xD2  //I2C address of the L3G4200D
#define SAMPLE_TIME        20
#define SAMPLE_NUM         500


- You are using types int, byte, unsigned long. This is confusing, especially when converting from other processors. For example an int on many processors is 16 or 32 bit but only 8 bit on the PIC. Good practice is to use types like int8 and int16 because these are equal between all processors. On the Arduino an 'int' is a 16-bit signed integer, on the PIC an 'int' is 8-bit unsigned integer.
- Doing so you will find bugs in about 11 variables:
Code:
void initializingL3G4200D(){
   int n;
   
...   
   for(n=0;n<SAMPLE_NUM;n++){
Since SAMPLE_NUM == 500, n must be of the type 'long int' or better: int16

And another bug:
Code:
   setupL3G4200D(2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec
...
void setupL3G4200D(int scale){
Should be int16 instead ...

And the same applies to:
- rate_*
- prev_rate_*
Note that the following code is in a 500 times loop:
Code:
      dc_offset_x+=gyrogx;
      dc_offset_y+=gyrogy;
      dc_offset_z+=gyrogz;
dc_offset_* must therefor be a signed int32.

Code:
unsigned int current_time;
Is wrong because you defined your timer as 16 bit, now the read value can only store 8 bits.

Code:
   if((current_time-time)> SAMPLE_TIME){
      set_ticks(0);
      time=get_ticks(); // update the time to get the next sample
This makes little sense. time is only updated in the part of code shown here. One line above it is always set to 0, so time will always be 0. This code can be simplified by removing the time variable:
Code:
   if(current_time > SAMPLE_TIME){
      set_ticks(0);  // reset sample timer


- Add fuse HS. You are just lucky your project is running because this is also the default oscillator setting when not specified.
- Add fuse PUT. This Power Up delay ensures a more stable program start and is good practice to always add when using an external crystal.
- Watchdog is not used. Remove WDT128 fuse and restart_wdt from #delay for easier reading and saving a few bytes.
- Always add ERRORS to #use rs232, it will prevent the hardware UART from locking up on receive buffer overflows.
- Fix indentation
- Just personal preference: in #delay 20MHz is easier to read clock frequency than 20000000
- Remove includes for stdlib.h, math.h and stdio.h. These are not used and removing makes your program easier to read. Also saves 4 bytes and almost 4000 lines in the *.lst file.

Code:
void setupL3G4200D(int16 scale){
   writeRegisterI2C(L3G4200D_Address, CTRL_REG1, 0x0F);   // 100Hz, 12.5, Power Up
   writeRegisterI2C(L3G4200D_Address, CTRL_REG2, 0x0);
   writeRegisterI2C(L3G4200D_Address, CTRL_REG3, 0x8);
   
   if(scale == 250){
      writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x00);
   }else if(scale == 500){
      writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x10);
   }else{
      writeRegisterI2C(L3G4200D_Address, CTRL_REG4, 0x20);
   }
   writeRegisterI2C(L3G4200D_Address, CTRL_REG5, 0x0);
}
This function works fine (I think) but what I don't like is that it accepts an int16 for input (65536 combinations) while internally it just checks for 3 different values.
More elegant and efficient is to use defines for the 3 settings, or even better an enum.
Code:
enum Scale {      // 250, 500 or 2000 deg/sec
   SCALE_250=0x00,
   SCALE_500=0x10,
   SCALE_2000=0x20
};   

...

   setupL3G4200D(SCALE_2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec

...

void setupL3G4200D(Scale scale){
   writeRegisterI2C(L3G4200D_Address, CTRL_REG1, 0x0F);   // 100Hz, 12.5, Power Up
   writeRegisterI2C(L3G4200D_Address, CTRL_REG2, 0x0);
   writeRegisterI2C(L3G4200D_Address, CTRL_REG3, 0x8);
   writeRegisterI2C(L3G4200D_Address, CTRL_REG4, scale);
   writeRegisterI2C(L3G4200D_Address, CTRL_REG5, 0x0);
}


Code:
set_ticks(0x00000000);
Not an error, but since you defined ticks as a 16 bit size, why set it here with a 32-bit value?
I prefer the easier to read: set_ticks(0);

With all these changes your program becomes as follows:
Code:
#include <18F4520.h>
#case

#FUSES HS
#FUSES PUT
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(crystal=20MHz)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#use i2c(master, fast, sda=PIN_C4, scl=PIN_C3)
#use timer(timer=1,tick=1ms,bits=16,noisr)

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define WHO_AM_I 0x0F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

#define L3G4200D_ADDRESS   0xD2  //I2C address of the L3G4200D
#define SAMPLE_TIME        20
#define SAMPLE_NUM         500

enum Scale {      // 250, 500 or 2000 deg/sec
   SCALE_250=0x00,
   SCALE_500=0x10,
   SCALE_2000=0x20
};   

int8 xMSB;
int8 xLSB;
int8 yMSB;
int8 yLSB;
int8 zMSB;
int8 zLSB;
signed int16 rate_x;
signed int16 rate_y;
signed int16 rate_z;
signed int32 dc_offset_x=0;
signed int32 dc_offset_y=0;
signed int32 dc_offset_z=0;
signed int16 prev_rate_x=0;
signed int16 prev_rate_y=0;
signed int16 prev_rate_z=0;


signed int16 gyrogx=0;
signed int16 gyrogy=0;
signed int16 gyrogz=0;

float noise=0;
float x=0;
float y=0;
float z=0;

void initializingL3G4200D();
void setupL3G4200D(Scale scale);
void writeRegisterI2C(int8 deviceAddress, int8 address, int8 val);
int readRegisterI2C(int8 deviceAddress, int8 address);
void gyroscope();

void main(){
   initializingL3G4200D();
   set_ticks(0);
   while(1){
      output_high(PIN_A0);
      gyroscope();
      output_low(PIN_A0);
   }
}

void initializingL3G4200D(){
   int16 n;
   
   setupL3G4200D(SCALE_2000); // Configure L3G4200  - 250, 500 or 2000 deg/sec
   
   for(n=0;n<SAMPLE_NUM;n++){
     xMSB = readRegisterI2C(L3G4200D_ADDRESS,OUT_X_H);
     xLSB = readRegisterI2C(L3G4200D_ADDRESS,OUT_X_L);
     gyrogx=make16(xMSB,xLSB);
     yMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Y_H);
     yLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Y_L);
     gyrogy=make16(yMSB,yLSB);
     zMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Z_H);
     zLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Z_L);
     gyrogz=make16(zMSB,zLSB);
   
      printf("%ld;%ld;%ld\n",gyrogx,gyrogy,gyrogz);
     
      dc_offset_x+=gyrogx;
      dc_offset_y+=gyrogy;
      dc_offset_z+=gyrogz;
   }

   dc_offset_x=dc_offset_x/SAMPLE_NUM;
   dc_offset_y=dc_offset_y/SAMPLE_NUM;
   dc_offset_z=dc_offset_z/SAMPLE_NUM;
   for(n=0;n<SAMPLE_NUM;n++){
      xMSB = readRegisterI2C(L3G4200D_ADDRESS,OUT_X_H);
      xLSB = readRegisterI2C(L3G4200D_ADDRESS,OUT_X_L);
      gyrogx=make16(xMSB,xLSB);
      yMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Y_H);
      yLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Y_L);
      gyrogy=make16(yMSB,yLSB);
      zMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Z_H);
      zLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Z_L);
      gyrogz=make16(zMSB,zLSB);
      if((gyrogz-dc_offset_z)>noise)
         noise=gyrogz-dc_offset_z;
      else if((gyrogz-dc_offset_z)<-noise)
         noise=-gyrogz-dc_offset_z;
   }
   noise=noise/100; //gyro returns hundredths of degrees/sec
   delay_ms(10); //wait for the sensor to be ready
}

void setupL3G4200D(Scale scale){
   writeRegisterI2C(L3G4200D_ADDRESS, CTRL_REG1, 0x0F);   // 100Hz, 12.5, Power Up
   writeRegisterI2C(L3G4200D_ADDRESS, CTRL_REG2, 0x0);
   writeRegisterI2C(L3G4200D_ADDRESS, CTRL_REG3, 0x8);
   writeRegisterI2C(L3G4200D_ADDRESS, CTRL_REG4, scale);
   writeRegisterI2C(L3G4200D_ADDRESS, CTRL_REG5, 0x0);
}

void gyroscope(){
   int16 current_time=get_ticks();
   
   if(current_time > SAMPLE_TIME){
      set_ticks(0);  // reset sample timer
     
      xMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_X_H);
      xLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_X_L);
      gyrogx=make16(xMSB,xLSB);
      yMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Y_H);
      yLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Y_L);
      gyrogy=make16(yMSB,yLSB);
      zMSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Z_H);
      zLSB = readRegisterI2C(L3G4200D_ADDRESS, OUT_Z_L);
      gyrogz=make16(zMSB,zLSB);
     
      rate_x=(gyrogx-dc_offset_x)/100;
      rate_y=(gyrogy-dc_offset_y)/100;
      rate_z=(gyrogz-dc_offset_z)/100;
     
      if(rate_x >= noise || rate_x <= -noise)
         x += ((float)(prev_rate_x + rate_x) * SAMPLE_TIME * 1.32) / 2000;
      if(rate_y >= noise || rate_y <= -noise)
         y += ((float)(prev_rate_y + rate_y) * SAMPLE_TIME * 1.32) / 2000;
      if(rate_z >= noise || rate_z <= -noise)
         z += ((float)(prev_rate_z + rate_z) * SAMPLE_TIME * 1.32) / 2000;
     
      // remember the current speed for the next loop rate integration.
      prev_rate_x = rate_x;
      prev_rate_y = rate_y;
      prev_rate_z = rate_z;
     
      // Keep our angle between 0-359 degrees
      if (x < 0)
         x += 360;
      else if (x >= 360)
         x -= 360;
      if (y < 0)
         y += 360;
      else if (y >= 360)
         y -= 360;
      if (z < 0)
         z += 360;
      else if (z >= 360)
         z -= 360;
     
      //printf("%f;%f;%f\n",x,y,z);
      delay_ms(1); //Just here to slow down the serial to make it more readable
   }
}

void writeRegisterI2C(int8 deviceAddress, int8 address, int8 val){
   i2c_start();               // start transmission to device
   i2c_write(deviceAddress);  // send device address
   i2c_write(address);        // send register address
   i2c_write(val);            // send value to write
   i2c_stop();                // end transmission
}

int8 readRegisterI2C(int8 deviceAddress, int8 address){
   int v;
   i2c_start();                  // start transmission to device
   i2c_write(deviceAddress);     // This is where you have to _write_ the register number you want
   i2c_write(address);           // register to read
   i2c_start();                  // restart - the bus is now set to _read_
   i2c_write(deviceAddress + 1); // now turn the bus round
   v = i2c_read(0);
   i2c_stop();                   // This will update x, y, and z with new values
   return v;
}
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Mon Mar 17, 2014 1:07 pm     Reply with quote

Thanks very much for all answers! I understood well everything.
With that changes the program is working fine now. I wont post the code because it's identical to the last post by ckielstra.
hamid9543



Joined: 31 Jan 2013
Posts: 63

View user's profile Send private message

get_tick
PostPosted: Mon Mar 24, 2014 1:10 pm     Reply with quote

thanks very very very ....much!
it help me so much to solve many my problem with l3g4200d.but can you explain about get_tick()?
i read ccs help and write code
Code:

#define.......
#use delay(crystal=20MHz)
#use timer(timer=1,tick=1ms,bits=16,noisr)

void main()
{
set_ticks(0);
while(true)
{
int16 current_time=get_ticks();
lcd_gotoxy(5,1);printf(lcd_putc,"t=%ld    ",current_time); 
}

}

how work get_tick() function and how much it does return ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 24, 2014 2:13 pm     Reply with quote

Download the CCS manual:
https://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Use the search function of the Adobe reader to search for get_ticks().
Then click on the Table of Contents entry for get_ticks() and you will
go to the description.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group