LocoMotion: MMA8453 with Interrupts…

In the previous post about the MMA8453_N0m1 library we talked about how to get the stream of raw XYZ data back from the accelerometer.  In this post we will be getting into some of the more advanced features of the MMA8453.

The two advanced features that the MMA8453_N0m1 library breaks out for easier use are the interrupt motion detection, and the interrupt shake detection.  Now motion and shake sound like the same things, but in fact they are slightly different.  What motion detection does is allows you to detect any type of motion above a certain force threshold.  While shake is more specific and allows for only detecting sharp fast motion, by using a highpass filter to remove gentler smoother rolling motions.  The library includes 1 example for each feature.  However the way the library is designed, the two features are used in a very similar manner so we will only cover one here.

So lets assume you have the library and circuit still setup from the previous post on the MMA8453_N0m1 lib.  The example we will be explaining is the shake example, because its ever so slightly more complex than the motion.  Though really its almost identical.  After making the library object just as before, the first thing you will do is initialize the library in the arduino setup() function, with the following function call:

accel.shakeMode(32,true,true,true,false,2);

So the first parameter in this function, which is currently set at “32”  the shake detection acceleration force threshold, which is a value between 0-127.  This value is calculated through a simple formula as follows.  The gravitational threshold you desire divided by 0.063.  So for example in the above line we do this: 2g/ 0.063g = 31.746, and since the parameter is an int, lets round that value to 32.

The next 3 parameters are just enabling each axis for shake detection; listed X, Y, Z.  So if your project only needs to detect a shaking motion over 1 axis you can disable the others.

The second last parameter is a boolean to enable one of the INT pins on the MMA8453. So, to put it simply, True = pin 2, False = pin1.

The last parameter is to set the Arduino interrupt pin number.  In this example we are setting it to pin 2.  However you could set this to any interrupt pin you have available.  Included in the example folder is an example that uses pin change interrupt to use a non standard interrupt pin.  After that you are pretty much done.  There are just a few simple lines left to add:

accel.update();

  if(accel.shake())
  {

    if(accel.shakeAxisX()) //X
    {
      Serial.println("Shake X");
    }
  }

You must call the update function at the top of the loop().  The shake function returns true or false if shake is detected, and the shakeAxisX(), shakeAxisY(), shakeAxisZ() functions will return true if a particular axis is shaken. That’s all there is to it!  The motion functions are almost identical except it will only return whether or not there is motion, not which axis is in motion.  Well I tried to make it more complex, then the previous post.  That formula had you sweating, didn’t it?

5 Responses to “LocoMotion: MMA8453 with Interrupts…

  • Hi! Do you know any breakout board for MMA8453?

  • Hi,
    Could you roughly say why motion and shake modes don’t work when data mode works well at my board with accelerometer MMA8453Q with your library?

    Thanks!

  • Well, I can’t see your wiring setup. However if data is working and motion/shake are not. I would say you don’t have the interrupt wired correctly. Double check that the interrupt wire is going to an interrupt pin on the arduino. Or use the pinchangeINT library. Goodluck!

  • Hi,
    I realy like this library. In the next couple of weeks I’m going to try to make the orientation part of the chip working. This library can be extended to all the features of the MMA8453/2/1 chips. I will fork the git.
    Thx for al the nice work you already put into it.

  • I’ll admit from the start that I’m out of my depth, but I’m trying to wake an Arduino from deep sleep using a MMA8452Q on the SparkFun breakout board.

    I can get the module to interrupt the Arduino and rouse it, but I cannot seem to be able to get the MMA8452Q to ‘unlatch’ its interrupt output from the LOW state.

    From what I understand from the REASDME file, issuing “accel.update();” should perform the reset, but wherever I put it, the output stays latched.

    Can you help me, this is driving me nuts?!?!

    The code below shows ‘remmed out’ attempts to perform the reset at various points:

    #include

    #include
    #include

    MMA8453_n0m1 accel;

    const int ledPin = 9;
    const int inputPin = 2;
    boolean flagRun = false;

    volatile boolean flag;

    void setup()
    {
    delay(100);

    Serial.begin(9600);
    accel.setI2CAddr(0x1D); //change your device address if necessary, default is 0x1C
    /*
    threshold [0-127] formula: 0.5g/ 0.063g = 7.9 counts, round to 8 counts ,
    enable X,
    enable Y,
    enable Z,
    enable MMA8453Q INT pin 2 (false= pin 1),
    arduino INT pin number
    */
    accel.motionMode(16,true,true,true,false,2);
    // ** anything less than 16 (1g) gives constant trigger **

    Serial.println(“MMA8453_n0m1 library”);
    Serial.println(“Motion Example”);
    Serial.println(“n0m1.com”);

    pinMode(ledPin, OUTPUT);
    pinMode(inputPin, INPUT_PULLUP);
    // Does not reset once triggered accel.update();
    goToSleep();

    }

    void loop()
    {
    // Does not reset once triggered accel.update();
    if (flag)
    {
    doSomething();
    flag = false;

    // Does not reset once triggered accel.update();
    goToSleep();
    }
    }

    void setFlag()
    {
    flag = true;
    // Does not reset once triggered accel.update();
    }

    void goToSleep()
    {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    attachInterrupt(0, setFlag, LOW); // pin D2
    // Does not reset once triggered accel.update();
    sleep_mode(); // sleep now
    // Now asleep until LOW interrupt, then..
    sleep_disable();
    detachInterrupt(0);
    // Does not reset once triggered accel.update();
    }

    void doSomething()
    {
    // Does not reset once triggered accel.update();
    for (int i = 0; i < 5; i++)
    {
    digitalWrite(ledPin, HIGH);
    delay(200);
    digitalWrite(ledPin, LOW);
    delay(200);
    }
    // Does not reset once triggered accel.update();
    }

Leave a Reply

Your email address will not be published. Required fields are marked *