Pages: [1]   Go Down
Author Topic: [ADXL335] Measuring acceleration in Gs.  (Read 2000 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi.

I've bought an ADXL335 acceleration sensor and I want to measure the acceleration in Gs.

I've made this code:

Code:
float x, y, z;

void setup()
{
  Serial.begin(9600);     
}

void loop()
{
  x = analogRead(0) / 330.000;       
  y = analogRead(1) / 330.000;       
  z = analogRead(2) / 330.000;       
 
  Serial.println("--MEASURING ACCELERATION... AXIS X, Y, Z--");
  Serial.println(x);     
  Serial.println(y);         
  Serial.println(z);
  delay(1000);             
}

When I put the acceleration sensor on a table, I can read this values:

1.02 (X)
1.27 (Y)
1.02 (Z)

I'm not sure this code is ok. Is it? The values it returns seem to be OK.
Is there a better code to measure acceleration in Gs? Than you.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8102
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Start by calibrating your accelerometer:

Take the average of 100 raw analog readings and display them.  Measure with each axis facing UP (-1G) and DOWN (+1G).  For each axis, note the minimum and maximum values.

Then you can then convert your analog readings directly to milli-g's:

      long int x = map(analogInput(0),minimumX, maximumX, -1000, +1000);

To print in G's:  Serial.print(x/1000.0);

By calibrating you can correct for offset error and scale error.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 3
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The calibration method is really important.

If you use the 1g numbers for min and max, the only range you will get is 1g.
Any readings out of that range will not display properly.

Finding the range of +/- 1g is important.  Add them and divide by two.
That will give you the analogRead() value of 0g, assuming the accelerometer is perfectly level.
The difference between 0g and the min or max is your resolution.  How many units read/g.

For an example, on my sensor I get 401 & 611 on the X axis.  (I am using external voltage reference @ 3.6v)
Zero g would be at 506.  The resolution would be 105.  
Multiply the difference of analog reading from 0g by .0095 (1/105 or 1/resolution) and there is your g reading.
Or (analogRead(analog pin) - 506) * .0095

Here is the code I used for calculating g forces while driving.
The orientation of the Adafruit accelerometer:  X points left, Y points to the rear.
Arduino orientated natural (USB on left) and accelerometer header pins mounted next to analog pins on protoshield.

WARNING - please do not use alone while driving.  Ask a friend to be your Co-pilot or Navigator - WARNING

Code:
/*
 Designed by AB9VH James Douglas July 2012
 Unified Microsystem's ATS-1 LCD Terminal Display Shield
 with adafruit 3 axis accelerometer, external 3.3v reference
 Shows g forces while driving
 
 */

int Xaxis = 0;         // fresh data from accelerometer
int Yaxis = 0;
int Xcal = 505;        // calibration data, zero g
int Ycal = 505;
int key = -1;

void setup() {
  analogReference(EXTERNAL);     // uses 3.3v from accelerometer for reference voltage
  Serial.begin(4800);            // opens serial port for LCD shield
  Serial.write(1);               // clears display and homes cursor
  Serial.println("   Automobile  ");
  Serial.print(" Accelerometer ");
  delay(2000);
  Serial.write(1);
  Serial.println(" Prototype 2012");
  Serial.print(" J. Douglas III");
  delay(2000);
  Serial.write(1);               // clear display & home cursor
  Serial.println(" Press any Key");
  Serial.print("    to start ");
  while (key<0) key = Serial.read();
  Serial.write(1);
}

void loop() {
  Xaxis = analogRead(2);
  Yaxis = analogRead(1);
  if (Xaxis<Xcal) {                          // calculate Left & right
    Serial.print("Right ");
    Serial.print((Xcal-Xaxis)*.0095);
    Serial.println("g   ");
  }
  else if (Xaxis>Xcal) {                      // always display left and right
    Serial.print("Left ");                   // g force as positive value
    Serial.print((Xaxis-Xcal)*.0095);            
    Serial.println("g   ");
  }
  else Serial.println("L/R 0.00g     ");    // display forward as positive g
  Serial.print("Front ");                   // display rearward as negative g
  Serial.print((Ycal-Yaxis)*.0095);          
  Serial.println("g   ");
  delay(50);
  LCDpos(1,1);                                // home cursor ATS-1
}




void LCDpos(char x, char y) {
  Serial.write(20);
  Serial.write(x);
  Serial.write(y);
}
« Last Edit: January 03, 2013, 12:55:01 pm by JD3 » Logged

That little black caterpillar you just stepped on will set you back a few bucks....

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

I think I'm doing something wrong or my code isn't good, because when I face down the ADXL335 I get values around 0'85 G's in the Z axis, and I should get -1G...
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8102
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think I'm doing something wrong or my code isn't good, because when I face down the ADXL335 I get values around 0'85 G's in the Z axis, and I should get -1G...

From the datasheet it looks like the zero point and the sensitivity can both be off by about 10%.  I think that means that if you use the nominal zero (Vs/2) and the nominal sensitivity (Vs*0.1 per g) you may get readings as much as 20% off.  If you get 0.85 instead of 1.0 your error is only about 15%, well within specs.

Below is what code with calibration looks like.  Of course your calibration values will be different from mine.

Yes, you will get results outside the -1000/+1000 range.  The map() function does not constrain the inputs or outputs.  It just uses the input range and output range to calculate the offset and scale.

Code:
// Accelerometer calibrate
const int XPin = A2;
const int YPin = A1;
const int ZPin = A0;

// Raw analog values for -1g and +1g.  Position carefully and look for min and max values.
// These are from an accelerometer running on 3.3V measured agains a 5V analog reference.
// You would expect (3.3V/2-0.33V)*1024/5V = 270 for -1g and (3.3V/2+0.33V)*1024/5V = 405 for +1g.
// As you can see, my accelerometer does not match the nominal values.
const int XMin = 180;
const int XMax = 507;
const int YMin = 199;
const int YMax = 542;
const int ZMin = 152;
const int ZMax = 477;

void setup() {
  Serial.begin(9600);
 
  pinMode(A3, OUTPUT);
  digitalWrite(A3, HIGH);  // Power
  pinMode(A4, OUTPUT);
  digitalWrite(A4, LOW);  // Ground
}

void loop() {
  unsigned long XSum = 0;
  unsigned long YSum = 0;
  unsigned long ZSum = 0;
 
  for (int i=0; i<100; i++) {
    XSum += analogRead(XPin);
    YSum += analogRead(YPin);
    ZSum += analogRead(ZPin);
  }
 
  Serial.print("X=");
  Serial.print(map(XSum/100, XMin, XMax, -1000, 1000));
   
  Serial.print(", Y=");
  Serial.print(map(YSum/100, YMin, YMax, -1000, 1000));

  Serial.print(", Z=");
  Serial.println(map(ZSum/100, ZMin, ZMax, -1000, 1000));
  delay(500);
}
« Last Edit: January 03, 2013, 05:18:50 pm by johnwasser » Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Pages: [1]   Go Up
Jump to: