Pages: [1]   Go Down
Author Topic: Problems with a i2c accelerometer...  (Read 872 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys,
I' ve a problem with an accelerometer, really it' s a magneto with a built-in accelerometer for tilt-compensated output but the two devices work in two different i2c address so I think it' s fine... I' m working with this device LSM303DLH, and I wrote this code to get the accelerometer output...
Code:
#include <Wire.h>
#define AXEL 0x18
//Funzione di setup
// Accelerometer address: 0011000b  0x18
// Magnetometer address:  0011110b  0x1E
// Registi di setup acceletometro:
// CTRL_REG1_A address:   0x20  parameters:  0x27
// CTRL_REG4_A address:   0x23  parameters:  0x40
//
// Registri di setup magnetometro:
// CRA_REG_M  address:   0x00  parameters:  0x14
// MR_REG_M   address:   0x02  parameters:  0x00
void lsmsetup(byte address, byte reg, byte setting);
void lsmsetup(byte address, byte reg, byte setting){
  Wire.beginTransmission(address);
  Wire.send(reg);
  Wire.send(setting);
  Wire.endTransmission();
}

//Funzione di lettura dei dati da un registro
int reading(int address, byte reg);
int reading(int address, byte reg){
  byte value;
  Wire.beginTransmission(address);
  Wire.send(reg);
  Wire.endTransmission();
  Wire.requestFrom(address, 1);
  while(Wire.available()){
    value=Wire.receive();
  }return value;
}

byte xlow, ylow, zlow, xhigh, yhigh, zhigh;
int X, Y, Z;
void setup(){
  Serial.begin(9600);
  Wire.begin();
  lsmsetup(AXEL, 0x20, 0x27);
  lsmsetup(AXEL, 0x23, 0x40);
  lsmsetup(0x1E, 0x00, 0x14);
  lsmsetup(0x1E, 0x02, 0x00);
}

void loop(){
  xhigh= reading(AXEL, 0x28);
  xlow= reading(AXEL, 0x29);
  X = (xhigh << 8) + xlow;
 
  yhigh= reading(AXEL, 0x2A);
  ylow= reading(AXEL, 0x2B);
  Y = ((yhigh << 8) | ylow);
   
  zhigh= reading(AXEL, 0x2C);
  zlow= reading(AXEL, 0x2D);
  Z = ((zhigh << 8) | zlow);
 
  Serial.print(X);
  Serial.print('\t');
  Serial.print(Y);
  Serial.print('\t');
  Serial.print(Z);
  Serial.print('\n');
  delay(100);
}




/* //Funzione di lettura multipla dei dati da un registro
int multireading(byte address, byte register);
int multireading(byte address, byte register){
  int value;
  int temp[1];
  Wire.beginTransmission(address);
  Wire.send(register);
  Wire.send(register + 1);
  Wire.endTransmission();
  Wire.requestFrom(address, 2);
  while(Wire.available()){
    temp[0]=Wire.receive();
    temp[1]=Wire.receive();
  }
  temp[0] << 8;
  temp[0] += temp[1];
  value= temp[0];
  return value;
} */

I really don' t understand why the values I get are something which doesn' t match with real forces: these are some examples...
Quote
1136   368   49040
1136   384   49008
2176   1984   48256
5936   65280   51984
Respectly x, y and z axis; I don' t understand why it doesn' t give me negative numbers: I tried to join the two byte of z axis and it gives me "-something" but the "print" function says something like "51512". It' s strange, isn' t?
Here a quick start guide I followed to setup correctly the accelerometer http://www.sparkfun.com/datasheets/Sensors/Magneto/Tilt%20Compensated%20Compass.pdf
And here the datasheet:
http://www.sparkfun.com/products/10703

It' s my first time approaching with Arduino, but I' ve programmed some stuffs with C, I checked multiple times the code and I can' t find the error, someone can help me? smiley-sad Thank you,
Pentium
Logged

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 509
Posts: 31452
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looking at the data sheet you seem to have your high and low registers mixed up.
For example the X has the low at address 0x28 and high at 0x29, this does not match your code.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, you' re right: my high is actually the low; I' ve done the correction but I' ve always a problem:
Quote
61475   16386   32971
22   12288   53441
32782   4097   4288
4107   16385   45247
24582   57344   61630
53252   32768   41150
This doesn' t sound promising at all, what' s the matter? I really don' t understand smiley-sad
Logged

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 509
Posts: 31452
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't see how you get an int with a value of 61475 because as http://www.arduino.cc/en/Reference/Int says
Quote
Integers are your primary datatype for number storage, and store a 2 byte value. This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1).

So you are not making the int correctly.

I am not sure why this is but I would try:-
Y = ((int(yhigh) << smiley-cool | int(ylow));
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nope, it doesn' t work smiley-sad smiley-sad
The code is the simplest ever wrote, it' s divided just in few phases:
-Read data from register MSB X
-Store in xhigh

-Read data from register LSB X
-Store in xlow

-X= (Bitshift xhigh of 8 and merge with OR to xlow)
I really can' t understand why it gives values over the maximum int value D:
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is what you had above your current sketch? What operating system and version of Arduino are you using?

I tried to reproduce with a simple test:

Code:
void setup ()
{
  volatile byte xhigh, xlow;

  xhigh = 0xBC;
  xlow = 0x10;
  int x = (xhigh << 8) | xlow;
  Serial.begin (115200);

  Serial.print (x);
}

void loop () {}

But that printed:

Code:
-17392

As you would expect.
Logged

Worcester, MA
Offline Offline
God Member
*****
Karma: 2
Posts: 623
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I really can' t understand why it gives values over the maximum int value D:
It's not your fault, you can blame the technical writers! That IC claims to give 16 bit data but what they fail to mention is that the accelerometer data is only 12 bits so you have to shift it by 4 to the right.
Logged

I2C GPS Shield

Checkout my Open Source GPS Tracker on Kickstarter

Worcester, MA
Offline Offline
God Member
*****
Karma: 2
Posts: 623
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Try this instead, it should work.

Code:
  yhigh= reading(AXEL, 0x2A);
  ylow= reading(AXEL, 0x2B);
  Y = ((yhigh << 12) | ylow << 4) >> 4;
Logged

I2C GPS Shield

Checkout my Open Source GPS Tracker on Kickstarter

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try this instead, it should work.

Code:
  yhigh= reading(AXEL, 0x2A);
  ylow= reading(AXEL, 0x2B);
  Y = ((yhigh << 12) | ylow << 4) >> 4;

Hey, thank you a lot!!!By the way, I think you meant:
Code:
  yhigh= reading(AXEL, 0x2A);
  ylow= reading(AXEL, 0x2B);
  Y = ((yhigh << 8) | ylow ) >> 4;

I tried this code:
Code:
  xhigh= reading(AXEL, 0x29);
  xlow= reading(AXEL, 0x28);
  X = ((xhigh << 8) + xlow) >> 4;
Now, I get smaller values but I' ve still a problem: at first I know that if the first bit is equal to 1 then the number should be negative( for example B11111111 is negative!), now, this doesn' t work with my variable; don' t know why...
Logged

Worcester, MA
Offline Offline
God Member
*****
Karma: 2
Posts: 623
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
By the way, I think you meant:
Whoops, your right.
Quote
now, this doesn' t work with my variable; don' t know why...
It's because you have the high byte and low byte backwards. Using the default configuration would put the LSB at the lower address but you have the Control Register4A (0x23) set to 0x40 which swaps the LSB to the upper address and MSB to the lower address.
Logged

I2C GPS Shield

Checkout my Open Source GPS Tracker on Kickstarter

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, now it works!!!Thank you really, I would never thought of that setting, how stupid I' ve been! smiley-grin
That' s my final code, to solve the negative numbers problem...
Code:
  xhigh= reading(AXEL, 0x29);
  xlow= reading(AXEL, 0x28);
  X = ((xhigh << 8) + xlow) >> 4;
  if(X>2048){
    X -= 4096;
  }
Instead of working with the xhigh binary argument I' ve just written that if the joint value of X is over 2048( the xhigh has the first bit on!), then substract the amount of 2^12, because my final value is 12 bit composed, but it' s like a word...
smiley
« Last Edit: November 01, 2011, 03:15:19 pm by Pentium » Logged

Pages: [1]   Go Up
Jump to: