Go Down

Topic: Stabilizing Accelerometer (ADXL335) to measure displacement? (Read 1 time) previous topic - next topic

cloudurchin

Why don't you give this a try and see if it helps your project:

srss = sqrt(x*x + y*y + z*z)   

the magnitude of the combined acceleration vector
Hi DaveEvans,
Thanks so much for your comment!
I have a few questions for you;
Why do you think that equation is good to try it out? Why do I have to combine the magnitude? What does "magnitude of the combined acceleration vector" actually mean??

I've actually seen that formula on a tutorial using the adxl335, but has absolutely no clue what it is, what it is and how it works. I've tried using is but I don't know what the readings actually mean. Is it showing acceleration? Or displacement? or velocity??

It would be really really really be helpful if you could explain.

Looking forward to hearing from you...

MorganS

The sensor measures up/down separately from left/right. If you just want to know if it was hit without needing the direction of the hit, then use that formula above.
"The problem is in the code you didn't post."

DaveEvans

^^^right.

If you want to learn more about the formula, google 3d vector math

Also, regarding whether the formula gives acceleration, velocity, or displacement:google dimensional analysis

Regarding the latter, in brief: if x, y, and z all have units of length divided by time squared (i.e., acceleration), what must be the units of "srss"?

cloudurchin

The sensor measures up/down separately from left/right. If you just want to know if it was hit without needing the direction of the hit, then use that formula above.
^^^right.

If you want to learn more about the formula, google 3d vector math

Also, regarding whether the formula gives acceleration, velocity, or displacement:google dimensional analysis

Regarding the latter, in brief: if x, y, and z all have units of length divided by time squared (i.e., acceleration), what must be the units of "srss"?
Okay, thanks to you, the equation is starting to make sense to me.
I should have mentioned that I didn't need to know the direction of the hit earlier, so that my question was clearer! I'll try it out and see what happens. Thank you for your help!




Hey wvmarle,

Otherwise, have the Arduino just read the accelerometer on startup, and continue measuring. Use the average of the last few seconds or so as baseline, and any deviation that's for the impacts. Larger deviation is larger impact.
YES!! This is the kind of answer I was looking for!
Use the average of the last few seconds or so as baseline, and any deviation that's for the impacts.: I have done this exact thing in the code posted in post #0 - I'll put it here again, let me know what you think? I wanted to know if what I'm doing achieves what you described there.

The bit I calculate the deviation from, not the "last few seconds" but the last reading / loop cycle:
Code: [Select]
int accelerationX = abs(averageX - lastX);
  lastX = averageX;
  return accelerationX;



^So here,
1) I'm subtracting current averaged reading (of x-axis) "averageX" from "lastX" (which was the averageX in the last reading).
2) Then I store the current "averageX" in "lastX". This "lastX" is going to be used in the next loop cycle - the newer reading of "averageX" will be subtracted from the "lastX" and so on....

Is this the same thing as what you said???



Here is the whole code:
Code: [Select]
const int ap1 = A5;
const int ap2 = A4;
const int ap3 = A3;
const int numReadings = 30;
int inByte = 0;         // incoming serial byte

int readingsX[numReadings];      // the readings from the analog input
int readingsY[numReadings];      // the readings from the analog input
int readingsZ[numReadings];      // the readings from the analog input

int readIndexX = 0;              // the index of the current reading
int readIndexY = 0;              // the index of the current reading
int readIndexZ = 0;              // the index of the current reading
int totalX = 0;                  // the running total
int totalY = 0;                  // the running total
int totalZ = 0;                  // the running total
int averageX = 0;                // the average
int averageY = 0;                // the average
int averageZ = 0;                // the average
int lastX = 0;
int lastY = 0;
int lastZ = 0;



void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readingsX[thisReading] = 0;
    readingsY[thisReading] = 0;
    readingsZ[thisReading] = 0;
  }
}

void loop() {


  int Xval = getXval();
  int Yval = getYval();
  int Zval = getZval();
 
  Serial.print(Xval);
  Serial.print(",");
  Serial.print(Yval);
  Serial.print(",");
  Serial.print(Zval);
  Serial.print("\n");
  delay(2);

} //------End of Loop-----


int getXval(){
 
  //  X------------------------------
  // subtract the last reading:
  totalX = totalX - readingsX[readIndexX];
 
//read from the sensor:
  int x = abs(analogRead(ap1));
  int xMapped = map(x,0,10,0,1000);
  readingsX[readIndexX] = xMapped;
 
  // add the reading to the total:
  totalX = totalX + readingsX[readIndexX];
  // advance to the next position in the array:
  readIndexX = readIndexX + 1;

  // if we're at the end of the array...
  if (readIndexX >= numReadings) {
    // ...wrap around to the beginning:
    readIndexX = 0;
  }

  // calculate the average:
  averageX = totalX / numReadings;
  int accelerationX = abs(averageX - lastX);
  lastX = averageX;
  return accelerationX;
}


int getYval(){

  //  Y------------------------------
   // subtract the last reading:
  totalY = totalY- readingsY[readIndexY];
 
//read from the sensor:
  int y = abs(analogRead(ap2));
  int yMapped = map(y,0,10,0,1000);
  readingsY[readIndexY] = yMapped;
 
  // add the reading to the total:
  totalY = totalY + readingsY[readIndexY];
  // advance to the next position in the array:
  readIndexY = readIndexY + 1;

  // if we're at the end of the array...
  if (readIndexY >= numReadings) {
    // ...wrap around to the beginning:
    readIndexY = 0;
  }

  // calculate the average:
  averageY = totalY / numReadings;
  int accelerationY = abs(averageY - lastY);
  lastY = averageY;
  return accelerationY;
}


int getZval(){
  //  Z------------------------------
   // subtract the last reading:
  totalZ = totalZ - readingsZ[readIndexZ];
 
//read from the sensor:
  int z = abs(analogRead(ap3));
  int zMapped = map(z,0,10,0,1000);
  readingsZ[readIndexZ] = zMapped;
 
  // add the reading to the total:
  totalZ = totalZ + readingsZ[readIndexZ];
  // advance to the next position in the array:
  readIndexZ = readIndexZ + 1;

  // if we're at the end of the array...
  if (readIndexZ >= numReadings) {
    // ...wrap around to the beginning:
    readIndexZ = 0;
  }

  // calculate the average:
  averageZ = totalZ / numReadings;
  int accelerationZ = abs(averageZ - lastZ);
  lastZ = averageZ;
  return accelerationZ;
}


Quote
Of course now you have no idea in which exact direction it is, but that doesn't seem to matter much here. Nor do you know the absolute value of the acceleration (impact), but that also doesn't matter, you're not building a drone or so. It's more like: medium short time deviation: a good tug. Large short term deviation: a hit. Very large short term deviation: a baseball bat. Values all over the place for some time: it's tumbling around.
Yes, exactly! For my project the acceleration value doesn't have to be super accurate.

As for piezo,
Quote
Only little vibration is needed, so it may still work. You'll just have to try it.
I've tried it already actually, and with no luck... :( Also there were issues around installing them in the fabric/dismantling, having a limited amount of time/space/ being a in-class project... but thanks for the suggestion!

wvmarle

A number of replies back you got a suggestion on how to turn the three axis into a single acceleration number. That you need to do, as you shouldn't read each axis independently. Simply rotating the device would cause constant changes in the X, Y and Z values but should have a constant number for the overall acceleration.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

cloudurchin

A number of replies back you got a suggestion on how to turn the three axis into a single acceleration number. That you need to do, as you shouldn't read each axis independently. Simply rotating the device would cause constant changes in the X, Y and Z values but should have a constant number for the overall acceleration.
wvmarle,

Ooh you mean by the suggestion by DaveEvans (as seen below) ??

Why don't you give this a try and see if it helps your project:

srss = sqrt(x*x + y*y + z*z)   

wvmarle

Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.


cloudurchin

THANK YOU SO SO SO MUCH everyone who's contributed to this forum and supported me!  :smiley:

It seems like, the verdict for my project is - to use the equation

srss = sqrt(x*x + y*y + z*z)   


to find a combined acceleration of the 3-axises - x, y and z - store that in a variable, subtract from that variable a new reading of the combined acceleration.

It was also good to find out that what I was experimenting at the beginning (original code I posted in #0) still has a use!

I haven't tested out the equation yet, but how the equation fits in this whole code/project makes so much sense now.

I might report back once I test and am confident enough to explain what exactly I'm doing my code.

THANKS AGAIN EVERYONE!!


wvmarle

This srss value should then be stored in an array, to calculate a moving average, of say the last 8 or 16 readings (nice round number for easy calculation, a division becomes a simple bit shift if you convert that srss into an int value). How many readings you need depends on the reading interval and the duration of your impacts, and will require some trial and error.

That moving average is what you use to compare the current value against and determine whether you see an impact.

Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

cloudurchin

This srss value should then be stored in an array, to calculate a moving average, of say the last 8 or 16 readings (nice round number for easy calculation, a division becomes a simple bit shift if you convert that srss into an int value). How many readings you need depends on the reading interval and the duration of your impacts, and will require some trial and error.

That moving average is what you use to compare the current value against and determine whether you see an impact.


That is clear!

Here is my code, stripped to really just calculate the magnitude of the combined 3-axis accelerations. I think it's working okay!

I referenced code structure from this tutorial: https://learn.sparkfun.com/tutorials/das-blinken-top-hat/all

I hope this would be useful for others to reference in future!

Code: [Select]
const int accelX = A0;
const int accelY = A1;
const int accelZ = A2;
float aX, aY, aZ;
float currentAccelReading = 0;
float oldMag = 0;

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

void loop(){
  currentAccelReading = getAccel();
  currentAccelReading = map(currentAccelReading, 0, 100,0,1000);
  Serial.println(currentAccelReading, 0);
}

//Reads the accelerometer and returns an 'energy' value
float getAccel(){
  float avgMag = 0;
  for(int x = 0 ; x < 8 ; x++){
    aX = analogRead(accelX);
    aY = analogRead(accelY);
    aZ = analogRead(accelZ);

    float magnitude = sqrt((aX * aX) + (aY * aY) + (aZ * aZ)); //Combine all vectors
    avgMag += magnitude;
  }
  avgMag /= 8;
  float magDifference = abs(oldMag - avgMag);

  if(magDifference > 5) //0-10 works well. Increase to desensitize.
  {
    oldMag = avgMag;
    return(magDifference);
  }
  else
    return(0);
}

wvmarle

Glad to hear you got it working. Good luck with the rest of your project.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Go Up