Pages: [1] 2   Go Down
Author Topic: Library for Accelerometer MMA7361  (Read 25184 times)
0 Members and 2 Guests are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello people,

I'm posting my first library. It's a library for the MMA7361 accelerometer. I hope this is the correct way to share libraries

Since no library was available I believed posting mine would help some people.

I'm always open for suggestions since this is my first library I expect it not to be perfect.

available for download http://rapidshare.com/files/435429883/AcceleroMMA7361.zip

header file
Code:
/**************************************************************************************************
 * acceleroMMA7361.h - Library for retrieving data from the MMA7361 accelerometer. Only tested         *
 * with Duemilanove                                                                               *
 * Following functions need improving. I asumed the output to be linear (it is nearly linear but  *
 * not really). I also asumed the Arduino input to be scaled 0-5V                                 *
 * begin variables                                                                                *
 *       -int sleepPin: number indicating to which pin the sleep port is attached. DIGITAL OUT         *
 *      -int selfTestPin: number indicating to which pin the selftest port is attached.DIGITAL OUT    *
 *      -int zeroGPin: number indicating to which pin the ZeroGpin is connected to. DIGITAL IN        *
 *      -int xPin: number indicating to which pin the x-axis pin is connected to. ANALOG IN           *
 *      -int yPin: number indicating to which pin the y-axis  pin is connected to. ANALOG IN          *
 *      -int zPin: number indicating to which pin the z-axis  pin is connected to. ANALOG IN          *
 *      -int offset: array indicating the G offset on the x,y and z-axis                              *
 * Functions currently present:                                                                   *
 *  -getXRaw(): Instantly returns the raw data from the X-axis analog I/O port of the Arduino as  *
 *    a double. WARNING! OFFSET HAS NO INFLUENCE                                                  *
 *  -getYRaw(): Instantly returns the raw data from the Y-axis analog I/O port of the Arduino as  *
 *    a double. WARNING! OFFSET HAS NO INFLUENCE                                                  *
 *  -getZRaw(): Instantly returns the raw data from the Z-axis analog I/O port of the Arduino as  *
 *    a double. WARNING! OFFSET HAS NO INFLUENCE                                                  *
 *  -getXVolt(): Instantly returns the voltage in miliVolts from the X-axis analog I/O port of    *
 *    the Arduino as a double. WARNING! OFFSET HAS NO INFLUENCE                                   *
 *  -getYVolt(): Instantly returns the voltage in miliVolts from the Y-axis analog I/O port of    *
 *    the Arduino as a double. WARNING! OFFSET HAS NO INFLUENCE                                   *
 *  -getZVolt(): Instantly returns the voltage in miliVolts from the Z-axis analog I/O port of    *
 *    the Arduino as a double. WARNING! OFFSET HAS NO INFLUENCE                                   *
 *  -getXAccel(): Instantly returns the acceleration of the X-axis as a double (1G = 100.00)      *
 *  -getYAccel(): Instantly returns the acceleration of the Y-axis as a double (1G = 100.00)      *
 *  -getXAccel(): Instantly returns the acceleration of the Z-axis as a double (1G = 100.00)      *
 **************************************************************************************************
 * Revision History:                                                                              *
 *  Version 0.1: get raw values                                                                   *
 *  Version 0.2: get voltages and G forces                                                        *
 **************************************************************************************************
 * Created by Jef Neefs: Suggestions, questions or comments please contact me                     *
 * - mail: neefsj at gmail dot com                                                                *
 * - skype: studioj                                                                               *
 **************************************************************************************************/
#ifndef AcceleroMMA7361_h
#define AcceleroMMA7361_h
#include <WProgram.h>

class AcceleroMMA7361
{
  public:
    AcceleroMMA7361();
    void begin(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin, int xOffset, int yOffset, int zOffset);
    double getXRaw();
    double getYRaw();
    double getZRaw();
    double getXVolt();
    double getYVolt();
    double getZVolt();
    double getXAccel();
    double getYAccel();
    double getZAccel();
    double getTotalVector();
      
  private:
      long _mapMMA7361V(int value);
      long _mapMMA7361G(int value);
    int _sleepPin;
      int _selfTestPin;
      int _zeroGPin;
      int _xPin;
      int _yPin;
      int _zPin;
      int _xOffset;
      int _yOffset;
      int _zOffset;
};
#endif

cpp file
Code:
comment header as in h file is left away
#include <WProgram.h>
#include <AcceleroMMA7361.h>

AcceleroMMA7361::AcceleroMMA7361()
{
}

void AcceleroMMA7361::begin(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin, int xOffset, int yOffset, int zOffset)
{
  pinMode(sleepPin, OUTPUT);
  pinMode(selfTestPin, OUTPUT);
  pinMode(zeroGPin, INPUT);
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  pinMode(zPin, INPUT);
  digitalWrite(sleepPin,HIGH);
  digitalWrite(selfTestPin,LOW);
  _sleepPin = sleepPin;
  _selfTestPin = selfTestPin;
  _zeroGPin = zeroGPin;
  _xPin = xPin;
  _yPin = yPin;
  _zPin = zPin;
  _xOffset = xOffset;
  _yOffset = yOffset;
  _zOffset = zOffset;
}

double AcceleroMMA7361::getXRaw()
{
  return analogRead(_xPin);
}

double AcceleroMMA7361::getYRaw()
{
  return analogRead(_yPin);
}

double AcceleroMMA7361::getZRaw()
{
  return analogRead(_zPin);
}

double AcceleroMMA7361::getXVolt()
{
  return _mapMMA7361V(analogRead(_xPin));
}

double AcceleroMMA7361::getYVolt()
{
  return _mapMMA7361V(analogRead(_yPin));
}

double AcceleroMMA7361::getZVolt()
{
  return _mapMMA7361V(analogRead(_zPin));
}

double AcceleroMMA7361::getXAccel()
{
  return _mapMMA7361G(analogRead(_xPin))+ _xOffset;
}

double AcceleroMMA7361::getYAccel()
{
  return _mapMMA7361G(analogRead(_yPin)) + _yOffset;
}

double AcceleroMMA7361::getZAccel()
{
  return _mapMMA7361G(analogRead(_zPin)) + _zOffset;
}

long AcceleroMMA7361::_mapMMA7361V(int value)
{
  return map(value,0,1024,0,5000);
}

long AcceleroMMA7361::_mapMMA7361G(int value)
{
  return map(value,0,1024,-800,1600);
}
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12465
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


You can also make an article on the playground. Please include some basic examples how to use the lib.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

in the zip are examples as wel as a keyword.txt present.

I dont know where I should put this in the playground, there are several places where I could put it.

b.e. "Interfacing with Hardware or "Code Library and Tutorials"...
Logged

Denver
Offline Offline
God Member
*****
Karma: 19
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

studioj,
Thanks for sharing your lib.
After a brief look, I'd like to make the following comments / suggestions, if I may:
- Looks like you assume it will be run at 5V.  3.3V gives more accuracy.
- Maybe you should have a param for the Aref voltage.
- That accel has 2 sensitives - 1.5/6g. Looks like you expect 1g max.
- Not sure how you calc g - (1 g = 9.80665 m/s2)

(Not to crazy about the site that hosting your zip. You should check out "Dropbox".)

I've been messing with an example for the MMA7361. If there is any interest, I can post it.
« Last Edit: December 07, 2010, 06:25:41 pm by BroHogan » Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
- Looks like you assume it will be run at 5V.  3.3V gives more accuracy.

I assume 3.3V working voltage BUT the axis all attached to a 0-5 analog input gate. can i change the input gate itself? otherwise 0-1023 equals 0-5V

Quote
- Maybe you should have a param for the Aref voltage.

maybe yes (do you mean parameterwise change the input gates from 0-5V to 0-3.3V)
i do feel i have alot parameters already

Quote
- That accel has 2 sensitives - 1.5/6g. Looks like you expect 1g max.


