Pages: [1] 2 3   Go Down
Author Topic: ADXL345 information/help/problem/guidance etc :)  (Read 4052 times)
0 Members and 1 Guest are viewing this topic.
Athens, Greece
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello.

I'm trying to create an accelerometer logger for my R/C bikes (and cars, why not?).

The project will consists of an Arduino Nano, an ADXL345, a RTC, a GPS and a SD card module.
It will log the acceleration (in Gs) on X/Y/Z axis and the angle (in degrees) on X & Y axis (to see how much it leans at the corners, what was the maximum lean before crash etc). Also it will log the long/latt data from GPS and will be saved on SD card as KML (for Google Earth review). Power will be supplied either from the ESC's BEC or from a channel of the RX (with a 7805 voltage regulator and a diode for protection).

So far it looks that works OK, but there are two problems related with the accelerometer.

First problem is that when I'm trying to move it left/right/front/back on a table (keeping the Z axis steady), the acceleration changes, but it changes the angle too. Is it normal?

Second problem is that I don't know too much about accelerometers, and I'm not sure if it counts the G forces OK. It looks good, but when I'm accelerating for example, it changes the angle a lot, and I'm not leaning.

Here is my code so far. If I have any errors in calculations (I'm totally newbie to accelerometers), please help! Oh, and please contribute if you like smiley

Code:
#include <Time.h>  
#include "Wire.h"
#include "ADXL345.h"
#include <DS1307RTC.h>
#include <EEPROM.h>


#define GreenLed    13
#define RedLed      12
#define ButtonWrite 11

int x,y,z;
int xx, yy;
int defaultXX, defaultYY, defaultZZ;
double xyz[3];
double calibratedAccelXYZ[3];
double currentAccelX, currentAccelY, currentaccelz;
double differencexx, differenceyy, differencezz;
  
int CurrentFront = 0;
int CurrentBack = 0;
int CurrentLeft = 0;
int CurrentRight = 0;

double maxX = 0;
double maxY = 0;
double maxZ = 0;
int maxAngleLeft = 0;
int maxAngleRight = 0;
int maxAngleFront = 0;
int maxAngleBack = 0;

ADXL345 accel;

#define debug 1

void setup(void)
{
  pinMode(RedLed, OUTPUT);
  pinMode(GreenLed, OUTPUT);
  // Turn on the red led to define that calibration
  // process will be started
  pinMode(ButtonWrite, INPUT);
  digitalWrite(GreenLed, HIGH);
  digitalWrite(RedLed, HIGH);
  setSyncProvider(RTC.get);        // Get the time from RTC
  delay(100);
  if (debug==1)
  {
    Serial.begin(9600);
    Serial.println("Begin");
  }
  accel.powerOn();                 // Power On the Accelerator
  
  accel.setRangeSetting(8);        // Set maximum range to 8G
 
  digitalWrite(GreenLed, LOW);
  digitalWrite(RedLed, LOW);
  delay(100);
  digitalWrite(RedLed, HIGH);
  delay(100);
  digitalWrite(RedLed, LOW);
  delay(100);
  digitalWrite(RedLed, HIGH);
  delay(100);
  digitalWrite(RedLed, LOW);
  delay(100);
  digitalWrite(RedLed, HIGH);
  delay(100);
  
  // Read acceleration data and store them as default/inactive values
  accel.readAccel(&x, &y, &z);
  defaultXX = (atan2(y,z)+3.14)*RAD_TO_DEG;
  defaultYY = (atan2(x,z)+3.14)*RAD_TO_DEG;
  accel.get_Gxyz(xyz);
  calibratedAccelXYZ[0] = xyz[0];
  calibratedAccelXYZ[1] = xyz[1];
  calibratedAccelXYZ[2] = xyz[2];
  
  // Turn on the green led - ready to start
  delay(250);
  digitalWrite(RedLed, LOW);
  digitalWrite(GreenLed, HIGH);

  // Display previous records from EEPROM
  ReadFromEEPROM();
  
  // zero the variables to store the new maximum values
  maxX = 0;
  maxY = 0;
  maxZ = 0;
  maxAngleLeft = 0;
  maxAngleRight = 0;
  maxAngleFront = 0;
  maxAngleBack = 0;
  if (debug==1)  
    Serial.println("Ready!");
}




void loop()
{
  if (digitalRead(ButtonWrite) == HIGH)
    WriteToEEPROM();
  
  if (debug==1)  
  {
    Serial.print(TimeDate());
    Serial.print(" | ");
  }
  
  accel.readAccel(&x, &y, &z);
  xx = (atan2(y,z)+3.14)*RAD_TO_DEG;
  yy = (atan2(x,z)+3.14)*RAD_TO_DEG;
  
  accel.get_Gxyz(xyz);
  currentAccelX=abs(calibratedAccelXYZ[0]-xyz[0]);
  currentAccelY=abs(calibratedAccelXYZ[1]-xyz[1]);
  currentaccelz=abs(calibratedAccelXYZ[2]-xyz[2]);
  
  if (currentAccelX>maxX)
    maxX = currentAccelX;
  if (currentAccelY>maxY)
    maxY = currentAccelY;
  if (currentaccelz>maxZ)
    maxZ = currentaccelz;
  
  if (debug==1)
  {
    Serial.print("Acceleration X: ");
    Serial.print(currentAccelX, 1);
    Serial.print(" - Y: ");
    Serial.print(currentAccelY, 1);
    Serial.print(" - Z: ");
    Serial.print(currentaccelz, 1);
    Serial.print(" | ");
  }

  
  differencexx = defaultXX-xx;
  if (differencexx < -180)
    differencexx += 180;
  if (differencexx > 180)
    differencexx -= 180;

  if (differencexx<0)
    CurrentLeft=abs(differencexx);
  else
    CurrentRight=differencexx;

  
  differenceyy = defaultYY-yy;
  if (differenceyy < -180)
    differenceyy += 180;
  if (differenceyy > 180)
    differenceyy -= 180;
    
  if (differenceyy<0)
    CurrentFront=abs(differenceyy);
  else
    CurrentBack=differenceyy;
    
  if (CurrentFront>maxAngleFront)
    maxAngleFront=CurrentFront;
  if (CurrentBack>maxAngleBack)
    maxAngleBack=CurrentBack;
  if (CurrentLeft>maxAngleLeft)
    maxAngleLeft=CurrentLeft;
  if (CurrentRight>maxAngleRight)
    maxAngleRight=CurrentRight;

  if (debug==1)
  {
    Serial.print("Front: ");
    Serial.print(CurrentFront);
    Serial.print(" - Back: ");
    Serial.print(CurrentBack);
    Serial.print(" - Left: ");
    Serial.print(CurrentLeft);
    Serial.print(" - Right: ");
    Serial.print(CurrentRight);
    Serial.println("");
    delay(50);
  }
}


String TimeDate()
{
  String datetime;
  
  if (hour()<10)
    datetime=String("0");
  else
    datetime=String(hour());
  if (minute()<10)
    datetime += String(":0");
  datetime += String(":")+String(minute())+String(":");
  if (second()<10)
    datetime += String("0");
  datetime += String(second())+String(" / ");
  if (day()<10)
    datetime += String("0");
  datetime += String(day())+String("/");
  if (month()<10)
    datetime += String("0");
  datetime += String(month())+String("/")+String(year());
  
  return datetime;
}


void WriteToEEPROM()
{
  digitalWrite(RedLed, HIGH);
  digitalWrite(GreenLed, LOW);
  Serial.println("");
  Serial.println("Write to EEPROM");
  int foo;
  foo = maxX*100;
  EEPROM.write(0,foo);
  foo = maxY*100;
  EEPROM.write(1,foo);
  foo = maxZ*100;
  EEPROM.write(2,foo);
  EEPROM.write(3,maxAngleFront);
  EEPROM.write(4,maxAngleBack);
  EEPROM.write(5,maxAngleLeft);
  EEPROM.write(6,maxAngleRight);
  delay(500);
  digitalWrite(RedLed, LOW);
  digitalWrite(GreenLed, HIGH);
  Serial.println("Done!");
}

void ReadFromEEPROM()
{
  Serial.println("");
  Serial.println("");  
  Serial.println("Reading EEPROM");  
  maxX = EEPROM.read(0);
  maxY = EEPROM.read(1);
  maxZ = EEPROM.read(2);
  maxAngleFront = EEPROM.read(3);
  maxAngleBack = EEPROM.read(4);
  maxAngleLeft = EEPROM.read(5);
  maxAngleRight = EEPROM.read(6);
  Serial.println("");
  double foo = 0;
  Serial.print("Max X Acceleration: ");
  foo = maxX/100;  
  Serial.println(foo, 2);
  Serial.print("Max Y Acceleration: ");
  foo = maxY/100;  
  Serial.println(foo, 2);
  Serial.print("Max Z Acceleration: ");  
  foo = maxZ/100;  
  Serial.println(foo, 2);
  Serial.println("");
  Serial.print("Max Angle Front: ");
  Serial.println(maxAngleFront);
  Serial.print("Max Angle Back: ");
  Serial.println(maxAngleBack);  
  Serial.print("Max Angle Left: ");
  Serial.println(maxAngleLeft);  
  Serial.print("Max Angle Right: ");
  Serial.println(maxAngleRight);  
  Serial.println("");
  Serial.println("");
  delay(2000);
}

PS 1: I haven't receive the GPS & the SD card module yet, so it only displays the data on screen (and saves the max values @ EEPROM when button is pressed).

PS 2: I want to log the crashes (don't forget it's a RC Bike, it has lot of crashes). I guess that's possible with the tap detection. Any ideas how to do that?


Thank you,

Antonis.
Logged


0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

you are not considering the fast that the acceleration and the gravity vector sum together. That's why when you move your vector grow so much: it's the acceleration!

if you will let the module fall on the Z axis, you will read exactly 0 on all axes (well 0 in theory  smiley-mr-green)

don't bother with tap detection, you are more flexible if you just log all the data on SD and post-process it with your computer; because GPS has a precision of +-5 meters (due to some physic and software limitation), using accelerometer data you can estimate your position. But you'll need a gyroscope. take a look at quadcopeter's IMU/MARG code to understand the math behind this. Your system is easier only if you remove some "freedom", like no lateral or backward movement, no pitch change, etc. but this will be missing data in post processing because when you crash (or jump) you will probably break this rule.

sorry if i was confusing, but it is not easy as it seems, but using some "pre-coocked" math and patience, it is possible for everyone.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I did this with my cars some time back, as Lesto says you are much better of capturing the raw data and doing you post processing in excel.

You can find some of my excel charts here, I was mostly interested in the traction circle -

http://rcarduino.blogspot.com/p/project-index.html

Ultimatley I found that I could not interpret the data in a way that I could translate to faster lap timers so I build a lap timer instead - you can quickly gain a few seconds around the track with the instant feedback a lap timer provides.

Anyway, its all in the link

Duane B

rcarduino.blogspot.com
Logged


Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It will log the acceleration (in Gs) on X/Y/Z axis and the angle (in degrees) on X & Y axis

They are one and the same. No point in storing the angles.

Quote
Is it normal?

Yes. Your acceleration on X/Y is being combined with the gravity (-1g on Z).
Logged

Athens, Greece
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It will log the acceleration (in Gs) on X/Y/Z axis and the angle (in degrees) on X & Y axis

They are one and the same. No point in storing the angles.

Quote
Is it normal?

Yes. Your acceleration on X/Y is being combined with the gravity (-1g on Z).

Now I get it, thanks.

So the problem now is how to seperate the leaning (on one axis, left/right) of a bike from total acceleration? With a second accelerator or something else?

Ultimatley I found that I could not interpret the data in a way that I could translate to faster lap timers so I build a lap timer instead - you can quickly gain a few seconds around the track with the instant feedback a lap timer provides.

Anyway, its all in the link

Duane B

rcarduino.blogspot.com

I have already found your site some days ago. I don't want to get lap times right now. What I need is to find out how much acceleration in G forces can do (when accelerating, on brakes, on turns) and how much the rc bike can lean (in degrees) before it starts to slide/crash/etc smiley

BUT I have already bookmark your site, as a lap timer is not a bad idea, at least for the local parking track we race with some friends smiley
Logged


0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

you know that gravity is a fixed lenght vector, but you still need to know your orientation to the floor to subtract the gravity vector and get your real acceleration vector. (well vice-versa in your case)

without a gyro you can only know your inclination on lateral axes, because (hopefully) they are not influenced by acceleration
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Athens, Greece
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

without a gyro you can only know your inclination on lateral axes, because (hopefully) they are not influenced by acceleration

Thats the axis I want to know for bike leaning. Just left & right degrees.
And the Gs on acceleration, brakes, left leaning, right leaning. So I can see what forces and what angle the bike has..
Logged


Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You cannot measure bike leaning with only an accelerometer.  The vector will always be straight down with respect to the bikes axis.  A cheap gyro cannot do much better in the real world on a full size bike.  Because of all the vibration.  Using GPS only you can measure G-forces because you know the radius and speed.  The code for this is complex.  Questions?
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Athens, Greece
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You cannot measure bike leaning with only an accelerometer.  The vector will always be straight down with respect to the bikes axis.  A cheap gyro cannot do much better in the real world on a full size bike.  Because of all the vibration.  Using GPS only you can measure G-forces because you know the radius and speed.  The code for this is complex.  Questions?

I get it smiley
So I have to keep the accelerometer for the G forces, and a 3ple axis gyro for the leaning...
The vibrations are not too much (I guess). Running on a track, with a "street" bike...

Thanks.
Logged


Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Let me try again.  You only need GPS to measure G-forces.  Accel, braking, left, right.  5-10hz sampling would be best.  For a motorcycle there is no left or right G-forces.  Only down with respect to the bikes axis.

You cannot measure leaning directly with any cheap hardware.  Perhaps you could calculate it from GPS data.  Many people have spent years on this problem.  There is too much vibration to use a cheap Gyro over any length of time.  If there are many straight sections you could assume it is upright between every turn.  Even that is difficult without spending a lot of money.

Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Athens, Greece
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, now I get it.
So, no low-cost gyro can provide what I need.
So, bye bye angle-meter smiley
Logged


0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

gps have 2 meter radius precision AND normally 1 or 5 Hz output... i don't think it is enough.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Athens, Greece
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

gps have 2 meter radius precision AND normally 1 or 5 Hz output... i don't think it is enough.

Low-cost GPS have up to 10Hz sampling rate. The precision is about 2 meters (WAAS/EGNOS-enabled), but -if I'm not wrong- that's not affecting the results. If it's 2m, it will be also 2m here (sample #1) and 2m there (sample #2). So the results will be -almost- the same...
Logged


0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no way, take a look at sparkfun GPS test (can't find it, but here you can see and image of result http://www.sparkfun.com/news/380), and you will see how things around you will ruin signal.
Also pay attention to REAL output and interpolated output. i'm not expert in this, but many times i've seen this alert smiley-wink
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@vegos- That's right!  You can measure the radius of a curve very accurately.  The error from 1 second to the next is minimal.  It's an absolute error, not relative.  Speed is also very accurate.  These 2 give you G-force. 
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Pages: [1] 2 3   Go Up
Jump to: