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
1 Answer 1
Here's an extract from page 39 of MMA8452Q-rev8.1.pdf, the MMA8452 spec sheet:
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.
-
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.2015年09月28日 23:28:56 +00:00Commented 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.James Waldby - jwpat7– James Waldby - jwpat72015年09月28日 23:32:10 +00:00Commented Sep 28, 2015 at 23:32
Explore related questions
See similar questions with these tags.
setup()
orloop()
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