I set it to 6G sensitivity, thats not mentioned in the header comment indeed.
Code:
long AcceleroMMA7361::_mapMMA7361G(int value)
{
  return map(value,0,1024,-800,1600);
}

that function maps 0-5V volt to from -8G to +16G (as the output voltage of the MMA7361 will off course never reach those values) therefor 6G = 3.3V


Quote
- Not sure how you calc g - (1 g = 9.80665 m/s2)
I think i answered this in the above question

Quote
(Not to crazy about the site that hosting your zip. You should check out "Dropbox".)
I feel ok using this host

Quote
I've been messing with an example for the MMA7361. If there is any interest, I can post it.
Of course there is no point sharing a lib if it is not open for input

Thank you for your comments I'll post version 0.3 maybe later today
« Last Edit: December 08, 2010, 08:58:06 am by studioj » Logged

Denver
Offline Offline
God Member
*****
Karma: 19
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@studioj
As you know, the MMA7361 centers it's -/+ g output around it's working voltage (3.3V). Therefore, you loose potential accuracy when Aref is 5V.

You can set the Arduino's ARef by putting the 3.3V on the ARef pin and calling analogReference(EXTERNAL);

However, if you are happy with only using the 6g sensitivity, and mapping it to -8 -16g the loss of accuracy mentioned above may not be the biggest factor.

