0

I'm trying to get MMA8452Q to trigger an interrupt when motion is detected and wonder if I'm missing something very obvious here.

So I setup CTRL_REG4 to 0x0B with

void MMA8452Q::setupISR()
{
    writeRegister(CTRL_REG4, 0x0B);
}

then I setup FF_MT with

void MMA8452Q::setupFF_MT()
{
    writeRegister(FF_MT_CFG, 0xF8);
    writeRegister(FF_MT_THS, 0x0F);
    writeRegister(FF_MT_COUNT, 0x00);
}

and I read ISR with

#define SRC_PULSE 2
#define SRC_FF_MT 1

byte MMA8452Q::readISR()
{
    byte intStat = readRegister(INT_SOURCE);

    if (intStat & 0x0B)
    {
        readRegister(FF_MT_SRC);
        return intStat & 0x0B;
    }
    else
        return 0;
}

void printISR()
{
  byte isr = (accel.readISR() >> 2);
  if (isr & SRC_PULSE)
    Serial.print("(ISR) Tap");
  else
    Serial.print("(ISR) No Tap");

  Serial.print("\t");

  if (isr & SRC_FF_MT)
    Serial.print("(ISR) Motion");
  else
    Serial.print("(ISR) No Motion");

  Serial.print("\t");
}

AFAIK, that should already have FF/MT interrupt enabled. Even when I'm getting readings in FF_MT_SRC, I'm not picking up an interrupt in INT_SOURCE.

Interrupts are fired on (most) taps, but not on motion at all.

Am I missing something here?

Thanks

4
  • Please post all your code. Do not do serial prints inside an ISR. Read: Interrupts
    – Nick Gammon
    Sep 28, 2015 at 7:39
  • @NickGammon I've updated my post with the full code now. Re. serial prints, am I doing serial prints inside an ISR? I read the ISR first and then print. The ISR would have finished processing - right?
    – Kar
    Sep 28, 2015 at 8:36
  • Kar, I may have missed something, but in what you've posted I don't see any setup() or loop() routines as often found in Arduino sketches. Without that code it isn't clear what routines are being called when. Also, you haven't shown how the MMA8452Q is connected to your Uno. Is an interrupt wire from the 8452 connected to the Uno? Absent other info, it looks like MMA8452Q::readISR() is not an interrupt processing routine, but instead a routine that polls an interrupt-source register to find out what source would have triggered an interrupt if correctly wired and initialized Sep 28, 2015 at 16:45
  • Kar, re setup() & loop(), I'd overlooked a block of code. Sep 28, 2015 at 23:15

1 Answer 1

0

Here's an extract from page 39 of MMA8452Q-rev8.1.pdf, the MMA8452 spec sheet:

interrupt enable bits

Rather than saying writeRegister(CTRL_REG4, 0x0B); in MMA8452Q::setupISR(), try writeRegister(CTRL_REG4, 0xD);.

0xB is 1011 in binary, while 0xD is 1101, which turns on INT_EN_FF_MT to enable freefall/motion interrupts.

The above should answer your question as asked. The following expands on my earlier comment which said

Absent other info, it looks like MMA8452Q::readISR() is not an interrupt processing routine, but instead a routine that polls an interrupt-source register to find out what source would have triggered an interrupt if correctly wired and initialized.

"Interrupt" as used in your question (and code) refers to when the MMA8452 signals (via an I1 or I2 output line) that an interrupt-worthy condition has occurred.

"Interrupt" as in the question does not refer to an interrupt from the Uno's point of view, because (per diagram) neither of I1 or I2 connects to the Uno.

If speed of response becomes important, you may wish to hook I1 or I2 to one of the Uno's Digital Pins With Interrupts, ie pin 2 or 3, as noted in the AttachInterrupt page at arduino.cc. Then you'd replace the polling loop that now periodically reads the MMA8452's ISR (interrupt status register) to check for set bits, with an interrupt service routine which would set a flag to cause loop() to use Wire.read to get ISR data.

2
  • Ah yes, I was about to say something to this effect. Your code does not actually use interrupts, so I am not surprised it is missing things. Your terminology of "reading the ISR" was confusing. The chip appears to actually generate interrupts, which you should connect to a pin as jwpat7 suggested.
    – Nick Gammon
    Sep 28, 2015 at 23:28
  • Kar -- note that if your Uno's V+ is 5V, use a Logic Level Converter between it and the MMA8452. Sparkfun's BOB-12009 is bidirectional if the i/o's it connects are implemented with open-collector/open drain. Sep 28, 2015 at 23:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.