SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By mprowe
#197181
Hi,

How can I generate a hardware interrupt from the SparkFun Triple Axis Accelerometer Breakout board.
My starting point is the Spakrfun_ADXL345_example.ino which is included in the Arduino library for this product.

This example implies that it demonstrates such a technique - the ADXL345 generates an interrupt on INT1 pin which is then detected by the Arduino and serviced by the ADXL_ISR() routine - once the relevant REMs are removed for the sketch, that is.

However, as this post implies, I can not get this to work. This is the debug testing I have done so far:
Replaced the INT1 input with a switch and added a volatile flag to the ADXL_ISR() routine to test that the Arduinio is detecting and servicing the attachInterrupt(). Which it is.
Scoped the INT1 output pin. No activity.
Read the getInterruptSource() (which the example program does via polling) and interrupt conditions are being met within the ADXL345 chip.

My conclusion so far is that there must be an internal register that the Sparkfun library is not exposing that will enable the internally generated interrupt to be routed to the INT1 pin? Looking at the source, I see several references to "isInerruptEnabled()" that do not seem to be functioning? However my programming skills fall far short of being able to understand all that is happening (or in my case - not happening).

Searching this forum, I see what looks like a similar issue posed back in 2012. But that does not seem to have been concluded with any success?

Best regards, and looking forward to any suggestions, Martin
By paulvha
#197184
Have you removed the REM's also before the line : //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);. This will set the interrupt output to line 1
Otherwise try to make a read of all the registers (using the printAllRegister()) and share them. Especially the 0x2e (enable) and 0x2f (map) are of importance as a start.
By mprowe
#197188
paulvha wrote: Wed Dec 13, 2017 8:28 am Have you removed the REM's also before the line : //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);. This will set the interrupt output to line 1
Yes, I have done that.
Otherwise try to make a read of all the registers (using the printAllRegister()) and share them. Especially the 0x2e (enable) and 0x2f (map) are of importance as a start.
Screenshot attached.
printAllRegister().png
Regards, Martin
You do not have the required permissions to view the files attached to this post.
By paulvha
#197191
nothing weird... that I can see directly.... when you measure on the INT0 / pin 2 is that constant high or low ? If it is high, than an interrupt has been raised, but not cleared yet with reading the right register(s) and hence no new interrupt being raised. Maybe it needs a pull-down/pull-up resistor (e.g. 10K).. but maybe not..
By mprowe
#197192
paulvha wrote: Wed Dec 13, 2017 11:24 am .... when you measure on the INT0 / pin 2 is that constant high or low ? If it is high, than an interrupt has been raised, but not cleared yet with reading the right register(s) and hence no new interrupt being raised. Maybe it needs a pull-down/pull-up resistor (e.g. 10K).. but maybe not..
INT0 / pin2? Are you referring to the breakout pins or the ADXL345 pins? In either case, I am seeing INT1 or INT2 on the board edge and INT1 & INT2 are pins 8 & 9 on the chip.

Pedantry aside, INT1 (at the board edge) is always low and this is my (modified) view of the adxl345 setup routine with a PULLUP on the interrupt pin:
Code: Select all
void setupSF_ADXL()
{
  term.println("SparkFun Aadxl.printAllRegister();DXL345 Accelerometer Hook Up Guide Example");
  adxl.printAllRegister();
  term.println();
  
  adxl.powerOn();                     // Power on the ADXL345

  adxl.setRangeSetting(4);           // Give the range settings
                                      // Accepted values are 2g, 4g, 8g or 16g
                                      // Higher Values = Wider Measurement Range
                                      // Lower Values = Greater Sensitivity

  adxl.setActivityXYZ(1, 0, 0);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setActivityThreshold(75);      // 62.5mg per increment   // Set activity   // Inactivity thresholds (0-255)
 
  adxl.setInactivityXYZ(1, 0, 0);     // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setInactivityThreshold(75);    // 62.5mg per increment   // Set inactivity // Inactivity thresholds (0-255)
  adxl.setTimeInactivity(10);         // How many seconds of no activity is inactive?

  adxl.setTapDetectionOnXYZ(0, 0, 1); // Detect taps in the directions turned ON "adxl.setTapDetectionOnX(X, Y, Z);" (1 == ON, 0 == OFF)
 
  // Set values for what is considered a TAP and what is a DOUBLE TAP (0-255)
  adxl.setTapThreshold(50);           // 62.5 mg per increment
  adxl.setTapDuration(15);            // 625 μs per increment
  adxl.setDoubleTapLatency(80);       // 1.25 ms per increment
  adxl.setDoubleTapWindow(200);       // 1.25 ms per increment
 
  // Set values for what is considered FREE FALL (0-255)
  adxl.setFreeFallThreshold(7);       // (5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(30);       // (20 - 70) recommended - 5ms per increment
 
  // Setting all interupts to take place on INT1 pin
  adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);" 
                                                        // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
                                                        // This library may have a problem using INT2 pin. Default to INT1 pin.
  
  // Turn on Interrupts for each mode (1 == ON, 0 == OFF)
  adxl.InactivityINT(1);
  adxl.ActivityINT(1);
  adxl.FreeFallINT(1);
  adxl.doubleTapINT(1);
  adxl.singleTapINT(1);
  

  //The ADXL345 will generate its interrupts on the ATMega328 pin 14, Arduino 10
  pinMode(ADXL_INT1, INPUT_PULLUP);
  enableInterrupt(ADXL_INT1, SF_ADXL_ISR, RISING); 
}
Duff chip?

Anyway, thanks for the suggestions, Martin
By paulvha
#197193
Here is a thing to try. Maybe NONE of the trigger settings (single tap, double tap etc) might be triggered. According to the data-sheet " The DATA_READY, watermark, and overrun bits enable only the interrupt output". Watermark and overrun are only triggered with the FIFO. According to the picture, in 0x38 the FIFO is bypassed / disabled, so not action from there. I do not see in the sparkfun library a way to set the data_available , but you could include that in the library after : void singleTapINT(bool status); as

void ADXL345:data_availableINT (bool status) {
if(status) {
setInterrupt( ADXL345_INT_DATA_READY_BIT, 1);
}
else {
setInterrupt( ADXL345_INT_DATA_READY_BIT, 0);
}
}
and in the .h file under : void singleTapINT(bool status);
void data_availableINT(bool status);

and make sure to add that call in your ino.... as adxl.data_availableINT(1);

Try to recompile, install and run... Maybe.....
By mprowe
#197202
paulvha wrote: Wed Dec 13, 2017 12:38 pmTry to recompile, install and run... Maybe.....
Hi Paul(?)

WooHoo... That did it.
I have no idea what it is that you have suggested but I have blindly done what you said, And (in general) it seems to have worked for me!! Thanks.

May I prevail on your patience a bit longer and keep this thread going?

Above, I said "in general" it is working. However, I am now noticing that after a while, the interrupt will stop working again. The only way I can get it working again is to power-down. A reset is (to resend the .ino setup instructions to the ADXL345) is not good enough.

Secondly, and this is moving on a bit.
In my project., I am using the ADXL345 to turn Off/On a display. Inactivity to turn off and tap to turn it on again.
However, what I am seeing is: The inactivity interrupt is firing after 10sec (adxl.setTimeInactivity(10);) and a tap will turn the display back on.
But it seems that the tap is not "seen" as activity? Therefor not resetting the Inactivity timer. Meaning that the Inactivity Interrupt fires at random times between 0 & 10 sec after a Tap?

Any thought on how to address this problem?

Regards, Martin
By paulvha
#197203
HI Martin, that is good progress. So we now know the hardware is working.. but it is challenging our knowledge.

What we did is adding another trigger for the interrupt (data available), while the data-sheet states it is set by default ?. For the data_available trigger (and thus interrupt) to be cleared we MUST read , next toe INT SOURCE (register 0x30) the DataX, Data,Y, DATAZ registers. (registers address 0x32 to Address 0x37, according to the data sheet) So you have to add that in the interrupt routine as it is in the loop. If that is already happening.. try to lower the baudrate of the bus (i2C or SPI) which ever you are using. It is really not the first time I see a chip getting lost on the highest speed.

AND/OR..

remove setting the data_availability trigger and try to force the other triggers to do an interrupt by lowering the different threshold values that are set in the earlier lines (or just tap it harder... :-)) . The issue with activity and inactivity might be solved in the same manner. Lowering the thresholds (instead of 75 maybe them 10). They then might be to sensitive... but that is matter of trial and error to find the right value


regards.
Paul