If this is to be a lib for general use, you should consider supporting the +/- 1.5g range. Many applications would require the lower range. (You'd have a very fast car that could pull >1.5g!)

Since I haven't tried your lib yet, I shouldn't quibble about your calc method. I assume, at rest, you read ~0g on X & Y and ~+1g on the Z axis, and moving the accel 180° displays the 1g accordingly.

I know you have a bunch of parameters already. Perhaps #defines for sensitivity and Aref - not sure.

Assuming that you are using the great little board from ModernDevice, you can read the jumper and automatically set the sensitivity.

I'll post what I have in a bit. I'd like to simplify it some first. (I added a smoothing filter.) However, below are some formulas I used in case they are helpful.

Code:
1.5g setting:  Sensitivity: 800 mV/g   -1g = 850mV    0g = 1650mV   1g = 2450mV
6g setting:  Sensitivity: 206 mV/g   -1g = 1444mV   0g = 1650mV   1g = 1856mV
mV/analogRead unit = Aref V / 1024
g = [mV/analogRead unit] * ([units] - ([Aref/2]) / [mvPerG]
0-60 Time = 26.8224 / (g * 9.81) [60MPH = 26.8224 m/s, g = 9.81 m/s/s]

I know I'm being critical about what you've done, and I hope it's taken  in the spirit it's offered in.
« Last Edit: December 08, 2010, 12:08:35 pm by BroHogan » Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

Portugal
Offline Offline
God Member
*****
Karma: 5
Posts: 962
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you really need floats for all that integer reading and calcs?
Thats one huge cpu hog...
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ Senso and BroHogan

I was expecting comments and improvements. I'm definitly not the best programmer in the world :-) but i felt people could be helped by a library. Therefore, any help, hints or tips for improvement are happily received.

I used the sparkfun breakout board btw
Logged

Portugal
Offline Offline
God Member
*****
Karma: 5
Posts: 962
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
double AcceleroMMA7361::getXRaw()
{
  return analogRead(_xPin);
}

double AcceleroMMA7361::getYRaw()
{
  return analogRead(_yPin);
}

double AcceleroMMA7361::getZRaw()
{
  return analogRead(_zPin);
}

double AcceleroMMA7361::getXVolt()
{
  return _mapMMA7361V(analogRead(_xPin));
}

double AcceleroMMA7361::getYVolt()
{
  return _mapMMA7361V(analogRead(_yPin));
}

double AcceleroMMA7361::getZVolt()
{
  return _mapMMA7361V(analogRead(_zPin));
}

double AcceleroMMA7361::getXAccel()
{
  return _mapMMA7361G(analogRead(_xPin))+ _xOffset;
}

double AcceleroMMA7361::getYAccel()
{
  return _mapMMA7361G(analogRead(_yPin)) + _yOffset;
}

double AcceleroMMA7361::getZAccel()
{
  return _mapMMA7361G(analogRead(_zPin)) + _zOffset;
}

long AcceleroMMA7361::_mapMMA7361V(int value)
{
  return map(value,0,1024,0,5000);
}

long AcceleroMMA7361::_mapMMA7361G(int value)
{
  return map(value,0,1024,-800,1600);
}

analogRead returns an int, and map return an int too, so what is the advantage using floats?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I can only modify my last post. Anyhow here is a small update already. I'm planning to add the 1,5G sensitivity via a setSensitivity() function, later this year.


Revision History

Version 0.1: get raw values
Version 0.2: get voltages and G forces
Version 0.3: removed begin parameters offset, added public function setOffSets(int,int,int) added a private variable _offSets[3] containing the offset on each axis changed the long and double return values of private and public functions to int

new header file

Code:
/**************************************************************************************************
 * acceleroMMA7361.h - Library for retrieving data from the MMA7361 accelerometer. Only tested         *
 * with Duemilanove                                                                               *
 * Following functions need improving. I asumed the output to be linear (it is nearly linear but  *
 * not really). I also asumed the Arduino input to be scaled 0-5V                                 *
 * I also 'hard pinned' the G-Selector pin to 6G mode (HIGH) so nothing can be found here about   *
 * 1.5G sensitivity this will be fixed in later versions                                          *
 * begin variables                                                                                *
 *  -int sleepPin: number indicating to which pin the sleep port is attached. DIGITAL OUT         *
 *  -int selfTestPin: number indicating to which pin the selftest port is attached.DIGITAL OUT    *
 *  -int zeroGPin: number indicating to which pin the ZeroGpin is connected to. DIGITAL IN        *
 *  -int xPin: number indicating to which pin the x-axis pin is connected to. ANALOG IN           *
 *  -int yPin: number indicating to which pin the y-axis  pin is connected to. ANALOG IN          *
 *  -int zPin: number indicating to which pin the z-axis  pin is connected to. ANALOG IN          *
 *                                                                                                *
 * Functions currently present:                                                                   *
 *  -getXRaw(): Instantly returns the raw data from the X-axis analog I/O port of the Arduino as  *
 *    a int. WARNING! OFFSET HAS NO INFLUENCE                                                     *
 *  -getYRaw(): Instantly returns the raw data from the Y-axis analog I/O port of the Arduino as  *
 *    a int. WARNING! OFFSET HAS NO INFLUENCE                                                     *
 *  -getZRaw(): Instantly returns the raw data from the Z-axis analog I/O port of the Arduino as  *
 *    a int. WARNING! OFFSET HAS NO INFLUENCE                                                     *
 *  -getXVolt(): Instantly returns the voltage in miliVolts from the X-axis analog I/O port of    *
 *    the Arduino as a int. WARNING! OFFSET HAS NO INFLUENCE                                      *
 *  -getYVolt(): Instantly returns the voltage in miliVolts from the Y-axis analog I/O port of    *
 *    the Arduino as a int. WARNING! OFFSET HAS NO INFLUENCE                                      *
 *  -getZVolt(): Instantly returns the voltage in miliVolts from the Z-axis analog I/O port of    *
 *    the Arduino as a int. WARNING! OFFSET HAS NO INFLUENCE                                      *
 *  -getXAccel(): Instantly returns the acceleration of the X-axis as a int (1G = 100.00)         *
 *  -getYAccel(): Instantly returns the acceleration of the Y-axis as a int (1G = 100.00)         *
 *  -getXAccel(): Instantly returns the acceleration of the Z-axis as a int (1G = 100.00)         *
 *  -setOffSets( int offSetX, int offSetY, int offSetZ):                                          *
 **************************************************************************************************
 * Revision History:                                                                              *
 *  Version 0.1: get raw values                                                                   *
 *  Version 0.2: get voltages and G forces                                                        *
 *  Version 0.3: removed begin parameters offset, added public function setOffSets(int,int,int)   *
 *               added a private variable _offSets[3] containing the offset on each axis          *
 *               changed the long and double return values of private and public functions to int *
 **************************************************************************************************
 * Created by Jef Neefs: Suggestions, questions or comments please contact me                     *
 *  -mail: neefsj at gmail dot com                                                                *
 *  -skype: studioj                                                                               *
 **************************************************************************************************/
#ifndef AcceleroMMA7361_h
#define AcceleroMMA7361_h
#include <WProgram.h>

class AcceleroMMA7361
{
  public:
    AcceleroMMA7361();
    void begin(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin);
    int getXRaw();
    int getYRaw();
    int getZRaw();
    int getXVolt();
    int getYVolt();
    int getZVolt();
    int getXAccel();
    int getYAccel();
    int getZAccel();
    int getTotalVector();
      void setOffSets(int xOffSet, int yOffSet, int zOffSet);
      
  private:
      int _mapMMA7361V(int value);
      int _mapMMA7361G(int value);
    int _sleepPin;
      int _selfTestPin;
      int _zeroGPin;
      int _xPin;
      int _yPin;
      int _zPin;
      int _offSets[3];
};
#endif


cpp
Code:
#include <WProgram.h>
#include <AcceleroMMA7361.h>

AcceleroMMA7361::AcceleroMMA7361()
{
}

void AcceleroMMA7361::begin(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin)
{
  pinMode(sleepPin, OUTPUT);
  pinMode(selfTestPin, OUTPUT);
  pinMode(zeroGPin, INPUT);
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  pinMode(zPin, INPUT);
  digitalWrite(sleepPin,HIGH);
  digitalWrite(selfTestPin,LOW);
  _sleepPin = sleepPin;
  _selfTestPin = selfTestPin;
  _zeroGPin = zeroGPin;
  _xPin = xPin;
  _yPin = yPin;
  _zPin = zPin;
  setOffSets(0,0,0);
}

void AcceleroMMA7361::setOffSets(int xOffSet, int yOffSet, int zOffSet)
{
  _offSets[0]= xOffSet;
  _offSets[1]= yOffSet;
  _offSets[2]= zOffSet;
}

int AcceleroMMA7361::getXRaw()
{
  return analogRead(_xPin);
}

int AcceleroMMA7361::getYRaw()
{
  return analogRead(_yPin);
}

int AcceleroMMA7361::getZRaw()
{
  return analogRead(_zPin);
}

int AcceleroMMA7361::getXVolt()
{
  return _mapMMA7361V(analogRead(_xPin));
}

int AcceleroMMA7361::getYVolt()
{
  return _mapMMA7361V(analogRead(_yPin));
}

int AcceleroMMA7361::getZVolt()
{
  return _mapMMA7361V(analogRead(_zPin));
}

int AcceleroMMA7361::getXAccel()
{
  return _mapMMA7361G(analogRead(_xPin))+ _offSets[0];
}

int AcceleroMMA7361::getYAccel()
{
  return _mapMMA7361G(analogRead(_yPin)) + _offSets[1];
}

int AcceleroMMA7361::getZAccel()
{
  return _mapMMA7361G(analogRead(_zPin)) + _offSets[2];
}

int AcceleroMMA7361::_mapMMA7361V(int value)
{
  return map(value,0,1024,0,5000);
}

int AcceleroMMA7361::_mapMMA7361G(int value)
{
  return map(value,0,1024,-800,1600);
}

download library http://rapidshare.com/files/435911796/AcceleroMMA7361v0_3.zip

BroHogan you had some code to share?
Logged

Denver
Offline Offline
God Member
*****
Karma: 19
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@studioj

This example has a few small issues, but maybe it will give you some ideas. At least it has a close output to the actual g forces.

Code:
/* MMA7361 Accelerometer Test                                          BroHogan 12/10/10
 * CAUTION! input pins (Sleep, G-Select, Self-Test) are 3.3V max for HIGH
 * Z should read 1g at rest. The 0g-Detect pin goes high when ALL THREE axes are at 0g.
 * X & Y Bandwidth: 400Hz (Z=300Hz) Output Impedance: 32K
 *   1.5g setting:  Sensitivity: 800 mV/g   -1g = 850mV    0g = 1650mV   1g = 2450mV
 *     6g setting:  Sensitivity: 206 mV/g   -1g = 1444mV   0g = 1650mV   1g = 1856mV
 * mV/analogRead unit = Aref V(3.3) / 1024.0
 * g = [mV/analogRead unit] * ([units] - ([Aref/2]) / [mvPerG]
 * deg. = asin (mVout - 1650mv) / 800mV)  (double asin (double x) ) in radians
 * 0-60 Time = 26.8224 / (g * 9.81) [60MPH = 26.8224 m/s, g = 9.81 m/s/s]
 * Added digitalSmooth by  Paul Badger 2007 - big improvement!
 * (see www.arduino.cc/playground/Main/DigitalSmooth)
 * SETUP:
 * Best to use the 3.3V pin on the (Moderndevices) MMA7361 for ARef
 * TODO:
 * >1g && <-1g angle calc gets wonky (fixed).
 */

#include "WProgram.h"                   // needed for IDE to understand a "byte"!

#define X_PIN       2                   // X Axis input (analog pin #)
#define Y_PIN       1                   // Y Axis input (analog pin #)
#define Z_PIN       3                   // Z Axis input (analog pin #)
#define GSEL_PIN    14                  // pin on accel for range jmpr - LOW = 1.5 g range
#define ZERO_G_PIN  9                   // HIGH when X,Y,Z = 0 G
#define SLEEP_PIN   4                   // CAUTION 3.3V input pin - LOW to enable Sleep Mode

#define AREF_V      5000  //3280        // Aref voltage in mV BEST TO THE 3.2V ON THE ACCEL
#define LOW_RANGE   800                 // Sensitivity for 1.5 g range in mV/g
#define HIGH_RANGE  206                 // Sensitivity for 6 g range in mV/g
#define SAMPLES     13                  // SAMPLES should  be an odd number, no smaller than 3

int xSmoothArray [SAMPLES];             // array for holding X values for smoothing
int ySmoothArray [SAMPLES];             // array for holding Y values for smoothing
int zSmoothArray [SAMPLES];             // array for holding Z values for smoothing
int xOffset, yOffset, zOffset;          // used to hold calculated offsets

int Acc_X, Acc_Y, Acc_Z;                // raw accel output
float Acc_Xg, Acc_Yg, Acc_Zg;           // accel output expressed in mg's
float Xdeg, Ydeg, Zdeg;                 // angle expressed in degrees
float mVperUnit;                        // calculated mV / analogRead unit
float mvPerG;                           // Sensitivity for current range in mV/g
float zeroTo60;                         // seconds for 0-60MPH acceleration equivalent
boolean lowRange = true;                // 1.5 g max if true - else 6g range


void setup(){
  Serial.begin(9600);
  pinMode(ZERO_G_PIN,INPUT);            // HIGH when X,Y,Z = 0 G
  pinMode(GSEL_PIN,INPUT);              // LOW = 1.5 g range
  //analogReference(EXTERNAL);            // set if Aref pin wired to 3.3V source
  mVperUnit = AREF_V / 1024.0;          // calc mV / analogRead unit

  Serial.println("Lay flat for calibration!");
  CalAccel();                           // calc offsets
  delay (1000);
}


void loop(){
  //lowRange = !digitalRead(GSEL_PIN);    //  read pin on accel for range jmpr - If LOW set flag true
  lowRange = true;                      // USE THIS IF NOT READING JMPR ON ACCEL
  if (lowRange)mvPerG = LOW_RANGE;      // Set the mV/g based on the current range
  else mvPerG = HIGH_RANGE;

  Read_Accel();                         // read the X,Y,Z values from the MMA7361
  Disp_Vals();                          // display X,Y,Z g values
  delay(3000);
}

void Read_Accel(){
  //digitalSmooth(Acc_X,xSmoothArray,true); // reset running average
  for (int i=0; i< SAMPLES +2; i++){    // make a series of samples for smoothing
    Acc_X = analogRead(X_PIN) - xOffset;             // read the X Axis and apply offset
    Acc_X = digitalSmooth(Acc_X,xSmoothArray,false); // smooth X axis
    Acc_Y = analogRead(Y_PIN) - yOffset;             // read the Y Axis and apply offset
    Acc_Y = digitalSmooth(Acc_Y,ySmoothArray,false); // smooth Y axis
    Acc_Z = analogRead(Z_PIN) - zOffset;             // read the Z Axis and apply offset
    Acc_Z = digitalSmooth(Acc_Z,zSmoothArray,false); // smooth Z axis
    delay(5);                           // need this delay for 200Hz max sample rate
  }
  // now calc g's and angle . . .
  if (Acc_X >= 512) Acc_Xg = mVperUnit * (Acc_X - 512) / mvPerG;
  else Acc_Xg = ((512 - Acc_X) * (mVperUnit) / mvPerG) * -1;
  if (Acc_Xg >= -1.0 && Acc_Xg <= 1.0) Xdeg = asin(Acc_Xg) * (180.0/PI);
  else Xdeg = 0;
    zeroTo60 = 26.8224 / (Acc_Xg * 9.81);

  if (Acc_Y >= 512) Acc_Yg = mVperUnit * (Acc_Y - 512) / mvPerG;
  else Acc_Yg = ((512 - Acc_Y) * (mVperUnit) / mvPerG) * -1;
  if (Acc_Yg >= -1.0 && Acc_Yg <= 1.0) Ydeg = asin(Acc_Yg) * (180.0/PI);
  else Ydeg = 0;

  if (Acc_Z >= 512) Acc_Zg = mVperUnit * (Acc_Z - 512) / mvPerG;
  else Acc_Zg = ((512 - Acc_Z) * (mVperUnit) / mvPerG) * -1;
  Acc_Zg += 1.0;                        // add 1 g back into axis
  if (Acc_Zg >= -1.0 && Acc_Zg <= 1.0) Zdeg = asin(Acc_Zg) * (180.0/PI);
  else Zdeg = 0;
}

void Disp_Vals(){
  Serial.print("milli G's");
  Serial.print("\tX:");
  Serial.print(Acc_Xg * 1000,DEC);
  Serial.print("\tY:");
  Serial.print(Acc_Yg * 1000,DEC);
  Serial.print("\tZ:");
  Serial.println(Acc_Zg * 1000,DEC);

  Serial.print("Degrees  ");
  Serial.print("\tX:");
  Serial.print(Xdeg,DEC);
  Serial.print("\tY:");
  Serial.print(Ydeg,DEC);
  Serial.print("\tZ:");
  Serial.println(Zdeg,DEC);
  Serial.println("");

  if (zeroTo60 > 1 && zeroTo60 < 50){   // only use for zeroTo60 to eliminate noise
    // Serial.print("Sec 0-60: ");
    // Serial.println(zeroTo60,DEC); // zeroTo60 or Xdeg
  }
}



int digitalSmooth(int rawIn, int *sensSmoothArray, bool Reset){
  // modified from: www.arduino.cc/playground/Main/DigitalSmooth
  int j, k, temp, top, bottom;
  long total;
  static int i;
  static int sorted[SAMPLES];
  boolean done;

  if (Reset) {                    // added to reset running as an option
    for (j=0; j<SAMPLES; j++){
      sensSmoothArray[j] = 0;
      sorted[j] = 0;
    }
    i = 0;
    return 0;
  }

  i = (i + 1) % SAMPLES;    // increment counter and roll over if necc. -  % (modulo operator) rolls over variable
  sensSmoothArray[i] = rawIn;                 // input new data into the oldest slot

  for (j=0; j<SAMPLES; j++){     // transfer data array into anther array for sorting and averaging
    sorted[j] = sensSmoothArray[j];
  }

  done = 0;                // flag to know when we're done sorting              
  while(done != 1){        // simple swap sort, sorts numbers from lowest to highest
    done = 1;
    for (j = 0; j < (SAMPLES - 1); j++){
      if (sorted[j] > sorted[j + 1]){     // numbers are out of order - swap
        temp = sorted[j + 1];
        sorted [j+1] =  sorted[j] ;
        sorted [j] = temp;
        done = 0;
      }
    }
  }

  // throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom
  bottom = max(((SAMPLES * 15)  / 100), 1);
  top = min((((SAMPLES * 85) / 100) + 1  ), (SAMPLES - 1));   // the + 1 is to make up for asymmetry caused by integer rounding
  k = 0;
  total = 0;
  for ( j = bottom; j< top; j++){
    total += sorted[j];  // total remaining indices
    k++;
  }
  return total / k;    // divide by number of samples
}

void CalAccel(){ // make 30 iterations, average, and save offset
  //otherwise you get an overflow. But 60 iterations should be fine
  xOffset=0;
  yOffset=0;
  zOffset=0;
  for (int i=1; i <= 30; i++){        
    xOffset += analogRead(X_PIN);    
    yOffset += analogRead(Y_PIN);
    zOffset += analogRead(Z_PIN);
    delay(5);                           // need delay for 200Hz sample rate
  }
  xOffset /=30;                         // get average
  xOffset -= 512;                       // 0g = 512 raw
  yOffset /=30;
  yOffset -= 512;
  zOffset /=30;                         // this also removes the 1g static accel
  zOffset -= 512;                       // added back later
}
« Last Edit: December 11, 2010, 01:11:29 am by BroHogan » Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

Barcelona
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino hurts my brain... but i like it
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

cool....

i'm just waiting for this acelerometer, it will be a big help for me!

can someone confirm me if i can directly put 3,3V on the SL pin to get it waked up every time? i'm a little short with I/O in my future project.
i read it need a resistor, but is it only to limit the maxy current by security or I MUST PUT IT IF I DON'T WANT TO FRY THE BOARD???

regards



Logged

Denver
Offline Offline
God Member
*****
Karma: 19
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

lebenj,
If you are referring to the comment in my example above, you need to know that I am using a MMA7361 board sold by Moderndevices. This breakout board has a 3.3V regulator on it so it can be used as input with a 5V system ( via analogRead w/ ARef @ 3.3V).

If you run your board in a similar way, you have to be careful about setting lines HIGH - since the accel will get 5V when it's running at 3.3V. In that case, you will need a voltage divider or level shifter before the accel.

If you are running your Arduino at 3.3V, then there will be no problem.

I hesitate to give more concrete advice since I don't know what board you are using and how you plan to power it. Assuming you have the Sparkfun version and are going to use the 3.3V from the Arduino, then you definitely need some kind of level shift if you want to set SL HIGH.
Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

Barcelona
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino hurts my brain... but i like it
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks BroHogan,

I'm using sparkfun stuff.... pro mini 328p 3,3V and MMA7361 board.
i was in doubt about taking the main board in 5V or 3,3, because in my project i have a 5V regulated, so it was possible to use any board.
i finally choose the 3,3v because the MMA board i choose was not equipped with the 3,3v regulator...

so normally to keep the MMA waked up i can just put the 3,3V directly on the SL pin, no?

regards
Logged

Denver
Offline Offline
God Member
*****
Karma: 19
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

lebenj,

If you have a 3.3V "Arduino" than you are safe in controlling the sleep pin directly. However, if you simply want "to keep the MMA waked up", you can just add a pullup resistor (~2K) between the SL pin and +3.3V. That way you save a pin - although you can't make it sleep when you want.
Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

Pages: [1] 2   Go Up
Jump to: